Building a blog with Next.js and Markdown allows you to create a fast, SEO-friendly site with a simple content management system. In this guide, we’ll walk you through setting up a Next.js project, integrating Markdown for content, and creating a blog website with dynamic routes and posts. By the end, you’ll have a fully functional blog that showcases Markdown posts.
1. Setting Up Your Next.js Project
1.1. Create a New Next.js Project
Start by setting up a new Next.js project using create-next-app
.
npx create-next-app@latest my-blog
cd my-blog
1.2. Install Dependencies
You’ll need gray-matter
to parse front matter in Markdown files and remark
for processing Markdown.
npm install gray-matter remark remark-html
2. Adding Markdown Support
2.1. Create a Directory for Markdown Files
Create a folder named posts
in the root directory of your project. This folder will contain your Markdown files.
mkdir posts
2.2. Add Sample Markdown Files
Create a sample Markdown file in the posts
directory:
// posts/first-post.md
---
title: "My First Post"
date: "2024-09-01"
---
This is the content of my first post. Markdown allows you to **format** text, add [links](https://example.com), and more.
3. Parsing Markdown Files
3.1. Create a Utility Function to Load Posts
Create a lib
directory and add a posts.js
file to handle loading and parsing Markdown files.
// lib/posts.js
import fs from 'fs';
import path from 'path';
import matter from 'gray-matter';
const postsDirectory = path.join(process.cwd(), 'posts');
export function getSortedPostsData() {
const fileNames = fs.readdirSync(postsDirectory);
const allPostsData = fileNames.map(fileName => {
const id = fileName.replace(/\.md$/, '');
const fullPath = path.join(postsDirectory, fileName);
const fileContents = fs.readFileSync(fullPath, 'utf8');
const matterResult = matter(fileContents);
return {
id,
...matterResult.data,
};
});
return allPostsData.sort((a, b) => (a.date < b.date ? 1 : -1));
}
export function getPostData(id) {
const fullPath = path.join(postsDirectory, `${id}.md`);
const fileContents = fs.readFileSync(fullPath, 'utf8');
const matterResult = matter(fileContents);
return {
id,
...matterResult.data,
content: matterResult.content,
};
}
4. Building Pages and Components
4.1. Create the Home Page
Edit pages/index.js
to display a list of blog posts.
// pages/index.js
import Link from 'next/link';
import { getSortedPostsData } from '../lib/posts';
export default function Home({ allPostsData }) {
return (
<div>
<h1>My Blog</h1>
<ul>
{allPostsData.map(({ id, title, date }) => (
<li key={id}>
<Link href={`/posts/${id}`}>
<a>{title}</a>
</Link>
<br />
<small>{date}</small>
</li>
))}
</ul>
</div>
);
}
export async function getStaticProps() {
const allPostsData = getSortedPostsData();
return {
props: {
allPostsData,
},
};
}
4.2. Create Dynamic Post Pages
Add a [id].js
file in the pages/posts
directory for dynamic routes.
// pages/posts/[id].js
import { getAllPostIds, getPostData } from '../../lib/posts';
export default function Post({ postData }) {
return (
<div>
<h1>{postData.title}</h1>
<div dangerouslySetInnerHTML={{ __html: postData.contentHtml }} />
</div>
);
}
export async function getStaticPaths() {
const paths = getAllPostIds();
return {
paths,
fallback: false,
};
}
export async function getStaticProps({ params }) {
const postData = getPostData(params.id);
return {
props: {
postData,
},
};
}
4.3. Process Markdown Content
Modify lib/posts.js
to include Markdown processing.
import remark from 'remark';
import remarkHtml from 'remark-html';
export async function getPostData(id) {
const fullPath = path.join(postsDirectory, `${id}.md`);
const fileContents = fs.readFileSync(fullPath, 'utf8');
const matterResult = matter(fileContents);
const processedContent = await remark().use(remarkHtml).process(matterResult.content);
const contentHtml = processedContent.toString();
return {
id,
contentHtml,
...matterResult.data,
};
}
5. Styling Your Blog
5.1. Add Global Styles
Create a styles/globals.css
file to include global styles.
/* styles/globals.css */
body {
font-family: Arial, sans-serif;
line-height: 1.6;
}
a {
color: #0070f3;
}
a:hover {
text-decoration: underline;
}
Import this CSS file in _app.js
.
// pages/_app.js
import '../styles/globals.css';
function MyApp({ Component, pageProps }) {
return <Component {...pageProps} />;
}
export default MyApp;
6. Conclusion
In this guide, you learned how to build a simple blog with Next.js and Markdown. You set up a Next.js project, integrated Markdown for content, and created dynamic routes for blog posts. You also learned how to style your blog and process Markdown content for display.
About Muhaymin Bin Mehmood
Front-end Developer skilled in the MERN stack, experienced in web and mobile development. Proficient in React.js, Node.js, and Express.js, with a focus on client interactions, sales support, and high-performance applications.