Skip to main content

createAPIPage

Create a React component for rendering OpenAPI documentation pages.
import { createAPIPage } from 'fumadocs-openapi/ui';
import { createOpenAPI } from 'fumadocs-openapi/server';

const server = createOpenAPI({
  input: ['./openapi.yaml'],
});

export const APIPage = createAPIPage(server, {
  // options
});
Returns: React component accepting ApiPageProps

CreateAPIPageOptions

Type Generation

Code Samples

Rendering

Media Types

Layout Customization

Schema UI

Playground

Client Options

ApiPageProps

Props for the generated API page component.
interface ApiPageProps {
  document: Promise<ProcessedDocument> | string | ProcessedDocument;
  showTitle?: boolean;
  showDescription?: boolean;
  operations?: OperationItem[];
  webhooks?: WebhookItem[];
}

OperationItem

interface OperationItem {
  path: string;
  method: HttpMethods;
}

WebhookItem

interface WebhookItem {
  name: string;
  method: HttpMethods;
}

RenderContext

Context object passed to custom renderers:
interface RenderContext {
  slugger: Slugger;
  schema: ProcessedDocument;
  proxyUrl?: string;
  mediaAdapters: Record<string, MediaAdapter>;
  generateTypeScriptDefinitions: (schema: JSONSchema, ctx: GenerateTypeScriptDefinitionsContext) => Awaitable<string | undefined>;
  renderMarkdown: (md: string) => ReactNode;
  renderHeading: (depth: number, text: string, props?: HTMLAttributes<HTMLHeadingElement>) => ReactNode;
  renderCodeBlock: (lang: string, code: string) => ReactNode;
  // ... plus all CreateAPIPageOptions
}

Example: Basic Usage

import { createAPIPage } from 'fumadocs-openapi/ui';
import { createOpenAPI } from 'fumadocs-openapi/server';

const server = createOpenAPI({
  input: ['./openapi.yaml'],
});

export const APIPage = createAPIPage(server);

// In your page component:
export default function Page() {
  return (
    <APIPage
      document="./openapi.yaml"
      operations={[
        { path: '/users', method: 'get' },
        { path: '/users/{id}', method: 'get' },
      ]}
    />
  );
}

Example: Custom Layout

export const APIPage = createAPIPage(server, {
  content: {
    renderOperationLayout: async (slots, ctx, method) => (
      <div className="grid grid-cols-2 gap-6">
        <div>
          {slots.header}
          {slots.description}
          {slots.authSchemes}
          {slots.paremeters}
          {slots.body}
          {slots.responses}
        </div>
        <div className="sticky top-4">
          {slots.apiPlayground}
          {slots.apiExample}
        </div>
      </div>
    ),
  },
});

Example: TypeScript Generation

import { createAPIPage } from 'fumadocs-openapi/ui';

export const APIPage = createAPIPage(server, {
  async generateTypeScriptDefinitions(schema, ctx) {
    if (typeof schema !== 'object') return;
    
    const { compile } = await import('@fumari/json-schema-ts');
    
    try {
      return compile(schema, {
        name: ctx.readOnly ? 'Response' : 'Request',
        readOnly: ctx.readOnly,
        writeOnly: ctx.writeOnly,
        getSchemaId: ctx.schema.getRawRef,
      });
    } catch (e) {
      console.warn('Failed to generate TypeScript:', e);
    }
  },
});

Example: Code Samples

import { createCodeUsageGeneratorRegistry } from 'fumadocs-openapi/requests/generators';

const codeUsages = createCodeUsageGeneratorRegistry();

codeUsages.add('typescript', {
  lang: 'typescript',
  label: 'TypeScript',
  generate: (url, data, { mediaAdapters }) => {
    const headers = data.header ? JSON.stringify(data.header, null, 2) : '{}';
    const body = data.body ? JSON.stringify(data.body, null, 2) : 'undefined';
    
    return `const response = await fetch('${url}', {
  method: '${data.method}',
  headers: ${headers},
  body: ${body},
});

const data = await response.json();`;
  },
});

export const APIPage = createAPIPage(server, {
  codeUsages,
});

Build docs developers (and LLMs) love