Astro
Integrate MDX UI with an Astro project using @astrojs/react and @astrojs/mdx
Overview
Astro has first-class MDX support via @astrojs/mdx. MDX UI components are React-based, so you also need the React integration. Components are injected per-page through Astro's components prop — no global provider needed.
Best for: Content-heavy sites, documentation, blogs, and static sites that want interactive islands.
1. Create an Astro Project
Skip this step if you already have a project.
pnpm create astro@latest my-app
cd my-app
pnpm install2. Add React Integration
MDX UI components are built with React. Add the Astro React integration:
pnpm astro add reactThis automatically updates astro.config.mjs and installs @astrojs/react, react, and react-dom.
3. Add MDX Integration
pnpm astro add mdx4. Add Tailwind CSS
MDX UI components use Tailwind CSS for styling.
pnpm astro add tailwindAfter this, update tailwind.config.mjs to include your MDX UI component files so Tailwind doesn't purge their classes in production:
/** @type {import('tailwindcss').Config} */
export default {
content: [
"./src/**/*.{astro,html,js,jsx,ts,tsx,mdx}",
"./src/components/mdx-ui/**/*.{ts,tsx}", // required for MDX UI
],
theme: {
extend: {},
},
plugins: [],
};5. Initialize MDX UI
pnpm dlx @ravikumarsurya/mdx-ui initThis creates mdx-ui.json and copies the cn() utility to src/lib/utils.ts.
6. Add Components
pnpm dlx @ravikumarsurya/mdx-ui add callout accordion code-blockThe CLI automatically copies the component file and updates
src/components/mdx-ui/mdx-components.ts with the correct imports and
mappings. You never need to edit that file manually.
7. Register Components
The init command creates src/components/mdx-ui/mdx-components.ts. Every subsequent add command patches this file automatically — you only wire it up once.
import { Callout } from "./callout";
import {
Accordion,
AccordionItem,
AccordionTrigger,
AccordionContent,
} from "./accordion";
import { CodeBlock } from "./code-block";
export const mdxComponents = {
Callout,
Accordion,
AccordionItem,
AccordionTrigger,
AccordionContent,
CodeBlock,
};In Astro, components are passed to the MDX <Content> renderer per page — not via a global provider. Create a shared layout that does this for all your docs pages:
---
import { mdxComponents } from "../components/mdx-ui/mdx-components";
const { Content } = Astro.props;
---
<html lang="en">
<body>
<main>
<Content components={mdxComponents} />
</main>
</body>
</html>Then use it in any .mdx page:
---
layout: ../layouts/DocsLayout.astro
---
# Guide
<Callout variant="info" title="Tip">
Components registered in mdxComponents are available here — no imports needed
in the MDX file.
</Callout>8. Interactive Components
Astro renders React components as static HTML by default. For components with interactivity (click handlers, open/close state), add a client: directive:
// Static — no JS sent to browser (fine for Callout, CodeBlock, badges)
<Callout variant="info" title="Note">
This is purely visual.
</Callout>
// Interactive — needs hydration (Accordion, Tabs, Reveal)
<Accordion client:load>
<AccordionItem value="item-1">
<AccordionTrigger>Click me</AccordionTrigger>
<AccordionContent>I open and close — needs client:load.</AccordionContent>
</AccordionItem>
</Accordion>| Directive | When it hydrates | Use for |
|---|---|---|
client:load | Immediately on page load | Components visible above the fold |
client:visible | When component enters the viewport | Components further down the page |
client:idle | When browser is idle | Lower-priority interactive components |
Adding client:load to a purely visual component like Callout or
CodeBlock ships unnecessary JavaScript. Only use it on components that have
state or event handlers (Accordion, Tabs, Reveal).
Project Structure
Troubleshooting
Tailwind classes not applying
Ensure src/components/mdx-ui/**/*.{ts,tsx} is in your content array in tailwind.config.mjs. Without it, Tailwind purges all component class names in production builds — components render but look unstyled.
Components not rendering in MDX
Make sure you are passing components={mdxComponents} to <Content /> in your layout. Without it, MDX treats component tags as unknown HTML elements and ignores them.
TypeScript error: Cannot find module @/lib/utils
MDX UI uses the @/ path alias. Add it to tsconfig.json:
{
"compilerOptions": {
"paths": {
"@/*": ["./src/*"]
}
}
}Component renders but is not interactive
You are missing the client: directive. Static-rendered React components have no JS. Add client:load to any component that has state (Accordion, Tabs, Reveal).
Use with Claude Code (MCP)
Once your Astro project is set up, connect the mdx-ui MCP server so Claude knows exactly which components are available — no system prompt needed.
Create .claude/settings.json in your project root:
{
"mcpServers": {
"mdx-ui": {
"command": "pnpm",
"args": ["dlx", "@ravikumarsurya/mdx-ui@latest", "mcp"]
}
}
}Replace pnpm dlx with npx or yarn dlx depending on your package manager.
Open the project in VS Code with Claude Code. The server starts automatically and gives Claude live access to your component registry. Claude will call list_components, convert_latex, and validate_mdx automatically before returning MDX output.
See the MCP Server doc for the full list of tools and prompts.
Next Steps
On This Page