DEV Community

Cheryl M
Cheryl M

Posted on • Originally published at cherylm.hashnode.dev on

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

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

codesandbox: https://codesandbox.io/p/github/cherylli/devto-api-nextjs/main

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].(https://developers.forem.com/api)

The endpoint to retrieve all posts from a user ishttps://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 https://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
        },
      }
}

Enter fullscreen mode Exit fullscreen mode

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>)
}

Enter fullscreen mode Exit fullscreen mode

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>

Enter fullscreen mode Exit fullscreen mode

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',
    };
}

Enter fullscreen mode Exit fullscreen mode

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
    };
};

Enter fullscreen mode Exit fullscreen mode

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>
    );
};

Enter fullscreen mode Exit fullscreen mode

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)

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.

Top comments (0)