Why I Use Next.js + MDX + Contentlayer for My Blog
This very blog is powered by a stack that’s become my favorite setup for content-driven sites: Next.js + MDX + Contentlayer.
It’s clean, fast, developer-friendly, and it gives me the right blend of control and automation to stay focused on writing without sacrificing flexibility.
Here’s why I love it, and why you might, too.
MDX: Markdown with Superpowers
Markdown is the obvious choice for writing long-form content—it’s readable, portable, and fast to write. But once you need to drop in a component (a custom note block, a chart, an interactive demo), vanilla markdown stops being enough.
MDX lets me keep writing in markdown while sprinkling in React components wherever I need them. It’s just plain .mdx
files—no special CMS, no remote markdown sources, no content admin panel.
Want to drop in a <CodeBlock>
or a custom <Button>
? I can do that inline, right inside the post body:
Here's some paragraph content with an action:
<Button variant='outline' size='lg'>
Get Started with MDX
</Button>
Contentlayer: Content with Type Safety
MDX is great for writing—but once you want to pull in metadata like titles, tags, or excerpts, and use that data elsewhere (say, in a blog index), you need something more structured.
That’s where Contentlayer shines.
It watches my filesystem, parses each .mdx
file, and gives me a fully typed content object I can import directly into my pages and components. No gray-matter
, no custom parsing logic, no guesswork.
If I define my frontmatter like this:
---
title: 'Why I Use Next.js + MDX + Contentlayer'
date: '2025-07-11'
excerpt: 'Combining Next.js, MDX, and Contentlayer gives me the best of all worlds.'
tags: ['Next.js', 'MDX', 'Contentlayer']
---
Contentlayer turns it into a fully typed JavaScript object with TypeScript definitions:
{
title: string
date: string
excerpt: string
tags: string[]
body: { code: string }
}
Which means better DX, autocomplete, and zero runtime surprises.
Next.js: The Backbone
Of course, Next.js glues everything together. With its support for file-based routing and the App Router’s flexibility, it’s easy to generate static blog pages from the parsed content and wire up a dynamic, fast-loading blog index.
All I needed was a dynamic route path directory of /blog/[slug]/page.tsx
, and I generated a full static site with rich MDX content—fully typed, automatically rendered, and SEO-ready.
The Workflow Feels Effortless
Here’s how streamlined things are:
- I write a new
.mdx
file in theblog/posts
folder. - I add the frontmatter (title, date, tags, etc.).
- I write the post, dropping in any React components I want.
- Contentlayer picks it up, types it, and exposes it as part of an
allPosts
array that I can import wherever I need it. - I hit save, commit and push, and my new post is live.
No custom API routes. No headless CMS. No copy/pasting markdown blobs into some admin UI. Just a markdown file in my repo.
A Setup Worth Recommending
This setup hits a really nice sweet spot:
- ✅ Fast to build with — no complex setup or external CMS
- ✅ Easy to write in — just markdown + React when I need it
- ✅ Structured and type-safe — thanks to Contentlayer
- ✅ Beautifully integrated — all within Next.js
It gives me everything I want out of a modern writing workflow while keeping my codebase lean and my content flexible.
If you’re building a blog, documentation site, or any content-heavy frontend, I highly recommend giving this trio a shot.