Displaying Dev.to Articles on your Website using Next.js

·

3 min read

Github: github.com/cherylli/devto-api-nextjs

codesandbox: codesandbox.io/p/github/cherylli/devto-api-..

We will create a basic app to pull articles from dev.to API, using next.js static site generation (SSG) and display the article when clicked into it.

Dev.to API documentation can be found here (developers.forem.com/api).

The endpoint to retrieve all posts from a user is https://dev.to/api/articles?username={username}

where the username can be a personal account or an organisation account name.

For example, the api endpoint to fetch all my articles is dev.to/api/articles?username=cherylli

the result looks like this,

Image description

Using SSG, we fetch all the posts in getStaticProps(),

//pages/index.js 
export async function getStaticProps(){ 
  const res = await fetch('https://dev.to/api/articles?username=cherylli') 
  const posts = await res.json()
  return{ 
    props:{ posts }
  } 
}

Props will be generate on build, passing the props into the page component, and display them on the page

//pages/index.js
const Home = ({posts}) => {
    return (
        <main className={styles.container}>
            <h1>
                Dev.to Blog
            </h1>
            <p>
                displaying dev.to blog posts using the Dev.to API
            </p>
            <div className={styles.grid}>
                {posts.map((post) => (
                    <BlogPostCard post={post} key={post.id}/>
                ))}
            </div>
        </main>)
}

Index page

Single Article page

The article body is not included in the above endpoint. So we will need to use another endpoint to get the article content.

If a user also publishes to an organization, https://dev.to/api/articles?username={username} returns all articles (including any articles published to an organization by the user). We will then need to specify username or organization when using the single article endpoint https://dev.to/api/articles/{username/organization}/{slug}.

For example, this gets the article I published to the organization 'wdp'.

https://dev.to/api/articles/wdp/using-google-fonts-with-nextjs-typescript-4pba

If the user do not publish to an organization account, or we only want to retrieve articles published to an organization account using slug would be enough, as {username} can just be defaulted to the user or organisation name.

Clicking on the title in the card will navigate to post/{user}/{slug} using next.js dynamic routes

Image description

<Link href={`posts${post.path}`}>{post.title}</Link>

Since this is a dynamic route, we will also need getStaticPaths()

//pages/posts/[user]/[slug].js
export async function getStaticPaths() {
    const res = await fetch(`https://dev.to/api/articles?username=cherylli`);
    const posts = await res.json()

    return {
        paths: posts.map(post => ({
            params: {
                user: post.path.split('/')[0],
                slug: post.slug
            }
        })),
        fallback: 'blocking',
    };
}

it fetches all my articles and returns user, and slug params, since I blog on both my personal and an organization account, the user param will vary based on where I published the article.

We can use these params in getStaticProps() to retrieve the single article,

//pages/posts/[user]/[slug].js
export const getStaticProps = async ({params}) => {
    const res = await fetch(`https://dev.to/api/articles/${params.user}/${params.slug}`);
    const post = await res.json()

    return {
        props: {
            post
        },
        revalidate: 30
    };
};

Now post can be passed into the page component, and post.body_html is the body of the post in html.

//pages/posts/[user]/[slug].js
const BlogPage = ({post}) => {
    return (
        <div className={styles.container}>
            // add content using the post props, and style the page
            <div dangerouslySetInnerHTML={{ __html: post.body_html }} />

        </div>
    );
};

Single Page

Notes

Using ID instead of Slug

We can also use the article id instead of slug, the endpoint would be https://dev.to/api/articles/{articleId}. This simplifies the code since we do not have to worry about whether the article is published to a personal account or an organization account. The single article page url would be /posts/{id} instead.

Using [Incremental Static Generation (ISR)] (nextjs.org/docs/basic-features/data-fetchin..)

Since SSG generates the pages on build time, newly published articles won't be added to the index page without a re-build. ISR can be used to create/update static pages after the site is built.