Nimbus generates API references from machine-readable specifications. Each supported format has its own source, configuration, and content loader.
OpenAPI
Nimbus currently supports OpenAPI 3.x. Nimbus turns a local OpenAPI document into a content collection that powers reference pages, navigation, alternate Markdown versions, search entries, llms.txt indexes, and stable links from prose documentation.
The OpenAPI document remains the source of truth. You do not create one MDX file per operation or schema.
Install with the recipe
Start with an OpenAPI 3.x document stored in your repository. Convert Swagger 2.0 documents to OpenAPI 3.x first. src/api/openapi.yaml is the usual location, but Nimbus accepts any project-relative local path or an inline document object. Remote specification URLs are not supported.
Run the API reference recipe from the project root inside your coding agent:
npx @cloudflare/nimbus-docs add api-referenceyarn dlx @cloudflare/nimbus-docs add api-referencepnpm dlx @cloudflare/nimbus-docs add api-referencebunx @cloudflare/nimbus-docs add api-referenceNimbus passes the recipe directly to detected coding agents. From a regular shell, add --print and pass the output to your coding agent. The recipe reviews its plan before changing files.
The recipe tells the agent to inspect your project, ask for the specification path and collection name, and then:
- Installs the editable API layout and its parser dependencies.
- Declares the specification in the Nimbus config in
astro.config.ts. - Registers a loader-backed Astro content collection with one line.
- Adds the HTML catch-all route. The starter’s shared Markdown route serves each page’s Markdown version.
- Connects the collection to search, alternate Markdown versions, and
llms.txtindexes.
How the pieces fit
| File | Responsibility |
|---|---|
src/api/openapi.yaml |
The API contract and documentation source. |
astro.config.ts |
Declares the specification, versions, routes, and rendering policy in the Nimbus config. |
src/content.config.ts |
Registers the generated entries as an Astro content collection. |
src/pages/api/[...slug].astro |
Renders API HTML through the user-owned API layout. |
src/pages/[...slug]/index.md.ts |
The starter’s shared Markdown route. Serves an alternate Markdown version of every API page. |
src/components/ui/api-*/ |
Owns the reference’s appearance and interaction design. |
Why the specification is not in src/content
src/content/docs/ contains authored MDX entries. An OpenAPI document is an input to a loader: Nimbus projects it into many operation, schema, tag, and webhook entries in the registered api collection.
Keeping the source under src/api/ makes that distinction visible. The path is only a convention; src/content/api/openapi.yaml also works if the configured spec points there.
Configuration generated by the recipe
The recipe declares the specification once, as an api entry in the Nimbus config:
import { defineConfig } from "astro/config";
import nimbus, {
defineConfig as defineNimbusConfig,
} from "@cloudflare/nimbus-docs";
const nimbusConfig = defineNimbusConfig({
site: "https://docs.example.com",
title: "Acme Docs",
api: [
{
collection: "api",
spec: "./src/api/openapi.yaml",
},
],
});
export default defineConfig({
integrations: [nimbus(nimbusConfig)],
});The collection name is also its URL prefix: api mounts the reference at /api.
The recipe then registers a loader-backed collection under the same key, preserving existing collections and custom schema fields:
import { defineCollection } from "astro:content";
import {
apiCollection,
docsCollection,
partialsCollection,
} from "@cloudflare/nimbus-docs/content";
export const collections = {
docs: defineCollection(docsCollection()),
partials: defineCollection(partialsCollection()),
api: defineCollection(apiCollection()),
};apiCollection() reads the api entry whose collection matches its key, so the specification is declared only once. The key tells Astro which loader turns that entry into content entries, and lets Nimbus find the collection during configuration and build validation.
To mount several specifications, add one api entry and one apiCollection() line for each. The build fails if a collection key has no api entry, or an api entry has no matching apiCollection() under its key. The error names both files. nimbus-docs check reports the same mismatches without a build.
In astro dev, editing a spec file re-indexes its pages. Editing the api entries restarts the dev server and re-indexes the reference, without a manual restart.
Passing the entry explicitly
apiCollection() also accepts the entry directly: apiCollection({ collection: "api", spec: "./src/api/openapi.yaml" }). Sites created by earlier versions of the recipe use this form, with the Nimbus config in a separate nimbus.config.ts built with defineConfig from @cloudflare/nimbus-docs/config. They keep building unchanged. Moving the config back into astro.config.ts and switching to apiCollection() lets nimbus-docs check validate the config statically, lets add adapter-cloudflare edit it in place, and re-indexes edits to the api entries in astro dev.
Coordinates and routes
Nimbus treats identity and routing separately. A coordinate identifies an API item in citations, cross-version matching, anchors, and the coordinate manifest. A route is the URL of its generated page.
Operations use their OpenAPI operationId as the coordinate:
paths:
/v1/events/{event_id}:
get:
operationId: retrieveEvent
summary: Retrieve an event
tags: [Events]This operation’s coordinate is retrieveEvent. Without a route policy, its first tag and operation ID produce /api/Events/retrieveEvent.
The optional resource-action-v1 policy instead derives routes from HTTP methods and paths:
api: [
{
collection: "api",
spec: "./src/api/openapi.yaml",
requireOperationId: true,
routes: {
convention: "resource-action-v1",
stripPathPrefixes: ["/v1"],
},
},
],Here, Nimbus removes /v1 and publishes the operation at /api/events/retrieve; its coordinate remains retrieveEvent.
Derivation recognizes /<resource> and /<resource>/{parameter} after prefix removal. It maps collection GET/POST to list/create, and member GET/PUT/PATCH/DELETE to retrieve/update/update/delete. Tags do not affect policy routes. Other shapes or unsupported method/shape combinations normally fall back to a normalized coordinate with a build warning; the build fails if that coordinate cannot produce a non-empty route.
An explicit operation override, keyed by the exact usable operationId, takes precedence and can preserve an existing URL or handle a path that cannot be derived:
routes: {
convention: "resource-action-v1",
operations: {
retrieveEvent: "events/get",
},
},Without a usable operationId, Nimbus derives a fallback coordinate from the method and path. requireOperationId: true rejects that fallback, but changing an existing operation ID still changes the coordinate. Webhooks always use their map keys as coordinates and publish below webhooks/<key>; configuring an operation override for a webhook fails the build.
Renaming a coordinate requires updating citations and affects cross-version matching. Changing only a route leaves coordinate-based citations intact, but breaks direct links to the previous URL. Nimbus does not create that redirect automatically; add it in Astro or on the deployment platform.
Link from prose by coordinate
Use an api.ref: destination in Markdown or MDX under src/content:
See how to [retrieve an event](api.ref:api:retrieveEvent).Nimbus resolves the citation during the build:
apiidentifies the API collection.retrieveEventidentifies the operation independently of its route.- A citation without a version targets the API family’s default version.
- An unknown coordinate in a known collection fails the authored-content build and may suggest a close match.
- An unknown collection is warned and rewritten to
#; verify collection names against/nimbus-api/coordinates.jsonso dead citations do not ship.
Pin a historical version only when the prose specifically discusses it:
Review the [v1 operation](api.ref:api@v1:retrieveEvent).Coordinate shapes
Operations are not the only addressable items. Nimbus assigns coordinates to pages and to details within them:
| API item | Coordinate example |
|---|---|
| API root | api |
| Tag | tags.Events |
| Operation | retrieveEvent |
| Request body field | retrieveEvent.name |
| Parameter | retrieveEvent.path.event_id |
| Response | retrieveEvent.response.200 |
| Response field in an additional media type | retrieveEvent.response.200.text-csv.id |
| Schema | Event |
| Schema field | Event.created_at |
| Webhook | delivery.succeeded |
Use /nimbus-api/coordinates.json to inspect the exact coordinates and resolved URLs published by a built site.
Versioned API references
API versions live inside the api entry. This is separate from the top-level versions option used for authored prose documentation. An entry accepts either spec for one version or versions for a family, not both. This example uses the default operation-ID routes; route policies are set independently on each version:
api: [
{
collection: "api",
label: "Acme API",
requireOperationId: true,
versions: [
{
version: "v2",
spec: "./src/api/openapi-v2.yaml",
default: true,
status: "ga",
},
{
version: "v1",
spec: "./src/api/openapi-v1.yaml",
status: "deprecated",
},
],
},
],The version marked default: true owns /api; other versions mount below their version, such as /api/v1. If none is marked, the first version is the default. Nimbus links pages across versions when they share a coordinate. A deprecated version renders its status in the reference UI.
Route policies belong to each version in a version family. This makes URL decisions explicit when two specifications use different base paths or need different overrides.
Build or request rendering
API HTML is prerendered by default. Request rendering first requires the Cloudflare adapter recipe:
npx @cloudflare/nimbus-docs add adapter-cloudflareyarn dlx @cloudflare/nimbus-docs add adapter-cloudflarepnpm dlx @cloudflare/nimbus-docs add adapter-cloudflarebunx @cloudflare/nimbus-docs add adapter-cloudflareWith server output configured, this policy renders only the API collection on request:
rendering: {
default: "build",
collections: {
api: "request",
},
},The recipe’s API catch-all uses Nimbus runtime helpers to resolve either mode. Request rendering changes the canonical HTML pages only. Alternate Markdown versions, coordinate data, search records, sitemaps, and llms.txt indexes remain build products, and requests consume prepared content entries rather than parsing the OpenAPI document.
Prepared code examples
apiCollection() highlights request samples, primary and named request examples, responses, and the examples of additional request body and response media types while it builds the content index. OpenAPI requestBody.content.*.examples entries are available as ApiOperationPage.requestExamples, preserving each key, summary, description, media type, and inline value. External-only examples are not fetched.
User-owned renderers should render highlightedHtml with Astro’s set:html rather than importing Shiki or Astro’s Code component into a request-rendered route:
---
import type { ApiOperationPage } from "@cloudflare/nimbus-docs/api";
interface Props extends Pick<ApiOperationPage, "samples"> {}
const { samples } = Astro.props;
function preparedCode(value: { highlightedHtml?: string }): string {
if (!value.highlightedHtml) {
throw new Error("Nimbus API code was not prepared during content sync.");
}
return value.highlightedHtml;
}
---
{samples.map((sample) => (
<Fragment set:html={preparedCode(sample)} />
))}Treat a missing prepared value as a stale or incorrectly built API index. Rebuild after changing the specification or API renderer types.
See Configuration for the Cloudflare adapter and Wrangler requirements.
Published outputs
For a collection named api, the reference integrates with these routes when their corresponding starter routes are present:
| Route | Purpose |
|---|---|
/api |
Default-version API overview. |
/api/<page-slug> |
Operation, schema, tag, or webhook page. |
/api/<page-slug>/index.md |
Clean Markdown version. |
/api/llms.txt |
API-only llms.txt index. |
/llms.txt and /llms-full.txt |
Site-wide page index and full Markdown documentation. |
/nimbus-api/coordinates.json |
Public coordinate-to-URL manifest. |
The API entries also join the existing Pagefind search, sitemap, and OG-image routes when those features are enabled in the project.
Cite an API hosted elsewhere
A documentation site can cite a reference published by another Nimbus site without mounting or republishing it:
apiReferences: [
{
collection: "api",
manifest: "https://api.example.com/nimbus-api/coordinates.json",
origin: "https://api.example.com",
},
],collection must match the collection key published by the remote manifest. origin is the absolute prefix prepended to site-relative manifest paths. Include the deployment base when the remote reference is hosted below one, for example https://api.example.com/docs.
The remote collection then uses the same prose syntax: api.ref:api:retrieveEvent. Remote references provide citation targets only; they do not add the remote pages to local search or agent outputs.
Nimbus fetches HTTPS manifests during the build. An unavailable or malformed remote manifest produces warnings and its citations resolve to #; it does not stop the build. You can instead commit a manifest and use a project-relative path when builds must work offline. An unreadable local manifest, invalid JSON, or invalid top-level shape fails the build; malformed entries inside an otherwise valid manifest are warned and ignored.
Verify the reference
Run a production build after adding or changing a specification:
pnpm buildConfirm that:
- The build reports the number of indexed API pages.
/apiand one operation page render.- The same operation’s
/index.mdroute returns Markdown. /api/llms.txtlists the reference pages./nimbus-api/coordinates.jsoncontains a known operation ID.- A prose
api.ref:link resolves to the expected route.
For request rendering, test the production Worker locally with Wrangler rather than relying only on Astro’s development server.