---
title: "OpenAPI Interactive UI"
description: "OpenAPI Interactive UI provides a component-based documentation rendering layer built on top of parsed OpenAPI and Swagger specifications, parsing Markdown processors, server state providers, and c..."
last_updated: "2026-10-12T07:53:59.986642+00:00"
canonical_url: "https://www.doc0.dev/docs/e8872a72-1909-479c-b585-dc74c6e26726/technical/api-documentation/openapi-interactive-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/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/ui/operation/index.tsx)
- [packages/openapi/src/ui/base.tsx](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/ui/base.tsx)
- [packages/asyncapi/src/ui/operation/index.tsx](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/asyncapi/src/ui/operation/index.tsx)
- [packages/api-docs/src/components/schema/client.tsx](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/api-docs/src/components/schema/client.tsx)
- [packages/asyncapi/src/ui/index.tsx](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/asyncapi/src/ui/index.tsx)
- [packages/openapi/src/server/index.tsx](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/server/index.tsx)
- [packages/openapi/src/ui/operation/usage-tabs.tsx](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/ui/operation/usage-tabs.tsx)
- [packages/openapi/src/scalar/client.tsx](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/scalar/client.tsx)
- [packages/openapi/src/ui/operation/request-tabs.tsx](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/ui/operation/request-tabs.tsx)
- [packages/openapi/src/ui/index.tsx](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/ui/index.tsx)
- [packages/api-docs/src/components/schema/index.tsx](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/api-docs/src/components/schema/index.tsx)
- [packages/openapi/src/ui/operation/response-tabs.tsx](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/ui/operation/response-tabs.tsx)
- [packages/asyncapi/src/ui/api-page.tsx](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/asyncapi/src/ui/api-page.tsx)
- [packages/openapi/src/scalar/index.tsx](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/scalar/index.tsx)
- [packages/asyncapi/src/ui/bindings/protocols/http.tsx](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/asyncapi/src/ui/bindings/protocols/http.tsx)
- [packages/asyncapi/src/server/index.tsx](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/asyncapi/src/server/index.tsx)
- [packages/openapi/src/index.ts](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/index.ts)
- [packages/asyncapi/src/ui/bindings/shared.tsx](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/asyncapi/src/ui/bindings/shared.tsx)
- [packages/asyncapi/src/ui/contexts/api.tsx](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/asyncapi/src/ui/contexts/api.tsx)
- [packages/asyncapi/src/ui/bindings/accordion-bindings.tsx](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/asyncapi/src/ui/bindings/accordion-bindings.tsx)
- [packages/openapi/src/ui/components/markdown.tsx](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/ui/components/markdown.tsx)
- [packages/openapi/src/ui/contexts/api.tsx](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/ui/contexts/api.tsx)
- [packages/openapi/src/utils/get-example-requests.ts](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/utils/get-example-requests.ts)
- [packages/openapi/src/ui/components/codeblock.tsx](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/ui/components/codeblock.tsx)
- [packages/asyncapi/src/ui/components/markdown.tsx](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/asyncapi/src/ui/components/markdown.tsx)
- [packages/openapi/src/ui/operation/context.tsx](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/ui/operation/context.tsx)
- [packages/openapi/src/types.ts](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/types.ts)
- [packages/openapi/src/requests/media/encode.ts](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/requests/media/encode.ts)
- [packages/radix-ui/src/components/ui/popover.tsx](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/radix-ui/src/components/ui/popover.tsx)
</details>

## Overview

OpenAPI Interactive UI provides a component-based documentation rendering layer built on top of parsed OpenAPI and Swagger specifications, parsing Markdown processors, server state providers, and customizable page layouts into interactive API documentation pages. Sources: [packages/openapi/src/ui/base.tsx](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/ui/base.tsx#L59-L80), [packages/openapi/src/server/index.tsx](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/server/index.tsx#L149-L233), [packages/openapi/src/ui/index.tsx](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/ui/index.tsx#L109-L154)

By leveraging [API Docs Primitives](https://www.doc0.dev/docs/e8872a72-1909-479c-b585-dc74c6e26726/technical/api-documentation/api-docs-primitives) and [Code Sample Generators](https://www.doc0.dev/docs/e8872a72-1909-479c-b585-dc74c6e26726/technical/api-documentation/code-sample-generators), the system parses endpoint operations, request bodies, response status codes, and security schemes into rich interactive cards, tabbed request and response viewers, and copy-enabled code blocks. Sources: [packages/openapi/src/ui/operation/index.tsx](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/ui/operation/index.tsx#L42-L255), [packages/openapi/src/ui/operation/request-tabs.tsx](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/ui/operation/request-tabs.tsx#L30-L149), [packages/openapi/src/ui/operation/response-tabs.tsx](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/ui/operation/response-tabs.tsx#L53-L159)

## Page Creation and Runtime Context

### Initialization and Rendering Pipeline

OpenAPI documentation pages initialize their rendering contexts, Markdown processors, and server state by invoking base factory functions that construct client components. The primary initialization sequence proceeds through the following call chain: `createOpenAPIPageBase` → `Schema` → `SchemaUI`. 

1. `createOpenAPIPageBase` establishes the base React component, sets up the remark and rehype Markdown processing pipeline with `remarkGfm` and `remarkRehype`, dereferences bundled documents using `dereferenceBundledDocument`, and configures the `RenderContext`. Sources: [packages/openapi/src/ui/base.tsx](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/ui/base.tsx#L38-L98)
2. `Schema` receives the resolved schema and user options, invokes `generateSchemaUI` to compute schema hierarchies and reference tables, and passes the generated data to the client component. Sources: [packages/api-docs/src/components/schema/index.tsx](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/api-docs/src/components/schema/index.tsx#L89-L112)
3. `SchemaUI` establishes anchor identifiers using `useAnchorId`, tracks object inspection navigation paths via component state, and hydrates interactive popovers or object property trees. Sources: [packages/api-docs/src/components/schema/client.tsx](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/api-docs/src/components/schema/client.tsx#L83-L184)

```mermaid
sequenceDiagram
    participant base.tsx
    participant index.tsx (api-docs)
    participant client.tsx
    base.tsx->>base.tsx: createOpenAPIPageBase()
    base.tsx->>index.tsx (api-docs): Schema()
    index.tsx (api-docs)->>client.tsx: SchemaUI()
```

Sources: [packages/openapi/src/ui/base.tsx:38-98](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/ui/base.tsx#L38-L98), [packages/api-docs/src/components/schema/index.tsx:89-112](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/api-docs/src/components/schema/index.tsx#L89-L112), [packages/api-docs/src/components/schema/client.tsx:83-184](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/api-docs/src/components/schema/client.tsx#L83-L184)

> [!NOTE]
> `createOpenAPIPageBase` accepts an optional `shiki` factory for [syntax highlighting](https://www.doc0.dev/docs/e8872a72-1909-479c-b585-dc74c6e26726/technical/core-architecture/syntax-highlighting) alongside custom options for generating TypeScript definitions via `compile` from `@fumari/json-schema-ts`. Sources: [packages/openapi/src/ui/base.tsx](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/ui/base.tsx#L38-L56)

### Server State and Context Providers

Server state management is coordinated through `ServerProvider` and `RenderContextProvider`, which manage active API servers, URL variables, and local storage persistence. The context infrastructure relies on specific React contexts to supply runtime options across operation cards and schema renderers.

| Context Provider | Hook | Purpose |
| :--- | :--- | :--- |
| `RenderContextProvider` | `useRenderContext()` | Supplies the global `RenderContext` containing schema references, proxy URLs, Shiki options, and code usage generators. |
| `ServerProvider` | `useServerContext()` | Manages active server selection, server variables, and persists selected configurations in local storage. |

Sources: [packages/openapi/src/ui/contexts/api.tsx:20-45](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/ui/contexts/api.tsx#L20-L45), [packages/openapi/src/ui/base.tsx:32-32](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/ui/base.tsx#L32-L32)

> [!WARNING]
> Both `useRenderContext` and `useServerContext` throw an error if called outside of their respective provider hierarchy, requiring components to be nested under `<ApiProvider />` or the corresponding provider wrapper. Sources: [packages/openapi/src/ui/contexts/api.tsx](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/ui/contexts/api.tsx#L23-L35)

> [!TIP]
> `ServerProvider` initializes the active server configuration using `storageKeyPrefix` (defaulting to `fumadocs-openapi-` when using `useStorageKey`) to prevent state conflicts when multiple OpenAPI instances are mounted on the same origin. Sources: [packages/openapi/src/ui/contexts/api.tsx](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/ui/contexts/api.tsx#L54-L64), [packages/openapi/src/ui/index.tsx](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/ui/index.tsx#L211-L218)

## Interactive Operation Cards

### Structural Decomposition and Operation Rendering

The `Operation` component serves as the core layout engine for individual HTTP endpoint cards and webhooks. It accepts properties defining the operation structure, including `path`, `method`, `operation`, `pathItem`, `type`, and `headingLevel`. When `showTitle` is enabled, the component computes the endpoint title using `operation.summary`, `pathItem.summary`, a humanized version of `operation.operationId` via `idToTitle`, or falls back to the raw `path`. If `operation.deprecated` is true alongside a title, a yellow status badge is rendered; when titles are hidden, deprecation warnings render as an inline callout.

```tsx
export function Operation({
  type = 'operation',
  path,
  operation,
  pathItem,
  method,
  showTitle,
  showDescription,
  headingLevel = 2,
}: {
  type?: 'webhook' | 'operation';
  path: string;
  method: HttpMethods;
  operation: NoReference<OperationObject>;
  pathItem: NoReference<PathItemObject>;

  showTitle?: boolean;
  showDescription?: boolean;
  headingLevel?: number;
}) {
  const t = useTranslations({ note: 'operation page' });
  const ctx = useRenderContext();
  const {
    schema: { dereferenced },
  } = ctx;
  const body = operation.requestBody;
  let headNode: ReactNode = null;
  const operationDescription = operation.description ?? pathItem.description;
  const descriptionNode = showDescription && operationDescription && (
    <Markdown md={operationDescription} />
  );
  let bodyNode: ReactNode = null;
  let authNode: ReactNode = null;
  let responseNode: ReactNode = null;
  let callbacksNode: ReactNode = null;
  const exampleRequests = useMemo(
    () => getExampleRequests({ path, operation, method, pathItem, ctx }),
    [ctx, operation, method, pathItem, path],
  );

  if (showTitle) {
    const title =
      operation.summary ||
      pathItem.summary ||
      (operation.operationId ? idToTitle(operation.operationId) : path);

    headNode = (
      <div className="flex gap-2 items-center justify-between">
        <Heading id={title} depth={headingLevel} className="my-0!">
          {title}
        </Heading>
        {operation.deprecated && (
          <Badge color="yellow" className="text-xs not-prose">
            {t('Deprecated')}
          </Badge>
        )}
      </div>
    );
    headingLevel++;
  } else if (operation.deprecated) {
    headNode = <Callout type="warn" title={t('Deprecated')} className="mt-0!" />;
  }

```

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

> [!WARNING]
> Media types defined within `operation.requestBody` are validated against registered media adapters via `isMediaTypeSupported(type, ctx.mediaAdapters)`. If an unsupported media type is encountered, an immediate error is thrown: `Media type ${type} is not supported (in ${path})`. Sources: [packages/openapi/src/ui/operation/index.tsx](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/ui/operation/index.tsx#L125-L130)

### Authentication Schemes and Security Contexts

Operations evaluate security requirements by checking `operation.security` with a fallback to `dereferenced.security`. Empty security object entries are filtered out. When securities are present on standard operations (`type === 'operation'`), they populate a tabbed selection interface driven by `SelectTabs`, mapping each security definition entry to its configured scopes and credential schemes retrieved from `dereferenced.components?.securitySchemes`.

```tsx
const securities = (operation.security ?? dereferenced.security ?? []).filter(
  (v) => Object.keys(v).length > 0,
);

if (type === 'operation' && securities.length > 0) {
  const securitySchemes = dereferenced.components?.securitySchemes;
  const items = securities.map((security, i) => {
    return {
      value: String(i),
      label: (
        <div className="flex flex-col text-xs min-w-0">
          {Object.entries(security).map(([key, scopes]) => (
            <code key={key} className="truncate">
              <span className="font-medium">{key}</span>{' '}
              {scopes.length > 0 && (
                <span className="text-fd-muted-foreground">{scopes.join(', ')}</span>
              )}
            </code>
          ))}
        </div>
      ),
    };
  });

  authNode = (
    <SelectTabs defaultValue={items[0].value}>
      <div className="flex items-start justify-between gap-2 mt-10">
        <Heading id="authorization" depth={headingLevel} className="my-0!">
          {t('Authorization')}
        </Heading>
        {items.length > 1 ? (
          <SelectTabTrigger items={items} />
        ) : (
          <div className="not-prose">{items[0].label}</div>
        )}
      </div>
      {securities.map((security, i) => (
        <SelectTab key={i} value={items[i].value}>
          {Object.entries(security).map(([key, scopes]) => {
            const scheme = securitySchemes?.[key];
            if (!scheme) return;

            return <AuthScheme key={key} scheme={scheme} scopes={scopes} />;
          })}
        </SelectTab>
      ))}
    </SelectTabs>
  );
```

Sources: [packages/openapi/src/ui/operation/index.tsx:208-255](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/ui/operation/index.tsx#L208-L255)

> [!NOTE]
> The `Markdown` component delegates parsing to `processMarkdown(md)` from `useRenderContext()` wrapped in a `useMemo` hook, supporting custom `Markdown` component overrides or direct return values from `renderMarkdown`. Sources: [packages/openapi/src/ui/components/markdown.tsx](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/ui/components/markdown.tsx#L1-L14)

### Operation Context and State Management

The `OperationProvider` component wraps interactive operation components, maintaining local state for selected examples and dispatching updates through a listener registry (`ExampleUpdateListener[]`). When `setExample` or `setExampleData` is invoked, registered listeners receive raw request payload data and encoded request representations to synchronize preview tabs and code generators.

```tsx
export function OperationProvider({
  route,
  examples,
  defaultExampleId,
  children,
}: {
  route: string;
  examples: ExampleRequestItem[];
  defaultExampleId?: string;
  children: ReactNode;
}) {
  const [example, setExample] = useState(() => defaultExampleId ?? examples.at(0)?.id);
  const listeners = useRef<ExampleUpdateListener[]>([]);

  return (
    <OperationContext
      value={useMemo(
        () => ({
          example,
          route,
          setExample(newKey: string) {
            const example = examples.find((example) => example.id === newKey);
            if (!example) return;

            setExample(newKey);
            for (const listener of listeners.current) {
              listener(example.data, example.encoded);
            }
          },
          examples,
          setExampleData(data, encoded) {
            for (const item of examples) {
              if (item.id === example) {
                // persistent changes
                item.data = data;
                item.encoded = encoded;
                break;
              }
            }

            for (const listener of listeners.current) {
              listener(data, encoded);
            }
          },
          removeListener(listener) {
            listeners.current = listeners.current.filter((item) => item !== listener);
          },
          addListener(listener) {
            // initial call to listeners to ensure their data is the latest
            // this is necessary to avoid race conditions between `useEffect()`
            const active = examples.find((item) => item.id === example)!;

            listener(active.data, active.encoded);
            listeners.current.push(listener);
          },
        }),
        [example, route, examples],
      )}
    >
      {children}
    </OperationContext>
  );
}
```

Sources: [packages/openapi/src/ui/operation/context.tsx:20-82](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/ui/operation/context.tsx#L20-L82)

> [!TIP]
> `OperationProvider` calls all registered listeners immediately upon registration in `addListener` using the currently active example configuration, preventing race conditions with asynchronous `useEffect` hooks. Sources: [packages/openapi/src/ui/operation/context.tsx](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/ui/operation/context.tsx#L67-L74)

## Interactive Schema Viewer Popovers

### Call-Chain Execution Walkthrough

Schema inspection relies on an anchored popover architecture defined across shared packages. The trace order begins at page initialization and terminates at the popover container:

1. `createOpenAPIPageBase` builds the render context and passes the resolved document schema. Sources: [packages/openapi/src/ui/base.tsx](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/ui/base.tsx#L38-L127)
2. `Schema` receives `root`, `resolver`, and `renderMarkdown` options, memoizing generated schema structures. Sources: [packages/api-docs/src/components/schema/index.tsx](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/api-docs/src/components/schema/index.tsx#L89-L112)
3. `SchemaUI` establishes anchor identifiers via `useAnchorId` and manages the current path inspection stack. Sources: [packages/api-docs/src/components/schema/client.tsx](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/api-docs/src/components/schema/client.tsx#L83-L185)
4. `PopoverContent` renders the floating inspection container using accessible primitives from [Radix UI Primitives](https://www.doc0.dev/docs/e8872a72-1909-479c-b585-dc74c6e26726/technical/ui-layouts/radix-ui-primitives). Sources: [packages/radix-ui/src/components/ui/popover.tsx](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/radix-ui/src/components/ui/popover.tsx#L10-L30)

```mermaid
sequenceDiagram
    participant base as createOpenAPIPageBase
    participant schema as Schema
    participant schemaUI as SchemaUI
    participant popover as PopoverContent
    base->>schema: Render root schema
    schema->>schemaUI: Pass generated data & client props
    schemaUI->>popover: Open inspection popover via trigger state
```

Sources: [packages/openapi/src/ui/base.tsx:38-127](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/ui/base.tsx#L38-L127), [packages/api-docs/src/components/schema/index.tsx:89-112](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/api-docs/src/components/schema/index.tsx#L89-L112), [packages/api-docs/src/components/schema/client.tsx:83-185](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/api-docs/src/components/schema/client.tsx#L83-L185), [packages/radix-ui/src/components/ui/popover.tsx:10-30](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/radix-ui/src/components/ui/popover.tsx#L10-L30)

> [!NOTE]
> `ExcludedFromAutoAnchor` tracks parsed root identifiers in a global `Set<string>` to prevent infinite loops when matching hash parameters in URL search strings against active component paths. Sources: [packages/api-docs/src/components/schema/client.tsx](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/api-docs/src/components/schema/client.tsx#L81-L113)

### State Management and Popover Configuration

The interactive schema viewer utilizes shared state context (`StateContextType`) to track root identifiers, traversal paths, and generated schema references. The table below outlines the core properties managed by path items during interactive inspection.

| Property | Type | Description |
| :--- | :--- | :--- |
| `name` | `string` | The property or field name being inspected. |
| `$ref` | `string` | Reference identifier pointing to the schema definition. |
| `scrollTop` | `number` (optional) | Scroll position preserved across popover transitions. |
| `highlighted` | `string` (optional) | Property name of the highlighted field for object structures. |
| `tabValues` | `string[]` (optional) | Active tab values for nested representations. |
| `closed` | `boolean` (optional) | Explicit popover closure state for the root item. |

Sources: [packages/api-docs/src/components/schema/client.tsx:34-56](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/api-docs/src/components/schema/client.tsx#L34-L56)

> [!TIP]
> When `PopoverContent` mounts or updates, `popoverRef` calculates a minimum height threshold using `element.clientHeight + 2` and restores the prior `scrollTop` coordinate from the active path node. Sources: [packages/api-docs/src/components/schema/client.tsx](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/api-docs/src/components/schema/client.tsx#L87-L95)

## Request Parameter Encoding

### Execution Walkthrough and Sequence

Request parameters and query strings are prepared during the initial rendering cycle of each operation component OpenAPI Interactive UI. The serialization workflow follows a strict execution path starting from the component and passing through request generation, encoding wrappers, and specific parameter serializers:

1. `Operation` initiates parameter collection from `operation.parameters` and `pathItem.parameters`, passing them along with context to `getExampleRequests`. Sources: [packages/openapi/src/ui/operation/index.tsx](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/ui/operation/index.tsx#L77-L80,L157)
2. `getExampleRequests` calls `getRequestData` to construct raw request objects via example picking or schema sampling, and then invokes `encodeRequestData`. Sources: [packages/openapi/src/utils/get-example-requests.ts](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/utils/get-example-requests.ts#L45-L59,L65-L74)
3. `encodeRequestData` loops over parameter locations (`cookie`, `query`, `header`, `path`), resolves media encoders, and dispatches parameters to type-specific formatters. Sources: [packages/openapi/src/requests/media/encode.ts](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/requests/media/encode.ts#L17-L67)
4. `serializeQueryParameter` inspects the parameter style and explosion rules, processing `spaceDelimited`, `pipeDelimited`, `deepObject`, arrays, and objects into final query representations. Sources: [packages/openapi/src/requests/media/encode.ts](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/requests/media/encode.ts#L164-L222)

```mermaid
sequenceDiagram
    participant op as Operation
    participant ex as getExampleRequests
    participant enc as encodeRequestData
    participant qenc as serializeQueryParameter
    op->>ex: Pass path, operation, method, pathItem, ctx
    ex->>enc: Pass raw request data, media adapters, parameters
    enc->>qenc: Dispatch query parameter object & field configuration
```

Sources: [packages/openapi/src/ui/operation/index.tsx:77-80](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/ui/operation/index.tsx#L77-L80), [packages/openapi/src/utils/get-example-requests.ts:45-74](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/utils/get-example-requests.ts#L45-L74), [packages/openapi/src/requests/media/encode.ts](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/requests/media/encode.ts#L17-L67,L164-L222)

> [!WARNING]
> When `deepObject` style is evaluated for query parameters, nested array behaviors are explicitly treated as undefined by wrapping values with `Array.isArray(v) ? v : [String(v)]` to prevent unexpected formatting edge cases. Sources: [packages/openapi/src/requests/media/encode.ts](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/requests/media/encode.ts#L186-L194)

### Parameter Serialization Strategies

The encoding module handles distinct parameter locations and styles according to OpenAPI specifications. The table below lists the serialization rules and style handlers implemented in the encoder.

| Parameter Type / Style | Explode Default | Behavior Description |
| :--- | :--- | :--- |
| `path` / `label` | `false` | Prefixes the encoded string with a period (`.`) using comma or dotted separators. |
| `path` / `matrix` | `false` | Prefixes parameters with semicolon specifiers (`;name=`) for URI path matrix variables. |
| `query` / `spaceDelimited` | `false` | Joins array elements using a single space character (` `) when explosion is disabled. |
| `query` / `pipeDelimited` | `false` | Joins array elements using a pipe character (`|`) when explosion is disabled. |
| `query` / `deepObject` | `true` | Expands nested object properties into bracketed query keys (`param[key]=value`). |
| `header` / `simple` | `false` | Joins array and object values using comma delimiters based on the explode flag. |

Sources: [packages/openapi/src/requests/media/encode.ts:83-252](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/requests/media/encode.ts#L83-L252)

> [!TIP]
> If a parameter defines custom media adapters via its `content` field, `getMediaEncoder` resolves and executes the matching adapter rather than falling back to standard style serialization routines. Sources: [packages/openapi/src/requests/media/encode.ts](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/requests/media/encode.ts#L42-L47,L72-L81)

## Request and Response Tabs

### Request Tab Rendering and Data Display

The `RequestTabs` component checks whether an operation defines a `requestBody` object before rendering. If a request body is present, it delegates to `renderRequestTabs`, falling back to `renderRequestTabsDefault`. When multiple example items exist, it wraps them in a Fumadocs UI `Tabs` component using each item's unique identifier as its value key. For single items, it renders the item directly, and when no examples are found, it outputs an empty state text.

Sources: [packages/openapi/src/ui/operation/request-tabs.tsx:30-97](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/ui/operation/request-tabs.tsx#L30-L97)

The `RequestTabsItem` component extracts `requestData` from each example item and populates a map of display names for parameter categories and bodies.

| Request Data Field | Display Label / Source |
| :--- | :--- |
| `body` | Request Body (with badge showing `requestData.bodyMediaType`) |
| `cookie` | Cookie Parameters |
| `header` | Header Parameters |
| `query` | Query Parameters |
| `path` | Path Parameters |

Sources: [packages/openapi/src/ui/operation/request-tabs.tsx:106-121](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/ui/operation/request-tabs.tsx#L106-L121)

Each available parameter or body category renders inside an accordion item containing a syntax-highlighted JSON code block.

Sources: [packages/openapi/src/ui/operation/request-tabs.tsx:131-148](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/ui/operation/request-tabs.tsx#L131-L148)

> [!NOTE]
> If a request data category contains no keys or evaluates to falsy, `RequestTabsItem` skips rendering that accordion section entirely. Sources: [packages/openapi/src/ui/operation/request-tabs.tsx](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/ui/operation/request-tabs.tsx#L133-L135)

### Response Tabs and Schema Sampling

The `ResponseTabs` component iterates over all response objects defined on an operation, extracting preferred media types and generating example payloads using schema sampling or pre-defined examples.

Sources: [packages/openapi/src/ui/operation/response-tabs.tsx:53-103](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/ui/operation/response-tabs.tsx#L53-L103)

| Property | Type | Description |
| :--- | :--- | :--- |
| `code` | `string` | HTTP response code (e.g., `200`, `400`). |
| `response` | `NoReference<ResponseObject>` | The underlying OpenAPI response specification object. |
| `mediaType` | `string \| null` | Preferred media type resolved via `getPreferredType`. |
| `examples` | `ResponseExample[]` | Array of generated or defined response example items. |

Sources: [packages/openapi/src/ui/operation/response-tabs.tsx:20-33](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/ui/operation/response-tabs.tsx#L20-L33)

Response tabs render as a group of tabs keyed by HTTP status code. When a response defines multiple examples, they are organized within a single-selection accordion component defaulting to the first index.

Sources: [packages/openapi/src/ui/operation/response-tabs.tsx:115-159](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/ui/operation/response-tabs.tsx#L115-L159)

> [!WARNING]
> If a response object specifies neither explicit examples nor a schema, response tab generation yields an empty array, causing `ResponseTabs` to return `null`. Sources: [packages/openapi/src/ui/operation/response-tabs.tsx](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/ui/operation/response-tabs.tsx#L90-L96,L104)

### Client Code Blocks and Usage Generation

The `UsageTabs` component initializes a code usage generator registry using `createCodeUsageGeneratorRegistry`, appending inline generators from context samples and `x-codeSamples` extensions on the operation object.

Sources: [packages/openapi/src/ui/operation/usage-tabs.tsx:30-90](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/ui/operation/usage-tabs.tsx#L30-L90)

The `ClientCodeBlock` component abstracts syntax highlighting by checking render context overrides before falling back to `DynamicCodeBlock` with Shiki initialization.

Sources: [packages/openapi/src/ui/components/codeblock.tsx:8-21](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/ui/components/codeblock.tsx#L8-L21)

## Alternative Scalar Client Integration

### The `withScalar` Wrapper and Client Component

Fumadocs supports delegating endpoint interaction and testing to the `@scalar/api-client-react` library by wrapping page generation options inside `withScalar`. The function requires `@scalar/api-client-react` to be installed in the project, automatically importing its style sheet from `@scalar/api-client-react/style.css` and loading the client component lazily.

Sources: [packages/openapi/src/scalar/client.tsx:10](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/scalar/client.tsx#L10), [packages/openapi/src/scalar/index.tsx:5-10](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/scalar/index.tsx#L5-L10)

| Option Property | Return / Action | Description |
| :--- | :--- | :--- |
| `playground.provider` | `props.children` | Bypasses default playground provider wrappers to use Scalar context. |
| `playground.render` | `<Client method={method} path={path} spec={ctx.schema.bundled} />` | Renders the lazy-loaded `ScalarPlayground` client component for each endpoint. |

Sources: [packages/openapi/src/scalar/index.tsx:15-23](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/scalar/index.tsx#L15-L23)

> [!NOTE]
> The `withScalar` function overrides `playground.provider` to pass children directly and assigns `playground.render` to mount `ScalarPlayground` with the bundled OpenAPI specification schema. Sources: [packages/openapi/src/scalar/index.tsx](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/scalar/index.tsx#L15-L23)

### Playground Rendering and Execution

The `ScalarPlayground` component renders an interactive card containing an HTTP method label, the request path, and a submit trigger button that opens the Scalar client modal with the specified path and method.

Sources: [packages/openapi/src/scalar/client.tsx:12-53](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/scalar/client.tsx#L12-L53)

```tsx
const client = useApiClient({
  configuration: {
    content: spec as never,
  },
});
```
Sources: [packages/openapi/src/scalar/client.tsx:24-28](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/scalar/client.tsx#L24-L28)

The component utilizes `useTheme` from `fumadocs-ui/provider/base` to resolve the current application theme and synchronize light or dark mode styling for the Scalar client wrapper div once mounted on the client.

Sources: [packages/openapi/src/scalar/client.tsx](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/scalar/client.tsx#L6-L8,L21-L39)

> [!WARNING]
> `ScalarPlayground` is marked with `'use client'` and relies on `useState` and `useEffect` hooks to track mounting status before applying resolved theme mode class names to avoid server-side hydration mismatches. Sources: [packages/openapi/src/scalar/client.tsx](https://github.com/blade47/fumadocs/blob/a9f988897e7dc4ef3d62b2865d80da2f5607701e/packages/openapi/src/scalar/client.tsx#L1-L8,L21-L32)

## Related

- [OpenAPI Document Generation](https://www.doc0.dev/docs/e8872a72-1909-479c-b585-dc74c6e26726/technical/api-documentation/openapi-document-generation)
- [Code Sample Generators](https://www.doc0.dev/docs/e8872a72-1909-479c-b585-dc74c6e26726/technical/api-documentation/code-sample-generators)


## Sitemap

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