MDX components & callouts: Markdown with superpowers
Use Astro components inside Markdown Ethe bundled <Callout>, JS expressions, slots, and a cookbook for building your own MDX-friendly components.
When the lines between data and presentation blur, MDX is your friend. You can mix JSX-flavoured components inside Markdown without leaving the authoring flow.
This post is itself an .mdx file. Open
src/content/posts/en/mdx-components-and-callouts.mdx
to see exactly how the demos below are written.
Use .md when… | Use .mdx when… |
|---|---|
| You only need standard Markdown. | You want to import an Astro component. |
| You want the file to stay portable. | You need JS expressions like {new Date()}. |
You write a lot of {} literally. | You want to compose layout-aware widgets. |
Both formats live side-by-side in the same posts/ folder Ethe build
picks them up via **/*.{md,mdx}.
The theme ships a small, accessible Callout component you can import
in any MDX post:
---title: Example---
import Callout from '../../components/Callout.astro';
<Callout type="info" title="Heads up"> This is an info callout.</Callout>It supports four semantic variants Ethey share daisyUI’s semantic colour tokens, so they stay readable in both themes.
MDX evaluates { ... } as JavaScript at build time. Today is Sat May 09 2026
according to the build server, and 2 + 2 is 4.
Variables defined at the top of the file are also in scope:
export const release = 'v6.0.0';
The latest release is **{release}**.You are not limited to Callout. Any Astro component can be imported
with a relative path. From a post at src/content/posts/en/foo.mdx,
the path to a component is ../../components/Foo.astro:
import Panel from '../../components/Panel.astro';
<Panel> <p>Embedded Panel content here.</p></Panel>Astro components inside MDX accept default slots. Anything between the
opening and closing tag is passed as <slot />:
<Callout type="success"> **Anything** can go in here E_Markdown_, [links](/), even nested components.</Callout>Named slots work too if your component declares them:
<MyWidget> <Fragment slot="header">A heading</Fragment> Body content goes in the default slot.</MyWidget>Want a <Tip> shorthand? Drop a tiny wrapper into
src/components/Tip.astro:
---import Callout from './Callout.astro';---
<Callout type="info" title="Tip"> <slot /></Callout>…then use it from any MDX file:
import Tip from '../../components/Tip.astro';
<Tip>Restart `bun run dev` after editing `astro.config.mjs`.</Tip>Inside MDX, GFM tables, footnotes, and task lists keep working unchanged:
| Feature | Status |
|---|---|
| TOC | ✁E |
| Code highlight | ✁E |
| Pagefind | ✁E |
| Giscus | ✁E |
This post sets comments: true to demonstrate that flag. To turn
comments off on a single post, set comments: false instead Esee the
frontmatter reference and the
Giscus post for the full picture.