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:
- Git-based content management - no databases or external CMS
- MDX support - ability to use React components in posts
- Static generation - fast page loads with pre-rendering
- 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:
- Server Components are great for content-heavy pages
- MDX provides flexibility without complexity
- File-based content is perfect for personal blogs
- 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!