← Back to Blog

Building a Blog with Next.js and MDX

2 min read
nextjsreacttypescripttutorial

Building a Blog with Next.js and MDX

When I decided to add a blog to my personal website, I wanted something simple but powerful. Here's how I built it.

Requirements

I had a few key requirements:

  1. Git-based content management - no databases or external CMS
  2. MDX support - ability to use React components in posts
  3. Static generation - fast page loads with pre-rendering
  4. Simple deployment - automatic builds on Vercel

Technology Choices

next-mdx-remote

I chose next-mdx-remote over alternatives because:

  • Actively maintained by HashiCorp
  • Works well with Next.js App Router
  • Supports React Server Components
  • Simple API

gray-matter

For parsing frontmatter metadata:

import matter from 'gray-matter';

const { data, content } = matter(fileContents);

This gives us structured metadata and clean content.

reading-time

Automatically calculates reading time:

import readingTime from 'reading-time';

const stats = readingTime(content);
console.log(stats.text); // "5 min read"

Implementation

Directory Structure

src/
├── app/
│   └── blog/
│       ├── page.tsx           # Blog index
│       └── [slug]/
│           └── page.tsx       # Individual post
├── content/
│   └── blog/
│       └── *.mdx             # Blog posts
└── lib/
    └── blog.ts               # Utility functions

Core Functions

The blog.ts utilities handle:

  • getAllPosts() - List all posts sorted by date
  • getPostBySlug() - Get a single post
  • getPostSlugs() - For static generation
  • formatDate() - Display-friendly dates

Dynamic Routes

The [slug] route uses generateStaticParams for static generation:

export async function generateStaticParams() {
  const slugs = getPostSlugs();
  return slugs.map((slug) => ({ slug }));
}

What I Learned

Building this taught me:

  1. Server Components are great for content-heavy pages
  2. MDX provides flexibility without complexity
  3. File-based content is perfect for personal blogs
  4. TypeScript helps catch errors in content processing

Next Steps

Future enhancements I'm considering:

  • Syntax highlighting with Prism or Shiki
  • Table of contents generation
  • Related posts suggestions
  • Full-text search

Conclusion

This setup gives me everything I need: simple content management, fast performance, and room to grow. If you're building a personal blog, I highly recommend this approach.

Check out the source code to see the full implementation!