Skip to content
Blume is now publicly available.
Blume
Esc
navigateopen⌘Jpreview
On this page

OpenAPI / AsyncAPI

Drop in an OpenAPI spec and get a native API reference — one real page per operation, in your sidebar and search.

Point Blume at an OpenAPI spec and it generates a native API reference: one real page per operation, grouped by tag in a tab-scoped sidebar, with schema tables, request/response examples, and generated code samples. Because each operation is a genuine Blume page, it gets its own URL, shows up in site search and llms.txt, and gets an Open Graph image — the same as any hand-written doc. The config below points Blume at the public Petstore spec as an example.

openapi: {
  enabled: true,
  spec: "https://petstore3.swagger.io/api/v3/openapi.json",
}

That mounts the reference at /reference (an overview page) with each operation at /reference/<tag>/<operation>. The spec is either an http(s) URL or a path to a local file in your project. Blume parses it with Scalar’s OpenAPI parser — Swagger 2.0 and OpenAPI 3.0 specs are upgraded to 3.1 automatically.

The reference doesn’t add a header tab on its own. To surface it, point a navigation tab at its route — this also scopes the operations sidebar for the native renderer:

navigation: {
  tabs: [{ label: "API", path: "/reference" }],
}

A local spec

A relative path is resolved from your project root and read at build time. Both JSON and YAML work:

openapi: {
  enabled: true,
  spec: "./openapi.yaml",
}

Route

route controls where the reference mounts — the overview page and the prefix for every operation route (and the route you point a navigation tab at):

openapi: {
  enabled: true,
  route: "/api",   // overview at /api, operations at /api/<tag>/<operation>
  spec: "./openapi.yaml",
}

Code samples and schemas

codeSamples picks which languages render per operation (built in: curl, js, python); expandSchemas starts nested schema rows expanded rather than collapsed:

openapi: {
  enabled: true,
  spec: "./openapi.yaml",
  codeSamples: ["curl", "js"],
  expandSchemas: true,
}

Multiple specs

Use sources to publish more than one spec. Each source gets its own overview route, operation pages, and header tab. Give each a label (used for the tab and to derive its route), or set an explicit route:

openapi: {
  enabled: true,
  sources: [
    { label: "Public API", spec: "./public.json" },   // → /reference/public-api
    { label: "Admin API", route: "/admin", spec: "./admin.json" },
  ],
}

spec is shorthand for a single-entry sources, so you only reach for sources when you have more than one.

Per-source indexing

Generated pages participate in search, llms.txt, and crawler indexing by default. A secondary or overlapping spec can opt out of any surface without hiding its pages or removing it from navigation:

openapi: {
  enabled: true,
  sources: [
    { label: "Public API", route: "/api", spec: "./public.json" },
    {
      label: "Platform API",
      route: "/platform",
      spec: "./platform.json",
      includeInSearch: false,
      includeInLlms: false,
      noindex: true,
    },
  ],
}
  • includeInSearch: false keeps the source’s overview and operations out of site search.
  • includeInLlms: false keeps them out of both llms.txt files.
  • noindex: true adds crawler noindex metadata and removes the pages from the sitemap.

With the Scalar renderer, only noindex applies — a Scalar-rendered reference already sits outside Blume’s search and llms.txt, so the two include* settings have nothing to act on there.

Authorization

Operations that declare security requirements render an Authorization section above their parameters, and the generated code samples send a placeholder credential (Authorization: Bearer YOUR_TOKEN, an API-key header, or a query key — whatever the scheme calls for). There’s nothing to configure: Blume reads security from the spec, so the reference always matches what the API actually enforces.

The OpenAPI semantics carry over as written:

  • An operation’s own security overrides the document’s root default; security: [] marks it public and renders no Authorization section.
  • Multiple requirement entries are alternatives — rendered as “or” groups; every scheme inside one entry is required together. The first alternative feeds the code samples.
  • An empty {} entry means auth is optional for that operation, and the section says so.
  • OAuth2 scopes are listed per scheme; scheme descriptions from components.securitySchemes render inline.

The Scalar renderer

The native renderer is the default. If you’d rather embed Scalar’s self-contained API reference — its own sidebar, search, theme, and “Try it” playground on a single route — set renderer: "scalar":

openapi: {
  enabled: true,
  renderer: "scalar",
  spec: "./openapi.yaml",
  theme: "purple",   // a Scalar theme name (Scalar renderer only)
}

A Scalar-rendered reference is a self-contained embed on its own route — it doesn’t weave into Blume’s sidebar, search, or llms.txt. Its “Try it” playground calls your target API directly from the browser (Blume doesn’t proxy), so the API must allow cross-origin requests from the docs site (Access-Control-Allow-Origin). theme and the playground apply to the Scalar renderer only.

Passing Scalar options

theme is a shorthand for the one option most people reach for, but Scalar supports many more. A scalar object forwards any Scalar configuration straight to the embedded reference — Blume doesn’t gate the keys, so anything Scalar accepts flows through:

openapi: {
  enabled: true,
  renderer: "scalar",
  spec: "./openapi.yaml",
  scalar: {
    localization: { locale: "es" },   // translate Scalar's own UI
    agent: { disabled: true },         // disable the Scalar Agent
    hideTestRequestButton: true,
    orderSchemaPropertiesBy: "preserve",
  },
}

Blume’s own i18n translates the docs chrome, but Scalar has a separate localization system — set scalar.localization.locale to translate the embedded reference too. Options in the scalar object win over Blume’s derived config, so anything set here (including theme, customCss, or the spec content/url) overrides Blume’s defaults. The same scalar block works on the asyncapi reference.

AsyncAPI

Event-driven APIs use a sibling asyncapi block with the same shape. AsyncAPI is rendered by Scalar (the native renderer is OpenAPI-only for now); only the default route differs (/events):

asyncapi: {
  enabled: true,
  spec: "./asyncapi.yaml",
}

Last updated on August 3, 2026

Was this page helpful?