Fumadocs

OpenAPI

Generating docs for OpenAPI schema

This guide is for RSC environment

React Server Component (RSC) offered good primitive for Fumadocs OpenAPI to build upon.

If your framework doesn't support RSC, you can see Usage without RSC instead.

Setup

Install the required packages.

npm i fumadocs-openapi shiki

Generate Styles

Add the following line:

Tailwind CSS
@import 'tailwindcss';
@import 'fumadocs-ui/css/neutral.css';
@import 'fumadocs-ui/css/preset.css';
@import 'fumadocs-openapi/css/preset.css';

Configure Plugin

Create the OpenAPI server instance & <APIPage /> component.

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

export const openapi = createOpenAPI({
  // the OpenAPI schema, you can also give it an external URL.
  input: ['./openapi.json'],
});

See createOpenAPI() & <APIPage /> for available options.

Generate Pages

You can generate MDX files directly from your OpenAPI schema.

Create a script:

scripts/generate-docs.ts
import { generateFiles } from 'fumadocs-openapi';
import { openapi } from '@/lib/openapi';

void generateFiles({
  input: openapi,
  output: './content/docs',
  // we recommend to enable it
  // make sure your endpoint description doesn't break MDX syntax.
  includeDescription: true,
});

Generate docs with the script:

bun ./scripts/generate-docs.ts

Add the APIPage component to your MDX components.

components/mdx.tsx
import defaultComponents from 'fumadocs-ui/mdx';
import { APIPage } from '@/components/api-page';
import type { MDXComponents } from 'mdx/types';

export function getMDXComponents(components?: MDXComponents) {
  return {
    ...defaultComponents,
    // should be available in MDX files
    APIPage,
    ...components,
  } satisfies MDXComponents;
}

You can also use it without generating real files by integrating into Loader API.

lib/source.ts
import { loader, multiple } from 'fumadocs-core/source';
import { openapiPlugin, openapiSource } from 'fumadocs-openapi/server';
import { docs } from 'collections/server';
import { openapi } from '@/lib/openapi';

export const source = loader(
  multiple({
    docs: docs.toFumadocsSource(),
    openapi: await openapiSource(openapi, {
      baseDir: 'openapi',
    }),
  }),
  {
    baseUrl: '/docs',
    plugins: [openapiPlugin()],
    // ...
  },
);

openapiSource() is a server-side API that generates pages directly to your loader(), hence allowing dynamic generation (e.g. different page tree as schema changes).

It shares a different type from your original source, explicit handling of OpenAPI pages might be necessary (e.g. in your page component).

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

function Page() {
  const page = source.getPage('...');

  // for OpenAPI pages
  if (page.data.type === 'openapi') {
    return (
      <DocsPage full>
        <h1 className="text-[1.75em] font-semibold">{page.data.title}</h1>
        <DocsBody>
          <APIPage {...page.data.getAPIPageProps()} />
        </DocsBody>
      </DocsPage>
    );
  }

  // your original flow below...
}

Or where you return text for LLM:

import { source } from '@/lib/source';
import type { InferPageType } from 'fumadocs-core/source';

export async function getLLMText(page: InferPageType<typeof source>) {
  if (page.data.type === 'openapi') {
    // e.g. return the stringified OpenAPI schema
    return JSON.stringify(page.data.getSchema().bundled, null, 2);
  }

  // your original flow below...
}

Features

The official OpenAPI integration supports:

  • Basic API endpoint information
  • Interactive API playground
  • Example code to send request (in different programming languages)
  • Response samples and TypeScript definitions
  • Request parameters and body generated from schemas

Demo

How is this guide?

Last updated on

On this page