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 without a CMS or 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, and 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 create a new
.mdxfile in theblog/postsfolder. - I add the frontmatter (
title,date,tags, etc.). - I write the post content, dropping in any React components I want.
- Contentlayer picks it up, types it, and exposes it as part of an
allPostsarray that I can import wherever I need it. - I save, commit and push, and my new post is live.
No custom API routes or a headless CMS, 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, external CMS, or remote data fetching
- ✅ Easy to write in — just markdown (& React if and when I need it)
- ✅ Structured and type-safe — thanks to Contentlayer
- ✅ Beautifully integrated — all within Next.js for routing and rendering
It gives me everything I want out of a modern writing workflow while keeping my codebase lean and my content flexible.
Have I Convinced You? Give It a Try!
Set up a new Next.js project with MDX and Contentlayer by following these steps:
- Follow Next.js's official installation guide.
- Add MDX support to your application.
- Install and configure Contentlayer with the official Contentlayer guide for Next.js.