TrademarkTrademark
Docs
Ctrl k
Search docs...
Modules

MDX

Updated: October 10, 2026
View on GitHub

@once-ui-system/core/mdx exports a component map for MDX content. Hand it to next-mdx-remote or @next/mdx and Markdown renders through Once UI: headings get an id and a link to themselves, links go through SmartLink, images through Media, fenced code through CodeBlock, and GFM tables through Table. Common components such as Feedback, Accordion, Card and OgCard are available in the content by name.

The map is typed against the props MDX passes for each element, so an override is checked when you write it, without casts.

next-mdx-remote

Pass mdxComponents as the components prop. The map works in server components, so it can be used with next-mdx-remote/rsc.

next-mdx-remote 6 blocks JavaScript expressions in MDX by default. If your content passes props such as codes={[...]}, set options={{ blockJS: false }}.

@next/mdx

@next/mdx reads the map from mdx-components.tsx at the project root (or in src/). Spread the Once UI map first, so the components passed in can override it.

Override or extend tags

createMdxComponents returns the default map with your entries applied. An HTML tag key (h2, a, hr and so on) replaces what Markdown renders for that element. Any other key registers a component the content can use by name.

  • To keep the plain HTML element, map the tag to its own name: createMdxComponents({ hr: "hr" }).
  • An entry set to undefined is skipped, so a conditional override cannot remove an element by accident.
  • The element components (MdxHeading, MdxParagraph, MdxLink, MdxImage, MdxInlineCode, MdxCodeBlock, MdxBlockQuote, MdxList, MdxListItem, MdxTable, MdxHr) are exported for wrapping. Each takes its element's MDX props plus margins. Setting any margin replaces the element's default margins.
  • An override that needs a prop Markdown can never supply does not compile. For example, h3: ({ level }: { level: number }) => ... is rejected.

What each element renders

Markdown
Renders
Notes
# Heading to ###### HeadingHeading with a link to itselfThe id is a slug of the heading's text, or the id MDX passes, for example from rehype-slug.
ParagraphText as a <p>A paragraph that is only an image renders the image on its own. Text around an inline image renders as a <div>.
[text](href)SmartLinkInternal paths use your router's link; external URLs open in a new tab.
![alt](src)MediaGoes through the image adapter and enlarges on click.
`code`InlineCode
Fenced codeCodeBlockThe language comes from the fence (ts, tsx, bash and so on). Without one, the code renders as plain text. Needs prismjs.
> quoteBlockQuote
- and 1. listsList, ListItemAn ordered list keeps its start number.
GFM tableTableNeeds remark-gfm. Column alignment carries over.
---LineHas the separator role.

Tags available by name: Accordion, AccordionGroup, BlockQuote, Button, Card, CodeBlock, Column, Feedback, Grid, Heading, Icon, InlineCode, Line, List, ListItem, Media, OgCard, Row, SmartLink, Table and Text.

Headings and anchors

Each heading renders with an anchor link next to it. The link shows on hover, on focus, and always on touch screens. It is a real link to the section, so it works without JavaScript and can be reached with the keyboard. Activating it also copies the section's URL and confirms with a toast, so the content must render inside a ToastProvider, as it does in the standard Once UI provider setup. HeadingNav picks up the ids.

For links and images to use next/link and next/image, import LayoutProvider from @once-ui-system/core/next. Without it, they render as a plain <a> and <img>.

Ids are slugged from the text the same way Studio and this site do it: "Get started & deploy" becomes get-started-and-deploy. Two headings with the same text get the same id. To make them unique, add rehype-slug, whose ids take precedence.

API reference

Type
Default
mdxComponents
The default map.
MdxComponents—
createMdxComponents
The default map with overrides applied.
(overrides?: Partial<MdxComponents>) => MdxComponents—
MdxComponents
Tag keys typed against MDX's props; other keys are components used by name.
type—
MdxElementProps
The props MDX passes for an element: MdxElementProps<"h2">.
type—
MdxHeading
A heading with an id and an anchor link. Takes as: "h1" to "h6".
MdxHeadingProps—
Edit this page on GitHub
TrademarkTrademark
Built with curiosity by Lorant One and the Design Engineers Club