How to make mdx based blogs in Next JS
How to Build an MDX-Based Blog in Next.js
MDX allows you to write JSX inside Markdown, making it perfect for a Next.js blog. In this guide, we will build a blog system that reads MDX files from the frontend, renders them dynamically, and applies custom styling.
We can basically have a static JSON based data on the frontend and use it to render the blog, but that's not scalable, thats why .mdx file based blogs are the best option.
1. Project Structure
Ensure your project has the following structure:
my-nextjs-blog/
│── pages/
│ ├── blogs/
│ │ ├── [slug].js # Dynamic blog page
│ │ ├── index.js # Blog listing page
│── components/
│ ├── MDXComponents.js # Custom MDX components
│── public/
│ ├── images/ # Store blog banner images
│── content/
│ ├── example-blog.mdx # Blog posts in MDX format
│── styles/
│ ├── blog.module.css # Blog styling
│── next.config.js
│── package.json
2. Install Required Packages
Run the following command:
npm install next-mdx-remote gray-matter remark-gfm
next-mdx-remote
: Helps render MDX files dynamically.gray-matter
: Parses frontmatter metadata.remark-gfm
: Enables GitHub-flavored Markdown.
3. Configure MDX Processing
Create a lib/blogs.js
file to load and process MDX files:
import fs from 'fs'
import path from 'path'
import matter from 'gray-matter'
import { serialize } from 'next-mdx-remote/serialize'
const contentDir = path.join(process.cwd(), 'content')
export function getBlogSlugs() {
return fs.readdirSync(contentDir)
}
export async function getBlogBySlug(slug) {
const fullPath = path.join(contentDir, `${slug}.mdx`)
const fileContents = fs.readFileSync(fullPath, 'utf8')
const { data, content } = matter(fileContents)
const mdxSource = await serialize(content)
return { source: mdxSource, frontmatter: data }
}
4. Create the Blog Listing Page
Inside pages/blogs/index.js
:
import Link from 'next/link'
import { getBlogSlugs } from '../../lib/blogs'
export async function getStaticProps() {
const slugs = getBlogSlugs().map((file) => file.replace('.mdx', ''))
return { props: { slugs } }
}
export default function BlogList({ slugs }) {
return (
<div>
<h1>Latest Blog Posts</h1>
<ul>
{slugs.map((slug) => (
<li key={slug}>
<Link href={`/blogs/${slug}`}>{slug.replace('-', ' ')}</Link>
</li>
))}
</ul>
</div>
)
}
5. Create the Blog Detail Page
Inside pages/blogs/[slug].js
:
import { getBlogBySlug, getBlogSlugs } from '../../lib/blogs'
import { MDXRemote } from 'next-mdx-remote'
import styles from '../../styles/blog.module.css'
export async function getStaticProps({ params }) {
const blog = await getBlogBySlug(params.slug)
return { props: blog }
}
export async function getStaticPaths() {
const slugs = getBlogSlugs().map((file) => file.replace('.mdx', ''))
return { paths: slugs.map((slug) => ({ params: { slug } })), fallback: false }
}
export default function BlogPage({ source, frontmatter }) {
return (
<div className={styles.blogContainer}>
<img
src={frontmatter.banner}
alt={frontmatter.title}
className={styles.bannerImage}
/>
<h1 className={styles.blogTitle}>{frontmatter.title}</h1>
<div className={styles.blogContent}>
<MDXRemote {...source} />
</div>
</div>
)
}
6. Example MDX Blog Post
Create content/example-blog.mdx
:
---
title: 'Example Blog Post'
date: '2025-02-15'
banner: '/images/example-banner.jpg'
---
<img src="/images/example-banner.jpg" alt="Example Blog Banner" width="100%" />
# Example Blog Post
This is an MDX-based blog post in Next.js.
## Benefits of MDX
- Write JSX inside Markdown
- Reuse React components
- Enhanced styling control
## Conclusion
MDX makes blogging in Next.js powerful and flexible!
7. Style the Blog Pages
Create styles/blog.module.css
:
.blogContainer {
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
.bannerImage {
width: 100%;
border-radius: 10px;
margin-bottom: 20px;
}
.blogTitle {
font-size: 2rem;
text-align: center;
margin-bottom: 15px;
}
.blogContent {
font-size: 1.1rem;
line-height: 1.8;
}
8. Run Your Blog
Start your Next.js development server:
npm run dev
Visit http://localhost:3000/blogs
to see your blog in action!
Final Thoughts
By following this guide, you have successfully built an MDX-powered blog in Next.js. You can now create content-rich blogs with JSX components, custom styling, and static generation for blazing-fast performance.
For more enhancements, consider adding:
- Pagination for the blog list
- Tags and categories
- A CMS for easier content management
Happy coding! 🚀