Skip to content
Blume
English
Esc
navigateopen⌘Jpreview
On this page

AsyncAPI

Drop in an AsyncAPI spec and get a native event reference — one real page per send and receive operation, in your sidebar and search.

Event-driven APIs use the asyncapi() adapter from blume/reference, listed under reference beside any OpenAPI or GraphQL adapters. It takes the same options as openapi() and renders with the same native renderer. Each send/receive operation becomes a real page with message payload and header schema tables, channel parameters, protocol bindings, an Authorization section derived from the spec’s securitySchemes (server-level and operation-level, alternatives as “or” groups), and a Try it message composer. 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.

import { defineConfig } from "blume";
import { asyncapi } from "blume/reference";

export default defineConfig({
  reference: [asyncapi({ spec: "./asyncapi.yaml" })],
});

That mounts the reference at /events (an overview page) with each operation on its own page beneath it. The spec is either an http(s) URL or a path to a local file in your project, JSON or YAML. As with every reference, it doesn’t add a header tab on its own — point a navigation tab at its route to surface it and scope the operations sidebar:

navigation: {
  tabs: [{ label: "Events", path: "/events" }],
}

Spec versions

AsyncAPI 2.x specs are normalized to 3.x automatically with the official AsyncAPI converter, so publish/subscribe channels map onto send/receive operation pages with stable URLs — later upgrading the spec file itself through the converter moves nothing. The converter is an optional peer dependency, so a site with a 1.x or 2.x spec installs it (npm install @asyncapi/converter); without it the build fails with that install command. A 3.x spec needs nothing extra. Operations group by tag; untagged operations group under their channel address.

Code samples

Code samples are protocol-aware, keyed off the operation’s binding (or its servers’ protocol): wscat and a browser WebSocket snippet for WebSockets, kcat for Kafka, mosquitto_pub/mosquitto_sub for MQTT. codeSamples filters that set, the same way it picks languages on openapi(); a protocol without a supported tool renders the message payload example alone rather than a fabricated client.

Shared options

Everything documented for OpenAPI carries over, playground included: route, sources with label/route, expandSchemas, the per-source indexing flags (seoDescriptionSuffix too — the generated sentence names the channel and action instead of an endpoint), and search indexing by operation summary and tag.

Embedding Scalar instead

asyncapi() always renders Blume’s own pages. To embed Scalar’s UI instead, list a scalar() adapter pointed at the AsyncAPI document — its embed detects the document type and renders channels, operations, messages, and a Models section. Scalar has no AsyncAPI playground of its own, so that swap trades the composer away, and only noindex of the per-source controls applies to it.

Try it for events

Operation pages rendered natively ship a Try it panel here too, on the same terms as the OpenAPI panel: server-rendered collapsed, with its JavaScript loaded only when a reader first opens it.

Whatever the protocol, the panel opens with a payload editor prefilled from the message’s examples — or, when the message declares none, from a value sampled out of the payload schema — validated against the message payload schema as you type. Under it sit an input per channel parameter and a server picker fed by the channel’s servers, with a free-text field for any other URL. The protocol-aware code samples stay in lockstep with the form exactly as curl, js, and python do on an HTTP operation: the channel address template is filled in with the parameter values you type, so a copied wscat, WebSocket, kcat, or mosquitto_pub snippet matches what the form says.

Live connect is WebSocket-only. On a ws or wss binding the panel connects to the resolved channel URL, shows the connection state, and logs every frame with a timestamp. AsyncAPI 3 states an action from the API’s side, and the panel follows it: a receive operation is one the API receives from you, so it gets a Send button that publishes the composed payload; a send operation only streams messages at you, so it connects and logs. There’s no reconnect logic — once a socket closes, it stays closed until you connect again. Kafka, MQTT, AMQP, and every other protocol get the composer and the copyable CLI samples, and the panel says as much on the page: Blume doesn’t fake broker connectivity from a browser tab.

asyncapi()’s playground mirrors openapi()’s — on by default with the native renderer, and false is the entire off switch:

reference: [asyncapi({ spec: "./asyncapi.yaml", playground: false })],

The event composer collects no broker credentials. Each operation page’s Authorization section documents what the broker expects, and a WebSocket connect carries only what’s already in the URL. Nothing is persisted for event operations.

Last updated on September 24, 2026

Was this page helpful?