Table of Contents
Next.js is a powerful framework for building static and server-rendered applications with React. In this guide, we will create a simple blog template using Next.js. This includes setting up the project, creating pages and components, and adding Markdown support for writing posts.
Prerequisites
Before we start, ensure you have the following installed:
- Node.js
- npm or yarn
Steps for Creating a Blog with Next.js
Step 1: Setting Up the Next.js Project
First, create a new Next.js project:
npx create-next-app my-nextjs-blog # or yarn create next-app my-nextjs-blog
Navigate to your project directory:
cd my-nextjs-blog
Step 2: Installing Dependencies
We need to install some additional dependencies to manage Markdown and styles:
npm install gray-matter remark remark-html # or yarn add gray-matter remark remark-html
Step 3: Creating the Blog Structure
Create a posts directory in the root of your project to store your Markdown files:
mkdir posts
Add a sample Markdown file, hello-world.md, in the posts directory:
--- title: 'Hello World' date: '2024-06-08' --- This is my first blog post using Next.js!
Step 4: Fetching Blog Posts
Create a utility function to fetch and parse the blog posts. Create a file lib/posts.js:
// 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) => { return new Date(b.date) - new Date(a.date); }); }
Step 5: Creating the Blog Index Page
Create an index page to list all the blog posts. Modify pages/index.js:
// pages/index.js import { getSortedPostsData } from '../lib/posts'; export async function getStaticProps() { const allPostsData = getSortedPostsData(); return { props: { allPostsData, }, }; } export default function Home({ allPostsData }) { return ( <div> <h1>My Blog</h1> <ul> {allPostsData.map(({ id, title, date }) => ( <li key={id}> <a href={`/posts/${id}`}>{title}</a> <br /> <small>{date}</small> </li> ))} </ul> </div> ); }
Step 6: Creating the Post Page
Create a dynamic route for individual blog posts. Create a file pages/posts/[id].js:
// pages/posts/[id].js import { useRouter } from 'next/router'; import { getAllPostIds, getPostData } from '../../lib/posts'; import Head from 'next/head'; import ReactMarkdown from 'react-markdown'; export async function getStaticProps({ params }) { const postData = await getPostData(params.id); return { props: { postData, }, }; } export async function getStaticPaths() { const paths = getAllPostIds(); return { paths, fallback: false, }; } export default function Post({ postData }) { return ( <div> <Head> <title>{postData.title}</title> </Head> <article> <h1>{postData.title}</h1> <div>{postData.date}</div> <ReactMarkdown>{postData.content}</ReactMarkdown> </article> </div> ); }
Step 7: Fetching Post Data
Update lib/posts.js to include functions for fetching individual post data and generating paths:
// lib/posts.js import fs from 'fs'; import path from 'path'; import matter from 'gray-matter'; import { remark } from 'remark'; import html from 'remark-html'; 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) => { return new Date(b.date) - new Date(a.date); }); } export function getAllPostIds() { const fileNames = fs.readdirSync(postsDirectory); return fileNames.map(fileName => { return { params: { id: fileName.replace(/\.md$/, ''), }, }; }); } 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(html) .process(matterResult.content); const contentHtml = processedContent.toString(); return { id, content: contentHtml, ...matterResult.data, }; }
Conclusion
In this guide, we created a basic blog template using Next.js. We set up the project, created a structure for our blog posts, and added support for Markdown. This setup provides a strong foundation for building and customizing your own blog with Next.js.
For more updates on programming trends and tutorials, visit blogsea.net regularly.
Creating a Blog with Next.js – FAQs
Markdown is easy to write and read, making it ideal for content creation.
Use npx create-next-app my-nextjs-blog or yarn create next-app my-nextjs-blog.
Implement the getStaticPaths function to generate paths for each post.
Use the getPostData function to read and parse Markdown files for each post.
Yes, you can customize the layout by modifying the pages and component files.
Yes, you can use plugins like remark-prism to add syntax highlighting to code blocks in Markdown.