MDX Guide: Writing Interactive Markdown with React Components
MDX Guide: Writing Interactive Markdown with React Components
MDX is a powerful format that lets you use JSX (React components) directly in your Markdown content. In this guide, we'll explore what makes MDX special and how to use it effectively.
What is MDX?
MDX stands for Markdown + JSX. It's an extension of Markdown that allows you to import and use React components within your content. This makes it perfect for documentation, blogs, and any content that needs interactivity.
MDX vs Markdown: Key Differences
| Feature | Markdown (.md) | MDX (.mdx) |
|---|---|---|
| Basic formatting (bold, italic, links) | ✓ | ✓ |
| Headings and lists | ✓ | ✓ |
| Code blocks with syntax highlighting | ✓ | ✓ |
| Tables | ✓ | ✓ |
| Images | ✓ | ✓ |
| Import statements | ✗ | ✓ |
| React/JSX components | ✗ | ✓ |
| JavaScript expressions | ✗ | ✓ |
| Interactive elements | ✗ | ✓ |
| Custom component styling | ✗ | ✓ |
| State management | ✗ | ✓ |
Markdown Example
# Hello World
This is a simple paragraph with **bold** and *italic* text.
- List item 1
- List item 2MDX Example
import { Button } from '@/components/ui/button'
import { Alert } from '@/components/ui/alert'
# Hello World
This is a paragraph with a <Button>Click Me</Button> button inline!
<Alert variant="info">
This is an interactive alert component!
</Alert>MDX File Convention
1. Frontmatter
MDX files typically start with frontmatter - YAML metadata between --- delimiters:
---
title: "Your Post Title"
description: "A brief description of your post"
date: "2025-12-03"
tags: ["tag1", "tag2"]
author: "Your Name"
---2. File Naming
- Use kebab-case:
my-awesome-post.mdx - Keep names descriptive but concise
- Avoid special characters
3. Content Structure
---
title: "Post Title"
---
# Main Heading (H1)
Introduction paragraph...
## Section Heading (H2)
Content...
### Subsection (H3)
More content...Adding Images in MDX
There are several ways to add images in MDX:
Method 1: Standard Markdown Syntax
Method 2: HTML img Tag
<img src="/images/my-image.png" alt="Description" width="600" />Method 3: Next.js Image Component (Recommended)
import Image from 'next/image'
<Image
src="/images/my-image.png"
alt="Description"
width={800}
height={400}
/>Method 4: External Images
Best Practices for Images
- Store locally: Put images in
/public/images/folder - Optimize: Compress images before adding them
- Alt text: Always provide descriptive alt text for accessibility
- Responsive: Use appropriate sizes for different screens
Using React Components in MDX
Importing Components
import { Card } from '@/components/ui/card'
import { Badge } from '@/components/ui/badge'
<Card className="p-4">
<Badge>New</Badge>
<p>This is a card with a badge!</p>
</Card>Inline Components
You can use components inline with text:
Click the <Button size="sm">Submit</Button> button to continue.Custom Components
Create reusable components for your content:
// components/Callout.jsx
export function Callout({ type, children }) {
const styles = {
info: 'bg-blue-100 border-blue-500',
warning: 'bg-yellow-100 border-yellow-500',
error: 'bg-red-100 border-red-500',
}
return (
<div className={`border-l-4 p-4 ${styles[type]}`}>
{children}
</div>
)
}Then use it in MDX:
import { Callout } from '@/components/Callout'
<Callout type="warning">
Remember to save your work frequently!
</Callout>Code Blocks with Syntax Highlighting
MDX supports fenced code blocks with language specification:
```javascript
function greet(name) {
return `Hello, ${name}!`;
}
```You can also add titles and line highlighting:
```typescript title="utils.ts" {2-3}
export function add(a: number, b: number) {
// This line is highlighted
return a + b;
}
```JavaScript Expressions
MDX allows inline JavaScript expressions:
The current year is {new Date().getFullYear()}.
{/* This is a comment in MDX */}
{isLoggedIn ? <UserDashboard /> : <LoginButton />}Setting Up MDX in Next.js
1. Install Dependencies
npm install @next/mdx @mdx-js/loader @mdx-js/react2. Configure next.config.js
const withMDX = require('@next/mdx')({
extension: /\.mdx?$/,
options: {
remarkPlugins: [],
rehypePlugins: [],
},
});
module.exports = withMDX({
pageExtensions: ['js', 'jsx', 'mdx', 'ts', 'tsx'],
});3. Create MDX Components Provider
// components/mdx-components.jsx
export const mdxComponents = {
h1: (props) => <h1 className="text-3xl font-bold" {...props} />,
h2: (props) => <h2 className="text-2xl font-semibold" {...props} />,
p: (props) => <p className="my-4" {...props} />,
// Add more custom components...
}Conclusion
MDX bridges the gap between content and interactivity. It's perfect for:
- Technical documentation with live code examples
- Blog posts with interactive demos
- Marketing pages with custom components
- Educational content with quizzes and exercises
Start with simple Markdown, then gradually add React components as needed. The power of MDX is that you can make your content as simple or as interactive as you want!