---
title: "API UI"
description: "API UI serves as the rendering layer for API documentation, transforming machine-readable specifications (OpenAPI and AsyncAPI) into interactive, human-readable documentation. It acts as a bridge b..."
last_updated: "2026-07-02T09:46:38.944344+00:00"
canonical_url: "https://www.doc0.dev/docs/e8872a72-1909-479c-b585-dc74c6e26726/technical/api-documentation/api-ui"
---

<details>
<summary>Relevant source files</summary>

The following files were used as context for generating this wiki page:

- [packages/openapi/src/ui/operation/index.tsx](https://github.com/blade47/fumadocs/blob/main/packages/openapi/src/ui/operation/index.tsx)
- [packages/asyncapi/src/ui/operation/index.tsx](https://github.com/blade47/fumadocs/blob/main/packages/asyncapi/src/ui/operation/index.tsx)
- [packages/openapi/src/ui/operation/usage-tabs.tsx](https://github.com/blade47/fumadocs/blob/main/packages/openapi/src/ui/operation/usage-tabs.tsx)
- [packages/asyncapi/src/ui/contexts/api.tsx](https://github.com/blade47/fumadocs/blob/main/packages/asyncapi/src/ui/contexts/api.tsx)
- [packages/api-docs/src/components/schema/client.tsx](https://github.com/blade47/fumadocs/blob/main/packages/api-docs/src/components/schema/client.tsx)
- [packages/asyncapi/src/ui/components/server-select.tsx](https://github.com/blade47/fumadocs/blob/main/packages/asyncapi/src/ui/components/server-select.tsx)
- [packages/openapi/src/ui/contexts/api.tsx](https://github.com/blade47/fumadocs/blob/main/packages/openapi/src/ui/contexts/api.tsx)
- [packages/openapi/src/ui/operation/response-tabs.tsx](https://github.com/blade47/fumadocs/blob/main/packages/openapi/src/ui/operation/response-tabs.tsx)
- [packages/asyncapi/src/ui/operation/message-examples.tsx](https://github.com/blade47/fumadocs/blob/main/packages/asyncapi/src/ui/operation/message-examples.tsx)
- [packages/asyncapi/src/ui/bindings/shared.tsx](https://github.com/blade47/fumadocs/blob/main/packages/asyncapi/src/ui/bindings/shared.tsx)
- [packages/asyncapi/src/ui/api-page.tsx](https://github.com/blade47/fumadocs/blob/main/packages/asyncapi/src/ui/api-page.tsx)
- [packages/openapi/src/ui/operation/request-tabs.tsx](https://github.com/blade47/fumadocs/blob/main/packages/openapi/src/ui/operation/request-tabs.tsx)
- [packages/asyncapi/src/ui/bindings/protocols/solace.tsx](https://github.com/blade47/fumadocs/blob/main/packages/asyncapi/src/ui/bindings/protocols/solace.tsx)
- [packages/asyncapi/src/ui/bindings/protocols/amqp.tsx](https://github.com/blade47/fumadocs/blob/main/packages/asyncapi/src/ui/bindings/protocols/amqp.tsx)
- [packages/asyncapi/src/ui/bindings/protocols/http.tsx](https://github.com/blade47/fumadocs/blob/main/packages/asyncapi/src/ui/bindings/protocols/http.tsx)
- [packages/asyncapi/src/ui/bindings/accordion-bindings.tsx](https://github.com/blade47/fumadocs/blob/main/packages/asyncapi/src/ui/bindings/accordion-bindings.tsx)
- [packages/openapi/src/ui/index.tsx](https://github.com/blade47/fumadocs/blob/main/packages/openapi/src/ui/index.tsx)
- [packages/openapi/src/ui/base.tsx](https://github.com/blade47/fumadocs/blob/main/packages/openapi/src/ui/base.tsx)
- [packages/asyncapi/src/ui/bindings/protocols/mqtt.tsx](https://github.com/blade47/fumadocs/blob/main/packages/asyncapi/src/ui/bindings/protocols/mqtt.tsx)
- [packages/asyncapi/src/ui/index.tsx](https://github.com/blade47/fumadocs/blob/main/packages/asyncapi/src/ui/index.tsx)
- [packages/asyncapi/src/ui/bindings/protocols/pulsar.tsx](https://github.com/blade47/fumadocs/blob/main/packages/asyncapi/src/ui/bindings/protocols/pulsar.tsx)
- [packages/asyncapi/src/ui/bindings/protocols/ibmmq.tsx](https://github.com/blade47/fumadocs/blob/main/packages/asyncapi/src/ui/bindings/protocols/ibmmq.tsx)
- [packages/asyncapi/src/ui/bindings/protocols/anypointmq.tsx](https://github.com/blade47/fumadocs/blob/main/packages/asyncapi/src/ui/bindings/protocols/anypointmq.tsx)
- [packages/asyncapi/src/ui/bindings/protocols/jms.tsx](https://github.com/blade47/fumadocs/blob/main/packages/asyncapi/src/ui/bindings/protocols/jms.tsx)
- [packages/asyncapi/src/ui/bindings/protocols/kafka.tsx](https://github.com/blade47/fumadocs/blob/main/packages/asyncapi/src/ui/bindings/protocols/kafka.tsx)
- [packages/asyncapi/src/ui/bindings/protocols/sqs.tsx](https://github.com/blade47/fumadocs/blob/main/packages/asyncapi/src/ui/bindings/protocols/sqs.tsx)
- [packages/asyncapi/src/ui/bindings/protocols/index.ts](https://github.com/blade47/fumadocs/blob/main/packages/asyncapi/src/ui/bindings/protocols/index.ts)
- [packages/asyncapi/src/ui/bindings/protocols/sns.tsx](https://github.com/blade47/fumadocs/blob/main/packages/asyncapi/src/ui/bindings/protocols/sns.tsx)
- [packages/asyncapi/src/ui/bindings/protocols/nats.tsx](https://github.com/blade47/fumadocs/blob/main/packages/asyncapi/src/ui/bindings/protocols/nats.tsx)
- [packages/asyncapi/src/ui/bindings/protocols/unknown.tsx](https://github.com/blade47/fumadocs/blob/main/packages/asyncapi/src/ui/bindings/protocols/unknown.tsx)
</details>

API UI serves as the rendering layer for API documentation, transforming machine-readable specifications (OpenAPI and AsyncAPI) into interactive, human-readable documentation. It acts as a bridge between the core document structure and the presentation layer, enabling features like request playground testing, code snippet generation, and complex protocol binding visualization.

By decoupling document parsing from UI rendering, the API UI system enables a pluggable architecture. Developers can provide custom renderers for different components of the API lifecycle—such as operations, response tabs, or playground UI—allowing for deep customization within a standard documentation framework.

The system relies heavily on context providers for state management, particularly for global state like server selection and render-time configurations (e.g., media type adapters, shiki highlighters). This ensures consistent behavior across different documentation components while maintaining the performance benefits of a client-side reactive rendering pipeline.

## Operation Rendering Mechanism

The `Operation` component (found in both OpenAPI and AsyncAPI) is the central entry point for rendering API documentation. In the OpenAPI implementation, it handles the lifecycle of an individual operation by aggregating sections such as Request Body, Parameters, Responses, and Callbacks.

The control flow follows a structured layout approach:
1. It initializes the `RenderContext` to access configuration and schema data.
2. If `showTitle` is true, it renders the heading, applying an `id` for auto-anchoring (based on summary, operationId, or path).
3. It conditionally branches based on the operation type (`operation` vs `webhook`), and renders subsections sequentially, injecting the results into a `renderOperationLayout` slot system if provided.

Sources: [packages/openapi/src/ui/operation/index.tsx:42-408](https://github.com/blade47/fumadocs/blob/main/packages/openapi/src/ui/operation/index.tsx#L42-L408)

```mermaid
flowchart TD
    A["Operation"] --> B{"Type?"}
    B -->|operation| C["Render header, playground, auth, params, body, responses"]
    B -->|webhook| D["Render layout"]
    C --> E["Inject into renderOperationLayout slots"]
    E --> F["Wrap in ServerProvider (if servers exist)"]
```
Sources: [packages/openapi/src/ui/operation/index.tsx:318-408](https://github.com/blade47/fumadocs/blob/main/packages/openapi/src/ui/operation/index.tsx#L318-L408)

## Server State Management

The `ServerProvider` manages the lifecycle of server configurations, which are critical for playground interactions and example generation. It utilizes `localStorage` to persist user-selected server configurations (selected ID and variables), ensuring that user preferences remain consistent across page reloads.

- `getDefaultValues`: Extracts initial variable values from the server definition.
- `setServerVariables`: Merges new variable values into the existing state and triggers a `localStorage` update.
- `setServer`: Switches the active server and recalculates variables based on the new definition.

Sources: [packages/openapi/src/ui/contexts/api.tsx:47-123](https://github.com/blade47/fumadocs/blob/main/packages/openapi/src/ui/contexts/api.tsx#L47-L123), [packages/asyncapi/src/ui/contexts/api.tsx:47-124](https://github.com/blade47/fumadocs/blob/main/packages/asyncapi/src/ui/contexts/api.tsx#L47-L124)

> [!NOTE]
> When multiple OpenAPI/AsyncAPI instances exist on the same host, use `storageKeyPrefix` to prevent state conflicts between `localStorage` keys.

Sources: [packages/openapi/src/ui/index.tsx:212-218](https://github.com/blade47/fumadocs/blob/main/packages/openapi/src/ui/index.tsx#L212-L218)

## Protocol Binding Visualization

The AsyncAPI UI subsystem supports complex protocol-specific bindings through a modular registry pattern. Each binding type (e.g., Kafka, AMQP, MQTT) defines its own UI components for rendering server, channel, operation, or message configurations.

The `AccordionBindings` component dynamically resolves the appropriate renderer by looking up the binding protocol in the `protocolBindings` registry.

```typescript
// The lookup pattern in accordion-bindings.tsx
const definition = getProtocolBinding(entry.protocol);
// definition.Server, definition.Channel, etc., provide UI for specific fields.
```
Sources: [packages/asyncapi/src/ui/bindings/accordion-bindings.tsx:11-47](https://github.com/blade47/fumadocs/blob/main/packages/asyncapi/src/ui/bindings/accordion-bindings.tsx#L11-L47)

### Available Protocol Bindings

| Protocol | Label | Key Source |
| :--- | :--- | :--- |
| Kafka | Kafka | [kafka.tsx:189-199](https://github.com/blade47/fumadocs/blob/main/packages/asyncapi/src/ui/bindings/protocols/kafka.tsx#L189-L199) |
| AMQP | AMQP | [amqp.tsx:215-222](https://github.com/blade47/fumadocs/blob/main/packages/asyncapi/src/ui/bindings/protocols/amqp.tsx#L215-L222) |
| MQTT | MQTT | [mqtt.tsx:209-217](https://github.com/blade47/fumadocs/blob/main/packages/asyncapi/src/ui/bindings/protocols/mqtt.tsx#L209-L217) |
| Solace | Solace | [solace.tsx:140-146](https://github.com/blade47/fumadocs/blob/main/packages/asyncapi/src/ui/bindings/protocols/solace.tsx#L140-L146) |
| Pulsar | Apache Pulsar | [pulsar.tsx:109-116](https://github.com/blade47/fumadocs/blob/main/packages/asyncapi/src/ui/bindings/protocols/pulsar.tsx#L109-L116) |

Sources: [packages/asyncapi/src/ui/bindings/protocols/index.ts:25-45](https://github.com/blade47/fumadocs/blob/main/packages/asyncapi/src/ui/bindings/protocols/index.ts#L25-L45)

## Schema UI and Interaction

The `SchemaUI` component provides a recursive interface for browsing complex JSON schema types. It maintains its state through a `Context` that tracks the current path into the schema object.

- `decodePath`: Parses a URL-encoded string to determine the current browsing depth.
- `ObjectProperty`: Renders an individual schema property and provides a "copy link" functionality that encodes the current path into the clipboard URL.

> [!CAUTION]
> The `decodePath` mechanism expects path segments separated by `|` and `\0`. Tampering with these query parameters in the URL may cause rendering failures in the `SchemaUI`.

Sources: [packages/api-docs/src/components/schema/client.tsx:603-616](https://github.com/blade47/fumadocs/blob/main/packages/api-docs/src/components/schema/client.tsx#L603-L616)

## Example Generation Workflow

The API UI generates code usage examples using a registry pattern. When a user changes the selected example (e.g., from a dropdown), the `UsageTabs` component broadcasts this event through a listener pattern.

### Call Chain: Changing Example
1. `UsageTabsSelector` triggers `setKey` from `useOperationContext`.
2. `useOperationContext` propagates the new state to all registered listeners.
3. `UsageTab` (the active tab) receives the update via `addListener`.
4. `codegen.generate` is invoked with the new data to refresh the displayed code block.

Sources: [packages/openapi/src/ui/operation/usage-tabs.tsx:102-180](https://github.com/blade47/fumadocs/blob/main/packages/openapi/src/ui/operation/usage-tabs.tsx#L102-L180)

## Design Trade-offs

| Design Choice | Benefit | Cost |
| :--- | :--- | :--- |
| Slot-based layout rendering | High flexibility for custom documentation designs | Higher implementation complexity for default renderers |
| JSON Schema dereferencing | Simplifies rendering logic (no recursive refs) | Increased memory usage for large bundled specifications |
| Context-based state | Simplifies cross-component data access | Forces components to be nested within specific providers |

Sources: [packages/openapi/src/ui/base.tsx:97-139](https://github.com/blade47/fumadocs/blob/main/packages/openapi/src/ui/base.tsx#L97-L139), [packages/openapi/src/ui/operation/index.tsx:318-389](https://github.com/blade47/fumadocs/blob/main/packages/openapi/src/ui/operation/index.tsx#L318-L389)

## Related

- [OpenAPI Generation](https://www.doc0.dev/docs/e8872a72-1909-479c-b585-dc74c6e26726/technical/api-documentation/openapi-generation)
- [AsyncAPI Generation](https://www.doc0.dev/docs/e8872a72-1909-479c-b585-dc74c6e26726/technical/api-documentation/asyncapi-generation)


## Sitemap

See the full [sitemap](https://www.doc0.dev/docs/e8872a72-1909-479c-b585-dc74c6e26726/llms.txt) for all pages in this wiki.
