createOpenAPIPage()
The component for rendering OpenAPI docs content
Overview
Fumadocs OpenAPI uses a <OpenAPIPage /> component to render page contents, it should be a client component.
'use client';
import { createOpenAPIPage } from 'fumadocs-openapi/ui';
export const OpenAPIPage = createOpenAPIPage({
// config
});Generate Code Usages
Generate code usage examples for each API endpoint.
'use client';
import { } from 'fumadocs-openapi/ui';
import {
,
type ,
} from 'fumadocs-openapi/requests/generators';
import { } from 'fumadocs-openapi/requests/generators/all';
const = ();
// include defaults
();
// add custom generators
.('custom-id', {
: 'My Example',
: 'js',
(, { }) {
// request data
.();
return 'const response = "hello world";';
},
});
export const = ({
,
});In addition, you can also specify code samples via OpenAPI schema.
paths:
/plants:
get:
x-codeSamples:
- lang: js
label: JavaScript SDK
source: |
const planter = require('planter');
planter.list({ unwatered: true });Internationalization
Assuming you have configured Internationalization at UI level:
import { defineI18n } from 'fumadocs-core/i18n';
import { uiTranslations } from 'fumadocs-ui/i18n';
import { openapiTranslations } from 'fumadocs-openapi/i18n';
const i18n = defineI18n({
languages: ['en', 'cn'],
defaultLanguage: 'en',
});
export const translations = i18n
.translations()
.extend(uiTranslations())
.extend(openapiTranslations())
.add({
cn: {
displayName: 'Chinese',
'Body(playground)': '請求正文',
},
});See Translations for more details.
Media Adapters
You can create a media adapter to support other media types in API pages, a media adapter implements:
- Converting value into
fetch()body compatible with corresponding media type. - Generate code example based on different programming language/tool.
Request bodies of other media types are read-only: they are left out of code usages, and cannot be sent from the playground.
'use client';
import { } from 'fumadocs-openapi/ui';
import type { MediaAdapter } from 'fumadocs-openapi';
const : <string, MediaAdapter> = {
// example: custom `application/json
'application/json': {
() {
return .(.);
},
// returns code that inits a `body` variable, used for request body
(, ) {
if (. === 'js') {
return `const body = "hello world"`;
}
if (. === 'python') {
return `body = "hello world"`;
}
if (. === 'go' && 'addImport' in ) {
.('strings');
return `body := strings.NewReader("hello world")`;
}
},
},
};
export const = ({
,
});Authorization
Auth providers handle the security schemes of the playground: the rows of their values, and how values are sent.
'use client';
import { createOpenAPIPage } from 'fumadocs-openapi/ui';
import { Custom } from 'fumadocs-openapi/ui/playground/client';
import type { AuthPanelProps } from 'fumadocs-openapi/playground';
export const OpenAPIPage = createOpenAPIPage({
playground: {
authProviders: [
{
// a scheme ID or a function, every scheme when omitted
on: 'my-auth',
render: ({ Value, Panel }) => (
<>
<Value name="Authorization" type="header" />
<Panel title="Sign in" component={SignIn} />
</>
),
},
],
},
});
function SignIn({ field, close }: AuthPanelProps) {
const { setValue } = Custom.useController(field.fieldName);
return (
<button
onClick={async () => {
const res = await fetch('/api/token');
setValue(`Bearer ${await res.text()}`);
close();
}}
>
Sign in
</button>
);
}| Option | Is |
|---|---|
on | the security schemes it handles |
render | its rows, from Value (an input of the value) and Panel (a panel) |
onRequest | write the value into request data, for requests and code usages |
Define providers outside of components, the auth fields are created again when they change.
Rows and panels hold their own state, Custom.useController(field.fieldName) reads and writes the value. It starts from the default of scheme, like Bearer , and is kept per scheme while the tab is open.
Leave the page with the function from useAuthRedirect(). When the page loads again, the playground reopens, and the rows get the data back in onReturn.
import { Custom } from 'fumadocs-openapi/ui/playground/client';
import {
type AuthPanelProps,
type AuthRenderProps,
useAuthRedirect,
} from 'fumadocs-openapi/playground';
function Rows({ field, Value, Panel }: AuthRenderProps) {
const { setValue } = Custom.useController(field.fieldName);
useAuthRedirect(field, (url, state) => {
if (url.searchParams.get('state') === state)
setValue(`Bearer ${url.searchParams.get('token')}`);
});
return (
<>
<Value name="Authorization" type="header" />
<Panel title="Sign in" component={SignIn} />
</>
);
}
function SignIn({ field }: AuthPanelProps) {
const redirect = useAuthRedirect(field);
return (
<button
onClick={() => {
const state = crypto.randomUUID();
redirect(`https://auth.example.com/login?state=${state}`, state);
}}
>
Sign in
</button>
);
}Customise UI
For customisations beyond the available options, you can install the UI into your codebase with Fumadocs CLI.
Full UI
The entire UI of API pages, built on the headless layer.
npx @fumadocs/cli add openapi/pageIt installs <OpenAPIPage /> itself, your components/api-page.tsx is no longer needed.
import { OpenAPIPage } from '@/components/api-page';
import { OpenAPIPage } from '@/components/openapi/page'; API Playground
The UI of the playground, its state comes from usePlayground().
npx @fumadocs/cli add openapi/playground'use client';
import { createOpenAPIPage } from 'fumadocs-openapi/ui';
import PlaygroundClient from '@/components/openapi/playground';
export const OpenAPIPage = createOpenAPIPage({
playground: {
render: () => <PlaygroundClient />,
},
});Operation
The UI of operations and webhooks.
npx @fumadocs/cli add openapi/operation'use client';
import { createOpenAPIPage } from 'fumadocs-openapi/ui';
import { Operation } from '@/components/openapi/operation';
export const OpenAPIPage = createOpenAPIPage({
components: {
Operation,
},
});Schema UI
The UI of JSON schemas, its state comes from <SchemaUIProvider />.
npx @fumadocs/cli add api-docs/schema'use client';
import { createOpenAPIPage } from 'fumadocs-openapi/ui';
import { Schema } from '@/components/api/schema';
export const OpenAPIPage = createOpenAPIPage({
components: {
SchemaUI: Schema,
},
});How is this guide?
Last updated on
