Why MDX#
When we started the Ephizen blog, the content we wanted to publish was technical: code samples, callouts, step-by-step setups, and the occasional chart. A traditional CMS forces that content through a WYSIWYG editor and a plugin marketplace, and a headless CMS adds an API round trip plus a separate publishing UI to learn.
We chose MDX instead because the content lives where the code lives. Posts are .mdx files in the repo, reviewed in pull requests, versioned in Git, and deployed with the same pipeline as the rest of the site. There is no separate editor, no draft database, and no plugin to add a callout.
MDX lets you write in Markdown while embedding React components inline. You get Markdown's readability for prose and React's component model for anything interactive.
TLDR
- MDX is Markdown with inline React components, so technical content lives in the repo and ships through normal code review.
- Custom components (
Callout,Steps,Video, charts) turn flat posts into interactive ones without leaving the file. - Code blocks get syntax highlighting and a copy button out of the box.
- Keep components small and store metadata in frontmatter, not content.
// You can use React components directly in your content
<Callout type="info">
This is a custom callout component rendered inside MDX!
</Callout>
How MDX renders a post#
An MDX file is not served as-is. It runs through a small pipeline before it reaches the browser, which is what lets a <Callout> tag in a Markdown file turn into a real React component.
The parser reads the frontmatter and Markdown, then maps every custom tag to a component in the MDX component map. Standard Markdown elements render as styled HTML, and your custom tags render as React.
Custom components#
The payoff of MDX is the ability to define components that make content richer and more interactive than plain Markdown allows.
Callouts#
Use callouts to highlight important information:
Information
Use the info callout for helpful tips and additional context.
Warning
Use warnings when readers need to be careful about something.
Error
Use error callouts for critical information or common mistakes.
Success
Celebrate wins and successful outcomes with success callouts.
Pro Tip
Share expert knowledge and insider tips with the tip callout.
Code blocks#
Code blocks come with syntax highlighting and a copy button:
// TypeScript example with syntax highlighting
interface BlogPost {
title: string;
description: string;
date: string;
author: string;
tags: string[];
content: string;
}
function formatDate(dateString: string): string {
return new Date(dateString).toLocaleDateString('en-US', {
year: 'numeric',
month: 'long',
day: 'numeric'
});
}
Step-by-step guides#
For tutorials and how-tos, use the Steps component:
Install Dependencies
Start by installing the required packages: next-mdx-remote, gray-matter, and reading-time.
Create Content Directory
Set up your /content/blog/ directory structure for MDX files.
Build MDX Utilities
Create utility functions to read, parse, and serve your MDX content.
Create Components
Build custom MDX components for rich content like callouts, code blocks, and more.
Tables#
Standard markdown tables work great:
| Feature | MDX | Traditional CMS |
|---|---|---|
| Version Control | Git-native | Requires plugins |
| Component Support | Full React | Limited |
| Developer Experience | Excellent | Variable |
| Flexibility | Very High | Medium |
Interactive elements#
MDX shines when you need interactivity. You can embed:
- Accordions for expandable content
- Tabs for organizing related information
- Charts for data visualization
- Videos from YouTube, Vimeo, or self-hosted
Example Video Embed
Best practices#
Here are our recommendations for working with MDX:
- Keep components simple. Each component should do one thing well.
- Use frontmatter wisely. Store metadata, not content.
- Embrace Markdown. Use standard syntax where possible.
- Test your components. Ensure they work in both light and dark modes.
- Document everything. Future you will thank present you.
Create a component library documentation page so content authors know what's available.
Key Takeaways#
- MDX keeps technical content in the repo, so posts go through the same Git review and deploy pipeline as code.
- Custom components like
Callout,Steps, andVideolet you add interactivity inline without a plugin marketplace. - Code blocks ship with syntax highlighting and a copy button, which matters for a developer audience.
- Keep components small, store metadata in frontmatter, and test rendering in both light and dark modes.
FAQ#
When should I pick MDX over a headless CMS?
Pick MDX when your authors are developers and your content is code-heavy. If non-technical editors need a visual editor and scheduled publishing, a CMS is the better fit.
Do I need to import components into every MDX file?
No. Components are registered once in a shared MDX component map, so tags like <Callout> and <Steps> are available in every post without an import line.
How does syntax highlighting work in the posts?
Fenced code blocks are processed at build time by a highlighter (we use Shiki via rehype-pretty-code), so the colored output and copy button are static HTML with no client-side highlighting cost.
Can I use any React component inside MDX?
You can use any component that is in the MDX component map or imported in the file. Keep interactive components client-safe, since posts are server-rendered first.
Where does post metadata like title and tags live?
In the YAML frontmatter at the top of each .mdx file. The site reads it with gray-matter to build cards, metadata, and structured data.

