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.
/api/weather:GET.| mode | content | file path |
|---|---|---|
| tag | operations with same tag | {tag_name}.mdx |
| file | operations in same schema file | {file_name}.mdx |
| operation | each operation | {operationId ?? endpoint_path}.mdx |
| custom | see below | N/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:
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.
tags:
- name: test
description: this is a tag.
x-displayName: My Test NamePages follow the tag hierarchy of OpenAPI 3.2 like groupBy, tags without operations get no page.
tags:
- name: store
kind: nav
# output: store/products.mdx
- name: products
parent: storegroupBy
In operation mode, you can group output files with folders.
| value | output |
|---|---|
| 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.
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:
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.tsAdd the OpenAPIPage component to your MDX components.
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():
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:
| property | description |
|---|---|
title | Page title |
description | Page description |
full | Always true, added for Fumadocs UI |
_openapi | Internal 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
