MDX Guide: Writing Interactive Markdown with React Components

5 min read
mdx
markdown
react
tutorial

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

FeatureMarkdown (.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 2

MDX 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

![Alt text](/images/my-image.png)

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

![External image](https://example.com/image.jpg)

Best Practices for Images

  1. Store locally: Put images in /public/images/ folder
  2. Optimize: Compress images before adding them
  3. Alt text: Always provide descriptive alt text for accessibility
  4. 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/react

2. 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!

Resources