Skip to content

Astro MDX — Markdown with Interactive Components

DodaTech Updated 2026-06-28 4 min read

Learn how to use MDX in Astro: embed React, Vue, or Svelte components inside Markdown content with type-safe frontmatter validation.

In this lesson, you'll configure MDX support in Astro, write .mdx files that import and use interactive components, and combine rich Markdown content with dynamic UI elements.

What You'll Learn

How to install and configure @astrojs/mdx, write MDX files with embedded components, and use frontmatter with type-safe schemas.

Why It Matters

MDX lets content authors write in familiar Markdown while adding interactive components where needed—without switching to a different page type or framework.

Real-World Use

DodaTech's advanced tutorials use MDX to embed interactive code sandboxes and live examples directly in Markdown content.

flowchart LR
    A[.mdx File] --> B[Markdown Content]
    A --> C[Component Imports]
    B --> D[HTML Output]
    C --> E[Interactive Islands]
    style A fill:#ff5a03,color:#fff

Setup MDX

Install the MDX integration:

npx astro add mdx

This adds @astrojs/mdx to your astro.config.mjs:

import { defineConfig } from "astro/config";
import mdx from "@astrojs/mdx";

export default defineConfig({
  integrations: [mdx()],
});

Writing MDX

Create src/pages/blog/hello-world.mdx:

---
title: Hello World
description: "My first MDX post with rich content."
---

## Introduction

This is a regular Markdown paragraph with **bold** and _italic_ text.

- List item one
- List item two

Output: The MDX file renders as a page at /blog/hello-world/ with the Markdown converted to HTML.

Using Components in MDX

Import and use framework components directly:

---
title: Interactive Demo
description: "A tutorial page with embedded interactive components."
---

import Counter from "../../components/Counter.tsx";
import Chart from "../../components/Chart.vue";

## Live Counter

Click the button to increment:

<Counter client:load />

## Data Visualization

This chart updates with real data:

<Chart client:visible />

Output: The <Counter> and <Chart> components become interactive islands within the Markdown content. Everything else renders as static HTML.

Custom Components for MDX

Define a map of components to replace HTML elements:

// src/components/mdx-components.js
import CodeBlock from "../components/CodeBlock.astro";
import Note from "../components/Note.astro";

export function useMDXComponents() {
  return {
    pre: CodeBlock,
    blockquote: Note,
  };
}

Configure in your layout:

---
import { useMDXComponents } from "../components/mdx-components";
---
<article>
  <slot />
</article>

Now code blocks and blockquotes in MDX use your custom components automatically.

Type-Safe Frontmatter

Validate MDX frontmatter using content collections:

// src/content/config.ts
import { defineCollection, z } from "astro:content";

const blogCollection = defineCollection({
  schema: z.object({
    title: z.string(),
    description: z.string().max(165),
    date: z.date(),
    tags: z.array(z.string()).optional(),
  }),
});

export const collections = {
  blog: blogCollection,
};

Common Mistakes

  1. Forgetting the client:* directive on MDX components: Framework components in MDX need client:* to be interactive, just like in .astro pages.
  2. Not configuring the MDX integration: Without @astrojs/mdx in config, .mdx files throw build errors.
  3. Using .mdx for pages without components: If a page has no interactive components, use .md instead. It's simpler and builds faster.
  4. Missing imports for components: Every component used in MDX must be imported at the top of the file.
  5. Putting server logic in MDX: MDX doesn't support the --- frontmatter fence for server code. Use .astro pages for dynamic logic.

Practice Questions

  1. What makes MDX different from regular Markdown? Answer: MDX allows importing and using JavaScript/TypeScript components directly in Markdown content.

  2. How do you install MDX support in Astro? Answer: Run npx astro add mdx. It installs @astrojs/mdx and updates astro.config.mjs.

  3. Can MDX files use content collection schemas? Answer: Yes. MDX files in src/content/ validate against collection schemas, just like .md files.

  4. What happens if you use a component without a client:* directive in MDX? Answer: The component renders as static HTML with no interactivity. It appears but doesn't respond to user input.

Challenge

Create an MDX page that imports a React counter component with client:load, a Vue chart with client:visible, and a note callout component. Add custom MDX component mapping for blockquotes.

Mini Project

Build a tutorial page using MDX for a "Getting Started" guide. Include a live code sandbox component, an interactive tip calculator, and a downloadable code snippet component.

FAQ

Does MDX work with Astro's content collections?

: Yes. Place .mdx files in src/content/ collections. They validate against the collection schema.

Can I use `.astro` components in MDX?

: Yes. Import .astro components just like framework components. They render as static HTML.

Is there a performance difference between `.md` and `.mdx`?

: MDX requires additional processing to handle component imports. For pages without components, .md is faster to build.

Can I use frontmatter variables in MDX content?

: Yes. Access them through the frontmatter export or via content collection APIs.

What's Next

Learn about Astro Content Collections for type-safe management of Markdown and MDX content at scale.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro