Skip to content

Markdown and MDX

Write content in Markdown or MDX, use components without imports, and let the build catch broken tags.

AI-generated · awaiting reviewUpdated View as Markdown

Content is Markdown (.md) or MDX (.mdx). MDX lets you drop components straight into prose — cards, tabs, steps, asides, and anything you build.

Write site links as logical root paths without Astro’s deployment base. If the site is deployed with base: "/docs", write [Installation](/installation), not [Installation](/docs/installation). Nimbus adds /docs during the build.

This applies to Markdown links, reference definitions, native <a href> attributes, and static component href strings. Relative links, external URLs, fragments, query strings, code, and dynamic JSX expressions are left unchanged.

For a link computed in component or route code, import withBase from @cloudflare/nimbus-docs/runtime and apply it once:

import { withBase } from "@cloudflare/nimbus-docs/runtime";

const href = withBase("/installation", import.meta.env.BASE_URL);

Do not pass an already based path to withBase; with a /docs base, withBase("/docs/installation", "/docs") intentionally produces /docs/docs/installation.

The components registry

Components listed in src/components.ts are available in every MDX file without an import:

src/components.tsts
import { Aside } from "./components/ui/aside";
import { Card } from "./components/ui/card";
import { CardGrid } from "./components/ui/card-grid";

export const components = {
  Aside,
  Card,
  CardGrid,
};
<CardGrid>
  <Card title="Fast">Built on Astro.</Card>
</CardGrid>

Anything not in the registry must be imported at the top of the file:

import { FileTree } from "@/components/ui/file-tree";

<FileTree>
- src/
</FileTree>

Build-time validation

A pre-build content pass checks every PascalCase tag in src/content/**/*.mdx against the registry plus per-file imports. Unknown components, lowercase usages, and missing imports fail the build instead of silently rendering as literal text on the deployed page. Opt out with validateMdx: false in the integration options.

Admonitions

In .mdx files, Sätteri parses fenced ::: directives and Nimbus renders them with <Aside>:

:::tip
This becomes an Aside.
:::

Rendered examples

These callouts are authored with directive syntax and rendered through Sätteri.

Syntax and behavior

Built-in types: note, info, tip, caution, warning, important, danger. Add synonyms with admonitions: { typeAliases: { heads: "tip" } }. Aside must be in your components registry (the default starter exports it).

Titles use the existing plain title prop. Sätteri emits the string attribute; quotes and expression-looking text are not evaluated. Markup in titles remains literal text. Directive titles must still be valid MDX syntax because Sätteri parses the document before the AST pass runs. For arbitrary text such as an unclosed <T> or {, use the direct component’s string prop:

<Aside title="Use <T>">Body content.</Aside>

No Aside component update is required.

Sätteri parses the directives and their bodies; Nimbus maps recognized directive nodes to Aside. Body indentation is not rewritten. Code examples, frontmatter, expressions and JSX attributes remain protected. The existing opening-line body form is retained for compatibility.

Nesting and fence termination follow Sätteri’s native grammar. Use a longer outer fence for nested admonitions:

::::note
Outer content.

:::tip
Inner content.
:::
::::

Unknown directives remain literal by default. If your Sätteri processor explicitly enables native directives, unrecognized nodes remain available to your own AST plugins. Files containing standalone carriage returns also remain literal because the installed native directive parser does not handle those line endings consistently; LF and CRLF are supported.

This feature requires Nimbus’s native Sätteri MDX pipeline. Compatible explicit Sätteri processors are supported. For unified or another custom processor, set admonitions: false and retain that processor’s callout implementation. .md files, raw imports and files outside admonitions.contentDirs are unchanged. Use admonitions.skip for per-file opt-outs.

Extending Markdown

Extend Sätteri with markdown.mdastPlugins for Markdown AST transformations and markdown.hastPlugins for HTML AST transformations. Nimbus provides native plugins through @cloudflare/nimbus-docs/markdown:

astro.config.tsts
import { externalLinks } from "@cloudflare/nimbus-docs/markdown";

nimbus(config, {
  markdown: { hastPlugins: [externalLinks()] },
});
Navigation

Type to search…

↑↓ navigate↵ selectEsc close