Configuration
On this page
Every component (the full widget, a standalone section, a single item, or a provider) takes the same config object. What you pass is merged over the defaults, so you only specify what you want to change.
import { AsyncAPI } from "apiuikit";
<AsyncAPI
asyncapi={doc}
config={{
show: { sidebar: false },
expand: { schemas: true },
sidePanel: { containment: "component" },
}}
/>;The shape is exported as ConfigInterface, and the defaults are exported as defaultConfig, which is useful when you want to extend a value rather than replace it:
import { defaultConfig, type ConfigInterface } from "apiuikit";
const config: ConfigInterface = {
theme: { colors: { primary: defaultConfig.theme?.colors?.primary } },
};show#
Switches individual sections and controls off. Everything listed here is on by default except messageExamples and tryIt.
| Option | Default | What it controls |
|---|---|---|
sidebar |
true |
The widget's navigation sidebar. |
info |
true |
The document's info block. |
servers |
true |
The servers section. |
search |
true |
Search, which lives in the sidebar. |
operations |
true |
The operations section. |
messages |
true |
The messages section. |
messageExamples |
false |
Payload examples inside messages. |
schemas |
true |
The schemas section. |
errors |
true |
Parser and validation errors. |
endpoints |
true |
OpenAPI only: the Endpoints tab. |
webhooks |
true |
OpenAPI 3.1 only: the Webhooks tab. It only appears at all when the document declares webhooks. |
extensions |
true |
Known x-* spec extensions. |
codeSamples |
true |
OpenAPI only: per-operation cURL, JavaScript, and Python request examples. |
copyMarkdown |
true |
The floating "Copy for LLM" / "View as Markdown" button. |
tryIt |
false |
A Try it button in the operation side panel's header. See Try it. |
config={{ show: { sidebar: false, search: false, codeSamples: false } }}Switching the sidebar off also removes search, since search lives inside it.
Try it#
show.tryIt adds a Try it button to the operation side panel's header:
- OpenAPI: a request builder that fills in parameters, auth, and a body, sends the request from the reader's browser, and shows the response.
- AsyncAPI: a WebSocket client that connects to the operation's
wsorwssserver, composes and validates messages, and logs frames in both directions. Operations with no WebSocket server show no button.
config={{ show: { tryIt: true } }}There is nothing to install. apiuikit depends on both panels and loads the one it needs on demand. While tryIt is off, that code is never fetched, so your readers download nothing extra.
Turn it on deliberately. It turns a documentation page into one that collects credentials from readers: API keys, passwords, tokens, and OAuth2 client secrets. The OpenAPI panel keeps them in sessionStorage for the tab's lifetime, where any script on the page can read them. The AsyncAPI panel keeps them in memory only. Either way, requests and connections go to whichever host the document's servers entry names, so if you render specs you don't control, the spec decides where readers' credentials are sent.
For other layouts (a full operation tab, or a row inside the Reference panel) or for options such as a CORS proxy, allowedHosts, or credential providers, install the OpenAPI Try it or WebSocket Try it plugin and register it with plugins.
expand#
Whether collapsible content starts open.
| Option | Default | What it controls |
|---|---|---|
schemas |
false |
Nested schema tree nodes: object properties, array items, and so on. The top level of each schema is always visible regardless. |
messageExamples |
false |
Message example blocks. |
Leaving schemas collapsed is usually right for a page with several large schemas; expand it when a page documents one small payload and the extra clicks are just friction.
topOffset#
A host-page safe area, in pixels, above the widget's fixed and sticky controls. Set it to the height of a fixed or sticky site navbar. The navigation spine, search, Copy-as-Markdown, search overlay, sticky content tabs, and component-contained side panels all respect it. Defaults to 0.
config={{ topOffset: 64 }}A component-contained side panel can override this with sidePanel.topOffset if the panel needs a different clearance than the rest of the widget.
sidePanel#
Where an operation's side panel is clipped when it opens.
| Option | Default | Values |
|---|---|---|
containment |
"viewport" |
"viewport" | "component" |
topOffset |
config.topOffset |
number |
"viewport" lets the panel cover the whole browser window, which is what you want when the widget is the page. "component" clips it to the widget's own root element. Use it whenever the widget is embedded inside a page that has its own chrome, so the panel can't cover your header or escape its frame.
config={{ sidePanel: { containment: "component" } }}The overlay is a fixed layer sized from either the window or the widget root. That means two things when you pick "component":
- The panel is clipped to the widget's root, not to whatever wrapper you put around it. Give the widget itself the height and the overflow — a scrolling wrapper around an unbounded widget will still let the overlay measure the full document.
- A host navbar sitting outside the widget cannot be inferred from that root.
topOffset(here, or the widget-widetopOffsetabove) reserves that safe area. It has no effect whencontainmentis"viewport".
config={{ sidePanel: { containment: "component", topOffset: 64 } }}theme#
Colours, in three parts: a brand scale applied in both modes, per-mode surface and text colours, and the schema tree's depth palette.
config={{
theme: {
mode: "system",
colors: {
primary: { 50: "#ddf4ff", 300: "#54aeff", 600: "#1f6feb", 700: "#0d419d" },
},
light: {
background: "#f8fafc",
surface: "#ffffff",
border: "#e2e8f0",
textPrimary: "#1e293b",
textSecondary: "#475569",
textMuted: "#64748b",
},
dark: {
background: "#0d1117",
surface: "#161b22",
border: "#30363d",
textPrimary: "#c9d1d9",
textSecondary: "#8b949e",
textMuted: "#6e7681",
},
depthColors: ["#14b8a6", "#22c55e", "#84cc16"],
},
}}colorstakesprimary,secondary, andneutralscales, each with the steps50,100,200,300,500,600,700. They apply regardless of which mode is active.modepicks which palette renders:"light","dark", or"system"(follows the OSprefers-color-schemesetting and updates live if it changes). Left unset, apiuikit falls back to whichever single one oflight/darkyou provided —lightwins if you provided both, or neither.lightanddarkeach takebackground,surface,border,textPrimary,textSecondary, andtextMuted. Pass both to support switching between them at runtime viamode— pass only one if you never intend to switch.depthColorscolours the schema tree's depth-indicator lines and their labels, cycling by nesting level. Any length works; deeper nesting repeats the palette from the start. The default is teal, green, lime, blue, cyan, violet.
Define both palettes once and let mode do the switching — no need to rebuild the theme object yourself:
// Follow the OS setting automatically:
config={{ theme: { ...theme, mode: "system" } }}
// Or sync with your own toggle by changing just one field:
config={{ theme: { ...theme, mode: isDark ? "dark" : "light" } }}markdown#
Controls what the "View as Markdown" button opens.
| Option | Default | Type |
|---|---|---|
url |
none | string | (target: MarkdownTarget) => string | null | undefined |
With nothing set, the button generates a throwaway blob: URL that is ephemeral, unshareable, and invisible to crawlers. Point it at a URL you serve instead:
config={{ markdown: { url: "https://example.com/api/asyncapi.md" } }}Pass a function to decide per target. It receives a MarkdownTarget that is either the whole document or a single operation, and returning null falls back to the generated blob URL for anything you don't serve:
config={{
markdown: {
url: (target) => {
if (target.kind === "document") return "/docs/api.md";
if ("path" in target) return `/docs/api/${target.method}${target.path}.md`;
return null;
},
},
}}Operation targets are discriminated by spec: OpenAPI operations carry method and path, AsyncAPI operations carry id. See AI Export for the build-time helpers that generate those files.
sidebar#
| Option | Default | What it controls |
|---|---|---|
useChannelAddressAsIdentifier |
true |
Whether sidebar entries are labelled with the channel address rather than the channel key. |
parserOptions#
Passed through to the underlying parser by the AsyncAPIRenderer and OpenAPIRenderer entry points, which take a raw string. It has no effect on AsyncAPI and OpenAPI, which take an already-resolved document. See With Parser.