DEV Community

Rajesh Kumar Yadav
Rajesh Kumar Yadav Subscriber

Posted on

Fetching Blog Posts in Next.js Using the DEV.to API

If you're looking to showcase your DEV.to blog posts on your Next.js website, you're in luck! DEV.to provides an easy-to-use API that lets you fetch your blog posts programmatically. In this guide, I'll show you how to integrate DEV.to's API into your Next.js application and dynamically display your blog content.

Let's dive in!

1. Setting Up the Next.js Project

First, if you haven't already, set up a new Next.js project by running:

npx create-next-app@latest my-dev-blog
cd my-dev-blog
Enter fullscreen mode Exit fullscreen mode

Now that we have our Next.js app ready, let's move on to fetching our blog posts.

2. Fetching Blog Posts from DEV.to API

The DEV.to API provides access to your published articles through a simple HTTP request. You can fetch articles by user by hitting the endpoint:

https://dev.to/api/articles?username=yourusername
Enter fullscreen mode Exit fullscreen mode

To fetch the blog posts in your Next.js app, we'll use the SWR library. SWR is a popular data fetching library designed to make it easy to fetch, cache, and update data in your React/Next.js applications.

Install SWR:

npm install swr
Enter fullscreen mode Exit fullscreen mode

Now, let's create a utility function to handle the API request:

// src/lib/fetcher.ts
export default async function fetcher(url: string) {
  const response = await fetch(url);
  if (!response.ok) {
    throw new Error("Failed to fetch data");
  }
  return response.json();
}
Enter fullscreen mode Exit fullscreen mode

3. Creating the Blog Page

Now that we have the fetcher utility, let's create a blog page that will display your DEV.to posts.

In pages/blog/index.tsx, fetch and display the blog posts using SWR:

import { Container, Row, Col, Card, Button, Badge } from 'react-bootstrap';
import Head from 'next/head';
import useSWR from 'swr';
import fetcher from '../../lib/fetcher';
import Link from 'next/link';
import { formatDistanceToNow, parseISO } from 'date-fns';

interface BlogPost {
  id: number;
  title: string;
  description: string;
  slug: string;
  cover_image: string;
  tag_list: string[];
  reading_time_minutes: number;
  published_timestamp: string;
  positive_reactions_count: number;
}

const Blog = () => {
  const { data, error } = useSWR<BlogPost[]>('https://dev.to/api/articles?username=yourusername', fetcher);

  if (error) return <div>Failed to load posts</div>;
  if (!data) return <div>Loading...</div>;

  return (
    <>
      <Head>
        <title>Blog | Your Name</title>
      </Head>
      <Container>
        <Row>
          <Col>
            <h1>Blog</h1>
            <Row className="g-4">
              {data.map((post: BlogPost) => (
                <Col md={4} key={post.id}>
                  <Card className="blog-card" data-aos="fade-up">
                    <Card.Body>
                      <Card.Title>{post.title.length > 50 ? `${post.title.substring(0, 50)}...` : post.title}</Card.Title>
                      <Card.Text>{post.description}</Card.Text>
                      <div className="mb-2">
                        {post.tag_list.map((tag: string) => (
                          <Badge pill bg="secondary" className="me-1" key={tag}>
                            {tag}
                          </Badge>
                        ))}
                      </div>
                      <div className="text-muted">
                        <small><i className="fa-solid fa-clock"></i> {post.reading_time_minutes} min read</small><br/>
                        <small><i className="fa-solid fa-calendar-day"></i> {formatDistanceToNow(parseISO(post.published_timestamp), { addSuffix: true })}</small><br/>
                        <small><i className="fa-solid fa-thumbs-up"></i> {post.positive_reactions_count} Likes</small>
                      </div>
                      <Link href={`/blog/${post.slug}`} passHref>
                        <Button variant="outline-primary" className="mt-3">Read More</Button>
                      </Link>
                    </Card.Body>
                  </Card>
                </Col>
              ))}
            </Row>
          </Col>
        </Row>
      </Container>
    </>
  );
};

export default Blog;
Enter fullscreen mode Exit fullscreen mode

4. Adding Dynamic Blog Pages

Next.js provides dynamic routes that allow you to generate individual pages for each blog post. Let's create a dynamic route to display each post.

Create a file called pages/blog/[slug].tsx:

import { useRouter } from 'next/router';
import useSWR from 'swr';
import { Container, Row, Col, Card, Button } from 'react-bootstrap';
import Head from 'next/head';
import Image from "next/image";
import fetcher from '../../lib/fetcher';

const BlogPost = () => {
  const router = useRouter();
  const { slug } = router.query;

  const { data, error } = useSWR(slug ? `https://dev.to/api/articles/yourusername/${slug}` : null, fetcher);

  if (error) return <div>Failed to load the post</div>;
  if (!data) return <div>Loading...</div>;

  return (
    <>
      <Head>
        <title>{data.title} | Your Name</title>
      </Head>
      <Container>
        <Row>
          <Col>
            <div className="section-title">
              <h1>{data.title}</h1>
              <p>{data.readable_publish_date}</p>
            </div>
            <section>
              {data.cover_image && (
                <Image
                  src={data.cover_image}
                  alt={data.title}
                  className="img-fluid mb-3"
                  width={1000}
                  height={420}
                  layout="responsive"
                />
              )}
              <div dangerouslySetInnerHTML={{ __html: data.body_html }} />
            </section>
            <Button variant="outline-dark" href="/blog">
              Back to Blog
            </Button>
          </Col>
        </Row>
      </Container>
    </>
  );
};

export default BlogPost;
Enter fullscreen mode Exit fullscreen mode

This page fetches individual posts using the slug from the URL and renders them with HTML content safely using dangerouslySetInnerHTML.

5. Final Touches

You can now start your Next.js app by running:

npm run dev
Enter fullscreen mode Exit fullscreen mode

Visit the /blog route, and you should see your DEV.to blog posts displayed. Clicking on any post will take you to the individual blog post page.

  1. Conclusion In this tutorial, we learned how to fetch and display blog posts from the DEV.to API in a Next.js app. This is a powerful way to integrate your DEV.to content into your personal website while leveraging the benefits of static site generation and client-side rendering.

Feel free to customize this setup further, add pagination, or improve styling to match your site’s design!

Let me know in the comments if you have any questions or suggestions.

Top comments (0)