Written by

Fuma Nama

At

Thu Jun 11 2026

Fumadocs OpenAPI v11

Upgrade guide for Fumadocs OpenAPI v11.

Back

We are pleased to announce the release of Fumadocs OpenAPI v11. This major release unifies the RSC and client APIs, removes deprecated options accumulated since v10, and simplifies the server surface.

This release requires attention during upgrades. Run a type check after migrating:

npm run types:check

Upgrading from v10?

If you haven't migrated to v10 yet, read the Fumadocs OpenAPI v10 announcement first.

Unify RSC & Client APIs

createAPIPage() and createClientAPIPage() are replaced by a single createOpenAPIPage() API. The component no longer accepts an OpenAPIServer instance or a separate client config, all options live in one client component.

The fumadocs-openapi/ui/client subpath export is removed. Merge any defineClientConfig() options into createOpenAPIPage() directly.

components/api-page.tsx
import { openapi } from '@/lib/openapi';
import { createAPIPage } from 'fumadocs-openapi/ui';
import client from './api-page.client';

export const APIPage = createAPIPage(openapi, {
  client,
  mediaAdapters: {
    /* ... */
  },
});
components/api-page.client.tsx
'use client';
import { defineClientConfig } from 'fumadocs-openapi/ui/client';

export default defineClientConfig({
  playground: {
    transformAuthInputs: (inputs) => inputs,
  },
  storageKeyPrefix: 'my-openapi-',
});

api-page.tsx must be a client component. Note that for existing non-RSC usages, old APIs are only deprecated, migrating to the new createOpenAPIPage() is optional, and API surface is identical.

Pass Page Props from Server

The server is responsible for passing OpenAPI data to <OpenAPIPage />.

Use page.data.getOpenAPIPageProps() when rendering OpenAPI pages from virtual files:

docs/[[...slug]]/page.tsx
import { OpenAPIPage } from '@/components/api-page';

export default function Page({ slug }) {
  const page = source.getPage(slug);

  if (page.type === 'openapi') {
    return (
      <DocsPage full>
        <DocsTitle>{page.data.title}</DocsTitle>
        <DocsBody>
          <OpenAPIPage {...page.data.getOpenAPIPageProps()} />
        </DocsBody>
      </DocsPage>
    );
  }

  // ...
}

Use openapi.preloadOpenAPIPage() when rendering generated MDX files:

app/docs/[[...slug]]/page.tsx
import { openapi } from '@/lib/openapi';
import { OpenAPIPage } from '@/components/api-page';

export default async function Page({ slug }) {
  const page = source.getPage(slug);

  return (
    <MdxContent
      components={getMDXComponents({
        OpenAPIPage: async (props) => (
          <OpenAPIPage {...await openapi.preloadOpenAPIPage(page)} {...props} />
        ),
      })}
    />
  );
}

Server & Loader

getSchema() Return Value

getSchema() on virtual pages and the OpenAPI server no longer includes a dereferenced document. It now returns the bundled schema only.

const schema = page.data.getSchema();

// dereferenced paths, components, etc.
schema.dereferenced.paths;

Dereferencing happens at render time inside <OpenAPIPage /> for better performance.

input Option

The whole-map factory form of input is removed. Use a record instead: each value can be a file path, URL, inline document, or a per-entry async function.

lib/openapi.ts
import { createOpenAPI } from 'fumadocs-openapi/server';

export const openapi = createOpenAPI({
  input: async () => {
    const res = await fetch('https://example.com/openapi.json');
    return {
      my_api: await res.json(),
    };
  },
});

Customization Callbacks

Several callbacks now receive richer context about the current operation.

generateCodeSamples

import { createCodeSample } from 'fumadocs-openapi/server';

export const OpenAPIPage = createOpenAPIPage({
  generateCodeSamples: (method) => [
    createCodeSample({
      label: 'Custom',
      lang: 'js',
      generate(data) {
        return `fetch('${data.url}')`;
      },
    }),
  ],
});

renderOperationLayout

export const OpenAPIPage = createOpenAPIPage({
  content: {
    renderOperationLayout: (slots, ctx, method) => <div>{slots.header}</div>,
  },
});

playground.render

export const OpenAPIPage = createOpenAPIPage({
  playground: {
    render: (method) => <MyPlayground method={method} />,
  },
});

Dropped Deprecated APIs

The following APIs are removed in v11. Use the replacements listed below.

RemovedReplacement
transformerOpenAPI()openapiPlugin()
generateTypeScriptSchema()generateTypeScriptDefinitions()
playground.requestTimeoutplayground.fetchOptions.requestTimeout
allowedUrls (proxy)allowedOrigins or filterRequest
groupStyle (generateFiles / staticSource)folderStyle

Loader Plugin

lib/source.ts
import { transformerOpenAPI } from 'fumadocs-openapi/server';

export const source = loader({
  pageTree: {
    transformers: [transformerOpenAPI()],
  },
});

Proxy Server

export const { GET, POST } = openapi.createProxy({
  allowedUrls: ['https://example.com'],
});

Playground Request Timeout

export const OpenAPIPage = createOpenAPIPage({
  playground: {
    requestTimeout: 30,
  },
});

TypeScript Definitions

export const OpenAPIPage = createOpenAPIPage({
  generateTypeScriptSchema: async (method, statusCode, contentType, ctx) => {
    // ...
  },
});

generateFiles() Context

The documents field is removed from the beforeWrite and index.items callback context. Access schemas from the OpenAPI server instead.

scripts/generate-docs.ts
void generateFiles({
  input: openapi,
  output: './content/docs',
  beforeWrite(files) {
    const doc = this.documents['petstore.yaml'];
    // ...
  },
});

Similarly, rename groupStyle to folderStyle when generating meta.json files:

void generateFiles({
  meta: {
    groupStyle: 'separator',
  },
});

Deprecated APIs

The following APIs are deprecated but still available in v11, migration is recommended.

Virtual Files

The data methods on page.data are unified into getOpenAPIPageProps().

BeforeAfter
getAPIPageProps()getOpenAPIPageProps()
getClientAPIPageProps()getOpenAPIPageProps()