Part 20: Creating a Dynamic Blog with Next.js
[Pages] Loading Data

In this blog post, we'll explore how to expand your Next.js application to handle multiple blog posts using Markdown files and dynamic routes. If you've been following along, you already have a basic setup that displays a single post. Now, let's see how we can efficiently scale this to accommodate multiple posts without duplicating code.
Adding a New Post
First, let's add a new Markdown file for our second blog post:
// content/posts/second-post.md
---
date: "2021-04-22"
title: "Second Post"
---
This is my second post, written in Markdown.With the new post in place, our goal is to display it using the same page component we use for the first post.
Refactoring the Page Component
Instead of creating a separate page component for each post, we can use a single component to handle multiple posts. We'll rename our existing component to PostPage and leverage Next.js's dynamic routing capabilities.
// pages/posts/[slug].js
import Head from 'next/head';
import { getPost } from '../../lib/posts';
export async function getStaticPaths() {
return {
paths: [
{ params: { slug: 'first-post' } },
{ params: { slug: 'second-post' } },
],
fallback: false,
};
}
export async function getStaticProps({ params: { slug } }) {
console.log('[PostPage] getStaticProps():', slug);
const post = await getPost(slug);
return {
props: { post },
};
}
function PostPage({ post }) {
console.log('[PostPage] render:', post);
return (
<>
<Head>
<title>{`${post.title} - My Blog`}</title>
</Head>
<main>
<p>{post.date}</p>
<h1>{post.title}</h1>
<article dangerouslySetInnerHTML={{ __html: post.body }} />
</main>
</>
);
}
export default PostPage;Dynamic Routes with Next.js
The page file pages/posts/[slug].js uses a dynamic segment [slug] to match any URL under /posts/. This means URLs like /posts/first-post or /posts/second-post will both render using the PostPage component.
Implementing getStaticPaths
getStaticPathsThe getStaticPaths function defines which paths are valid for the dynamic route. It returns an array of paths, each with a params object that includes the slug.
export async function getStaticPaths() {
return {
paths: [
{ params: { slug: 'first-post' } },
{ params: { slug: 'second-post' } },
],
fallback: false,
};
}Setting fallback: false ensures that any path not returned by getStaticPaths will result in a 404 page.
Using getStaticProps
getStaticPropsIn getStaticProps, we use the slug parameter from the context to load the corresponding Markdown file:
export async function getStaticProps({ params: { slug } }) {
console.log('[PostPage] getStaticProps():', slug);
const post = await getPost(slug);
return {
props: { post },
};
}This dynamic loading allows us to serve different content based on the URL.
Testing the Setup
With these changes, visiting /posts/first-post should display the first post, while /posts/second-post should display the second. Both routes use the same PostPage component, making the codebase more efficient and maintainable.
Conclusion
By using dynamic routes in Next.js, we can efficiently handle multiple blog posts without duplicating code. This approach not only simplifies the codebase but also makes it easier to add new posts in the future. As you continue building your blog, consider how dynamic routing can be leveraged for other types of content or features.
Last updated