main_logo
herohero
How to Build a Blog Using Next.js and Markdown

How to Build a Blog Using Next.js and Markdown

22-12-2024

Creating a blog with Next.js and Markdown is an excellent way to combine the simplicity of static content with the power of a modern React framework. In this tutorial, we'll walk through building a fully functional blog using Next.js and Markdown files as the content source.

Why Use Markdown with Next.js?

Markdown is a lightweight markup language that's easy to write and read. It simplifies content management by allowing you to write posts in plain text files. By pairing it with Next.js, you can:

Prerequisites

Before starting, ensure you have the following installed:

Step 1: Set Up a New Next.js Project

  1. Open your terminal and create a new Next.js application:

    npx create-next-app@latest my-blog
    cd my-blog
    
  2. Start the development server:

    npm run dev
    

    Your project should now be running at http://localhost:3000.

Step 2: Install Required Packages

Install dependencies for handling Markdown files and parsing them:

npm install gray-matter remark remark-html

Step 3: Organize the Project Structure

Create a folder structure to organize your Markdown files and components:

my-blog/
├── posts/        # Markdown files for blog posts
├── pages/
│   ├── index.js  # Homepage
│   └── [slug].js # Dynamic blog post pages
└── components/
    └── Layout.js # Reusable layout component

Add Sample Markdown Files

Create a posts folder in the root of your project and add some sample Markdown files:

posts/first-post.md:

---
title: "First Post"
date: "2024-07-01"
---

This is my first blog post written in Markdown!

posts/second-post.md:

---
title: "Second Post"
date: "2024-07-02"
---

Welcome to my second blog post. Markdown is awesome!

Step 4: Create a Layout Component

A Layout component ensures consistency across pages:

components/Layout.js:

export default function Layout({ children }) {
  return (
    <div style={{ maxWidth: "800px", margin: "0 auto", padding: "20px" }}>
      <header>
        <h1>My Blog</h1>
      </header>
      <main>{children}</main>
      <footer>
        <p>&copy; 2024 My Blog</p>
      </footer>
    </div>
  );
}

Step 5: Display Blog Posts on the Homepage

Fetch the list of Markdown files and display their metadata on the homepage.

pages/index.js:

import fs from 'fs';
import path from 'path';
import matter from 'gray-matter';
import Link from 'next/link';

export default function Home({ posts }) {
  return (
    <div>
      <h2>Blog Posts</h2>
      <ul>
        {posts.map((post) => (
          <li key={post.slug}>
            <Link href={`/${post.slug}`}>
              <a>{post.title}</a>
            </Link>
            <p>{post.date}</p>
          </li>
        ))}
      </ul>
    </div>
  );
}

export async function getStaticProps() {
  const postsDirectory = path.join(process.cwd(), 'posts');
  const filenames = fs.readdirSync(postsDirectory);

  const posts = filenames.map((filename) => {
    const filePath = path.join(postsDirectory, filename);
    const fileContents = fs.readFileSync(filePath, 'utf8');
    const { data } = matter(fileContents);

    return {
      slug: filename.replace(/\.md$/, ''),
      ...data,
    };
  });

  return {
    props: {
      posts,
    },
  };
}

Step 6: Create Dynamic Blog Post Pages

Use dynamic routes to generate pages for each Markdown file.

pages/[slug].js:

import fs from 'fs';
import path from 'path';
import matter from 'gray-matter';
import { remark } from 'remark';
import html from 'remark-html';
import Layout from '../components/Layout';

export default function Post({ post }) {
  return (
    <Layout>
      <h1>{post.title}</h1>
      <p>{post.date}</p>
      <div dangerouslySetInnerHTML={{ __html: post.content }} />
    </Layout>
  );
}

export async function getStaticPaths() {
  const postsDirectory = path.join(process.cwd(), 'posts');
  const filenames = fs.readdirSync(postsDirectory);

  const paths = filenames.map((filename) => ({
    params: { slug: filename.replace(/\.md$/, '') },
  }));

  return {
    paths,
    fallback: false,
  };
}

export async function getStaticProps({ params }) {
  const postsDirectory = path.join(process.cwd(), 'posts');
  const filePath = path.join(postsDirectory, `${params.slug}.md`);
  const fileContents = fs.readFileSync(filePath, 'utf8');

  const { data, content } = matter(fileContents);
  const processedContent = await remark().use(html).process(content);

  return {
    props: {
      post: {
        ...data,
        content: processedContent.toString(),
      },
    },
  };
}

Step 7: Style Your Blog

You can use CSS modules, Tailwind CSS, or any styling method you prefer to enhance the appearance of your blog.

Step 8: Deploy Your Blog

Once everything is ready, deploy your blog to Vercel:

  1. Push your code to GitHub.
  2. Connect your repository to Vercel.
  3. Deploy your project with one click.

Conclusion

Congratulations! You’ve built a fully functional blog with Next.js and Markdown. You’ve learned how to:

Happy coding!

Logo

© 2024 CodingDive. All rights reserved.