Fumadocs

Generating Pages

Generate pages from OpenAPI schema.

staticSource() and dynamicSource() generate pages for your loader(), generateFiles() writes them into your content directory as MDX files instead. They accept the same options.

Note that the page content is still rendered by the <OpenAPIPage /> component, the docs generator only arranges the endpoints/webhooks to render for each page.

Options

per

Customize the content of pages, default to operation.

Operation refers to an API endpoint with specific method like /api/weather:GET.
modecontentfile path
tagoperations with same tag{tag_name}.mdx
fileoperations in same schema file{file_name}.mdx
operationeach operation{operationId ?? endpoint_path}.mdx
customsee belowN/A
import { openapi } from '@/lib/openapi';

await openapi.staticSource({
  per: 'tag',
});

When set to custom, you can pass a function to fully customize the generation process:

Example
import type { OperationOutput } from 'fumadocs-openapi';
import { openapi } from '@/lib/openapi';

await openapi.staticSource({
  per: 'custom',
  toPages(builder) {
    const items = builder.extract();

    for (const op of items.operations) {
      const { pathItem, operation, displayName } = builder.fromExtractedOperation(op)!;

      const entry: OperationOutput = {
        type: 'operation',
        schemaId: builder.id,
        item: op,
        path: '...',
        info: {
          title: displayName,
          description: operation.description ?? pathItem.description,
        },
      };

      builder.create(entry);
    }
  },
});

When set to tag, adding x-displayName to the tag definition can control the title of each page.

openapi.yaml
tags:
  - name: test
    description: this is a tag.
    x-displayName: My Test Name

Pages follow the tag hierarchy of OpenAPI 3.2 like groupBy, tags without operations get no page.

openapi.yaml
tags:
  - name: store
    kind: nav
  # output: store/products.mdx
  - name: products
    parent: store

groupBy

In operation mode, you can group output files with folders.

valueoutput
tag{tag}/{operationId ?? endpoint_path}.mdx
route{endpoint_path}/{method}.mdx (ignores name option)
none (default){operationId ?? endpoint_path}.mdx
import { openapi } from '@/lib/openapi';

await openapi.staticSource({
  per: 'operation',
  groupBy: 'tag',
});

When grouping by tag, it follows the tag hierarchy of OpenAPI 3.2: a tag is nested into the folder of its parent tag, while tags with a kind other than nav are ignored.

openapi.yaml
tags:
  - name: store
    summary: Store
    kind: nav
  - name: products
    parent: store

paths:
  /products:
    get:
      # output: store/products/listProducts.mdx
      operationId: listProducts
      tags: [products]

Operations without tags are grouped under an unknown folder.

name

A function that controls the file name of generated pages.

import { openapi } from '@/lib/openapi';

await openapi.staticSource({
  name(output) {
    const doc = this.document;
    if (output.type === 'operation') {
      const operation = doc.paths![output.item.path]![output.item.method]!;
      // operation object
      console.log(operation);

      return 'my-dir/filename';
    }

    const hook = this.dereferenceShallow(doc.webhooks![output.item.name])[output.item.method]!;
    // webhook object
    console.log(hook);
    return 'my-dir/filename';
  },
});

meta

Generate meta.json files automatically.

You can always define the meta.json files manually for maximal flexibility.

import { openapi } from '@/lib/openapi';

await openapi.staticSource({
  meta: true,
});

Or customize how folders are represented:

import { openapi } from '@/lib/openapi';

await openapi.staticSource({
  meta: {
    folderStyle: 'separator',
  },
});

MDX Files

To write pages as MDX files, 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 OpenAPIPage component to your MDX components.

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

export default async function Page(props: PageProps<'/docs/[[...slug]]'>) {
  // ...
  <MDX
    components={getMDXComponents({
      OpenAPIPage: async (props) => (
        <OpenAPIPage {...await openapi.preloadOpenAPIPage(page)} {...props} />
      ),
    })}
  />;
}

Add the plugin to your loader():

lib/source.ts
import { openapiPlugin } from 'fumadocs-openapi/server';
import { loader } from 'fumadocs-core/source';

export const source = loader({
  // optional: adds a badge to each page item in page tree
  plugins: [openapiPlugin()],
});

generateFiles() also accepts the options below.

index

Generate index files with cards linking to generated pages.

import { generateFiles } from 'fumadocs-openapi';

void generateFiles({
  index: {
    // for generating `href`
    url: {
      baseUrl: '/docs',
      contentDir: './content/docs',
    },
    items: [
      {
        // output path
        path: 'index.mdx',
        // optional: restrict the input files (identical to the `input` field in server)
        only: ['petstore.yaml'],
        // optional: set frontmatter
        description: 'All available pages',
      },
    ],
  },
});

imports

Add custom imports to generated MDX files. This is useful for including components, utilities, or other dependencies in your generated documentation.

import { generateFiles } from 'fumadocs-openapi';

void generateFiles({
  imports: [
    {
      names: ['API_BASE_URL'],
      from: '@/constants',
    },
  ],
});

This will add the following imports to all generated MDX files:

import { API_BASE_URL } from '@/constants';

frontmatter

Customize the frontmatter of MDX files.

By default, it includes:

propertydescription
titlePage title
descriptionPage description
fullAlways true, added for Fumadocs UI
_openapiInternal Properties
import { generateFiles } from 'fumadocs-openapi';

void generateFiles({
  frontmatter: (title, description) => ({
    myProperty: 'hello',
  }),
});

addGeneratedComment

Add a comment to the top of generated files indicating they are auto-generated.

import { generateFiles } from 'fumadocs-openapi';

void generateFiles({
  // Add default comment
  addGeneratedComment: true,

  // Or provide a custom comment
  addGeneratedComment: 'Custom auto-generated comment',

  // Or disable comments
  addGeneratedComment: false,
});

How is this guide?

Last updated on