Every page is an .mdx file in src/content/docs/. The file path becomes the URL, so src/content/docs/guides/deploy.mdx is served at /guides/deploy/.
1. Create a page
Add a file with a title in its frontmatter. The title becomes the page heading, so don’t repeat it in the body.
---
title: Deploy
description: Ship the site to production.
---
Run the build, then upload the output.Frontmatter is validated at build time. A missing title or a misspelled field fails the build with a message that names the file and the field.
titleis required. Everything else is optional.descriptionappears under the heading, in search results, and in social cards.sidebarcontrols where the page sits in the navigation.ordersorts pages within a group, lowest first.badgeadds a short label next to the link.
1.1 Frontmatter fields
| Field | Type | Description |
|---|---|---|
title |
string | The page heading and the <title> tag. |
description |
string | One-line summary for search, social cards, and the page header. |
sidebar.order |
number | Position within the sidebar group. Lower numbers come first. |
draft |
boolean | Builds the page in development only. It never reaches production. |
2. Write with Markdown
Standard Markdown works everywhere: bold, italic, links, inline code, lists, tables, and fenced code blocks. Press ⌘ K to search the site for anything else.
Write the page you would want to find. One topic per page, and a title that says what the reader will be able to do.
Code blocks are highlighted at build time. Add a title to show a filename, and line numbers in braces to draw attention to specific lines.
const nimbusConfig = defineNimbusConfig({
site: "https://docs.example.com",
title: "My docs",
description: "Guides and reference for My product.",
});2.1 Organise the sidebar
Folders become sidebar groups. Inside a group, pages sort by sidebar.order, then by title.
- Create a folder in
src/content/docs/, for exampleguides/. - Move related pages into it.
- Set
sidebar.orderon each page to fix the order.
3. Use components
Components are available in every .mdx file without an import. Install more from the registry when you need them.
Add a component
Run
npx @cloudflare/nimbus-docs add accordionto copy it intosrc/components/ui/.Register it
Add it to
src/components.tsso every page can use it.
npx @cloudflare/nimbus-docs add accordionpnpm dlx @cloudflare/nimbus-docs add accordion3.1 What ships with the starter
- Aside
- Notes, tips, cautions, and warnings that stand apart from the text.
- Steps
- Numbered procedures, each with a title and its own content.
- Tabs
- The same content in several variants, such as one command per package manager.
Can I use plain Markdown files instead of MDX?
Yes. MDX is a superset of Markdown, so any .md content works unchanged in an .mdx file. You only need MDX syntax when you add a component.
Pages you write today keep working when you upgrade Nimbus1. Use highlights sparingly; they lose their meaning when everything is marked.
4. Component reference
Every .mdx file can use these components without an import. Each one is a file in src/components/ui/, so you can change how it looks or works.
4.1 Aside
Set a note, tip, caution, or warning apart from the text around it.
<Aside type="note">
Pages are validated at build time.
</Aside>
<Aside type="caution" title="Before you deploy">
Set `site` in `astro.config.ts` to your production URL.
</Aside>| Prop | Value |
|---|---|
type |
note (default), tip, caution, or danger |
title |
Text above the content. Defaults to the type’s name. |
icon |
Any ph: icon name, in place of the type’s icon. |
For a title with formatting, pass it as a slot: <Fragment slot="title">Uses <code>env</code></Fragment>.
4.2 Steps
Number a procedure. Each step has a title and its own content.
Create the page
Add
src/content/docs/deploy.mdxwith atitle.Preview it
Run
npm run devand open the page.
<Steps>
<Step title="Create the page">
Add `src/content/docs/deploy.mdx` with a `title`.
</Step>
<Step title="Preview it">
Run `npm run dev` and open the page.
</Step>
</Steps>| Prop | Value |
|---|---|
start on Steps |
The first step’s number. Defaults to 1. |
title on Step |
The step’s heading. Also accepts a title slot. |
4.3 Tabs
Show the same content in several variants. Give tabs a syncKey, and the reader’s choice carries over to every set of tabs with the same key.
Press ⌘ K to search.
Press Ctrl K to search.
<Tabs syncKey="os">
<TabItem label="macOS">
Press <kbd>⌘</kbd> <kbd>K</kbd> to search.
</TabItem>
<TabItem label="Windows">
Press <kbd>Ctrl</kbd> <kbd>K</kbd> to search.
</TabItem>
</Tabs>| Prop | Value |
|---|---|
syncKey on Tabs |
Tabs with the same key switch together, and remember the choice. |
label on TabItem |
The tab’s name. Required. |
4.4 Package managers
Write an install command once and show it for npm, pnpm, Yarn, and Bun.
npm i your-packageyarn add your-packagepnpm add your-packagebun add your-package<PackageManagers pkg="your-package" />Add dev for a dev dependency, or type="run" args="build" for a script.
4.5 Cards
Link readers to the next places to go, in a grid that stacks on small screens.
Write a page
Create an .mdx file in src/content/docs/.
Change the theme
Edit the colour and type tokens in src/styles/globals.css.
<CardGrid>
<Card title="Write a page" icon="ph:pencil-simple">
Create an `.mdx` file in `src/content/docs/`.
</Card>
<Card title="Change the theme" icon="ph:palette">
Edit the colour and type tokens in `src/styles/globals.css`.
</Card>
</CardGrid>| Prop | Value |
|---|---|
title on Card |
The card’s heading. Also accepts a title slot. |
icon on Card |
Any ph: icon name. Also accepts an icon slot. |
Icons come from Phosphor: use any name with the ph: prefix.
4.6 Partials
Write a passage once and include it on any page. Partials live in src/content/partials/.
This text lives in src/content/partials/example.mdx and is pulled in with
<Render file="example" />. Edit the partial once and every page that renders
it stays in sync — handy for install steps, support notes, or any boilerplate
you’d otherwise copy between pages.
<Render file="example" />4.7 Restyle any part
Every part of every component has a data-slot attribute, so you can restyle one piece from src/styles/globals.css without editing the component.
[data-slot="card-title"] {
letter-spacing: -0.01em;
}Corners come from two tokens in the same file: --nb-radius for cards, callouts, code blocks and buttons, and --nb-radius-sm for the small marks inside them. Change them to re-round the whole site.
4.8 Add more
Accordions, file trees, link cards, embeds, and more install from the registry when you need them. Each one lands as a file in src/components/ui/, like the components above.
npx @cloudflare/nimbus-docs add accordionyarn dlx @cloudflare/nimbus-docs add accordionpnpm dlx @cloudflare/nimbus-docs add accordionbunx @cloudflare/nimbus-docs add accordion5. FileTree
Use a nested Markdown list to describe a directory structure. End directory names with /, highlight important files with **name**, and use ... for omitted entries.
- src/
- content/
- docs/
- writing-pages.mdx
- docs/
- components/
- ui/
- content/
- astro.config.ts
- package.json
<FileTree>
- src/
- content/
- docs/
- **writing-pages.mdx**
- components/
- ui/
- astro.config.ts
- package.json
</FileTree>6. Accordion
Use collapsible sections for optional explanations. Set open on an Accordion to start expanded.
<AccordionGroup>
<Accordion>
<AccordionTrigger>Do components need imports?</AccordionTrigger>
<AccordionContent>Components registered in src/components.ts are available in every MDX article.</AccordionContent>
</Accordion>
<Accordion>
<AccordionTrigger>Where should shared text live?</AccordionTrigger>
<AccordionContent>Use a partial and the Render component.</AccordionContent>
</Accordion>
</AccordionGroup>7. CodeGroup
Use titles to label code alternatives. Each fenced block becomes one panel.
const greeting = "Hello, Petwan";const greeting: string = "Hello, Petwan";<CodeGroup titles={["JavaScript", "TypeScript"]}>
```js
const greeting = "Hello, Petwan";
```
```ts
const greeting: string = "Hello, Petwan";
```
</CodeGroup>8. CopyPrompt
The text prop supplies the full prompt copied to the clipboard, even if the displayed line is truncated.
Read the Writing pages and components guide, then help me draft a clear MDX article using the installed components.
<CopyPrompt text="Read the Writing pages and components guide, then help me draft a clear MDX article using the installed components." />9. Embed
Provide src and an accessible title; ratio defaults to 16/9. This local demo avoids depending on an external provider. External sites must permit embedding.
<Embed src="/embed-demo.html" title="Petwan embedded content example" ratio="16/9" />10. Frame
Wrap a screenshot or demo with a caption. Imported images passed through src use Astro image optimization; public image paths use a plain image.
<Frame caption="The Petwan P mark">
<img src="/logo.svg" alt="Petwan letter P logo" width="128" height="128" />
</Frame>11. LinkCard
Use href, title and an optional description. The entire card is a link.
Petwan Journal
Return to the homepage and browse the latest notes.<LinkCard href="/" title="Petwan Journal" description="Return to the homepage and browse the latest notes." />12. Popover
Compose the root, trigger and content. Keep PopoverTrigger a direct child of Popover. Supported placements are bottom-start, bottom-end, top-start and top-end.
Use one clear topic per article and runnable examples.
<Popover>
<PopoverTrigger class="rounded-md border border-border px-3 py-2 text-sm">Writing tip</PopoverTrigger>
<PopoverContent placement="bottom-start">
<p>Use one clear topic per article and runnable examples.</p>
</PopoverContent>
</Popover>13. Lightbox
Give a figure a caption and a click-to-zoom surface. Plain Markdown images already zoom, so wrap only when you want an explicit caption.
<Lightbox src="/logo.svg" alt="Petwan letter P logo" caption="The Petwan P mark" />| Prop | Value |
|---|---|
src |
Image path. Required. |
alt |
Accessible description. Required. |
caption |
Optional text below the image. |
class |
Extra class on the img element. |
14. Math formulas
MathFormula is not registered globally — import it explicitly. The tex prop is a string expression, so backslashes must be escaped as \\.
import MathFormula from "../../components/MathFormula.astro";
<MathFormula tex={"E = mc^2"} display />A bare $$ … $$ block does not render here: MDX reads the braces as a JSX expression and the build fails. Use the component.
Footnotes
-
Changes that need your attention are listed by
npx @cloudflare/nimbus-docs migrate --dry-run. ↩