Also known as: Markdown JSX, Markdown components, .mdx
TL;DR
MDX is Markdown extended with JSX — write prose that imports components and renders them inline. The format that powers most modern docs sites (Next.js, Astro, Docusaurus).
MDX is Markdown plus JSX. You write ## A heading, then import Chart from './Chart', then <Chart data={...} />, then more Markdown — and a build step turns the whole file into a React/Astro component. Every page in this catalog is an MDX file.
import Chart from './Chart.tsx';# Cosine similarityCosine similarity is the angle-based metric for vector pairs:<Chart data={cosineExample} />The math is `(a · b) / (|a| |b|)`.
What MDX is good for
The shape of MDX matches “written content with structured components” exactly. Plain Markdown is too restrictive (no components); pure JSX/HTML is too imperative (writing <h2>...</h2> for every heading is hostile to prose); MDX is the compromise that lets writers write and developers build components, with each layer staying in its lane.
What MDX is not good for
Interactive web apps. If the content is 90% UI logic and 10% text, just write JSX or TSX directly. MDX adds a parser and a build step that don’t pay off for app-shaped code.
User-generated content. MDX requires a build step. If users author content at runtime (CMS, forum, chat), you don’t want to ship the MDX compiler to the browser. Use plain Markdown there and call it a day.
Data interchange. MDX isn’t a data format despite living next to JSONL and Parquet in this catalog. It’s a content format. You wouldn’t ship training data as MDX, and you wouldn’t store user records in it.
The Astro / Next / Remix surface
At build time:
The MDX parser reads the file. It identifies prose blocks (handled by remark) and JSX blocks (handled by acorn).
The whole document is compiled into a JS module that exports a default function component. Imports at the top become real imports; JSX tags become real React/Preact/Astro elements.
Plugins run between stages: remark plugins for Markdown (footnotes, math, syntax highlighting), rehype plugins for HTML (rehype-mathjax for SVG math, rehype-pretty-code for code blocks).
The output is a regular component the framework can render alongside any other.
Astro’s content collections + Astro MDX handle this end-to-end. Next.js’s app router supports MDX natively with next-mdx-remote for runtime parsing. Remix and SvelteKit have their own integrations. The pattern is the same; the API surface differs.
Three places it bites:
Bare $ in prose.remark-math interprets `$…
as inline math. A casual the cost is $5 becomes a (broken) math block. Escape as \$ or rewrite (“the cost is five dollars”).
2. < followed by a digit or letter. MDX parses < as a JSX tag-open. <5% is parsed as the opening of a JSX tag named 5% and errors. Either escape (<5%), rewrite (“less than 5%”), or use code spans (`<5%`).
3. Math in YAML frontmatter. YAML doesn’t know about LaTeX. Strings with `$…
need to be quoted carefully: summary: "Pearson's $r = ...$" works; without the quotes, YAML parses the dollars as anchors and breaks. Always quote any frontmatter string that contains math.
Why we use it everywhere
The catalog you’re reading is hundreds of MDX files. Each <Concept>, <Details>, <Callout>, <Highlight> block in prose is a real JSX component that authors drop inline without thinking about the underlying rendering layer. The diagrams are imported TSX components. The math is server-rendered SVG via MathJax during the MDX compile pass. Everything lives in one source file per concept. Editing a concept is editing one .mdx file in src/concepts/. That ergonomic shape is what makes 232 concepts maintainable; without MDX, the same content would require either a CMS (overhead) or a custom renderer (technical debt) — neither of which scales for an opinionated reference catalog.
Go further
Why MDX over plain Markdown?
Plain Markdown can't render interactive components. You can't drop a <Chart> or a <Details> block into a .md file and have it work without a custom renderer doing string-level hacks. MDX gives you JSX as a first-class citizen in Markdown — import at the top, JSX tags inline, props pass through naturally. The cost is a build step; the benefit is that prose and components live in the same source file with no ceremony.
MDX vs HTML — when does each one win?
MDX wins when the content is mostly prose with some interactive bits (docs sites, blogs, reference catalogs). HTML wins when the content is mostly UI with some text (web apps, dashboards). The line is roughly: if a human authors the content and a developer authors the components, MDX. If a developer authors everything, just write JSX/HTML directly.
What are the production gotchas?
Three. (1) JSX-in-Markdown means literal < characters can be parsed as tag opens — <2pt regression will silently break; escape as < or rewrite. (2) Math libraries like remark-math/KaTeX interact with $...
syntax — bare dollar signs in YAML frontmatter or code blocks need escaping. (3) Build performance: every MDX file compiles to a JS module, so 1000+ MDX pages can balloon your build graph. Astro's content collections handle this gracefully; Next.js's next-mdx-remote` is the escape hatch.