createGraphQLPage()
The component for rendering GraphQL docs content
Overview
Fumadocs GraphQL uses a <GraphQLPage /> component to render page contents, it should be a client component.
'use client';
import { createGraphQLPage } from '@fumadocs/graphql/ui';
export const GraphQLPage = createGraphQLPage({
// config
});Playground
Operation pages get a playground when you configure an endpoint: readers edit the operation, fill the variables in a form or as JSON, and send it with their headers.
'use client';
import { createGraphQLPage } from '@fumadocs/graphql/ui';
export const GraphQLPage = createGraphQLPage({
playground: {
url: 'https://api.example.com/graphql',
// allow users to edit the endpoint URL (default: true)
allowUrlEdit: false,
// default headers of playground requests
headers: {
'X-Client-Name': 'docs',
},
},
});Do not put secrets in headers, they are sent to the browser, shown in code samples, and kept in its local storage by endpoint origin.
Queries and mutations are sent over HTTP POST, you can replace their fetcher, e.g. to proxy requests:
'use client';
import { createGraphQLPage } from '@fumadocs/graphql/ui';
export const GraphQLPage = createGraphQLPage({
playground: {
async fetcher(request) {
const start = performance.now();
const res = await fetch('/api/proxy', {
method: 'POST',
headers: { 'Content-Type': 'application/json', ...request.headers },
body: JSON.stringify({ query: request.query, variables: request.variables }),
});
return {
type: 'response',
status: res.status,
time: performance.now() - start,
body: await res.text(),
contentType: res.headers.get('Content-Type') ?? '',
// optional, shown in a Headers tab
headers: Array.from(res.headers),
};
},
},
});Or replace the playground UI entirely with render, it takes the place of the signature bar:
'use client';
import { createGraphQLPage } from '@fumadocs/graphql/ui';
export const GraphQLPage = createGraphQLPage({
playground: {
render({ kind, name, operation }) {
return <div>my playground</div>;
},
},
});Subscriptions
On subscription pages, the playground subscribes to subscriptionUrl and logs the events it receives. It defaults to url with a ws(s):// scheme.
subscriptionUrl | Protocol |
|---|---|
ws://, wss:// | graphql-ws (graphql-transport-ws) |
http://, https:// | GraphQL over SSE, in distinct connections mode |
'use client';
import { createGraphQLPage } from '@fumadocs/graphql/ui';
export const GraphQLPage = createGraphQLPage({
playground: {
url: 'https://api.example.com/graphql',
// GraphQL over SSE on the same endpoint
subscriptionUrl: 'https://api.example.com/graphql',
},
});Browser limits
Browsers can't set the headers of WebSocket connections, graphql-ws sends them in the payload of
connection_init instead.
Code Samples
Example requests are shown in GraphQL, or as code in cURL, JavaScript, Go, Python, Java, C# and Rust that sends them to playground.url (a placeholder when unset) with playground.headers. The playground shows the same code for the request being edited. Subscription pages show their example in GraphQL only.
Add generators with codeUsages, or remove the default ones:
'use client';
import {
createCodeUsageGeneratorRegistry,
createGraphQLPage,
registerDefaultCodeUsages,
} from '@fumadocs/graphql/ui';
// leave out the defaults to start from scratch
const codeUsages = registerDefaultCodeUsages(createCodeUsageGeneratorRegistry());
// the defaults: curl, js, go, python, java, csharp, rust
codeUsages.remove('java');
codeUsages.add('graphql-request', {
label: 'graphql-request',
lang: 'js',
generate({ url, query, variables = {}, headers }) {
return `import { request } from 'graphql-request';
const data = await request(${JSON.stringify(url)}, ${JSON.stringify(query)}, ${JSON.stringify(variables)}, ${JSON.stringify(headers)});`;
},
});
export const GraphQLPage = createGraphQLPage({ codeUsages });Prop
Type
Cross-linking
Type pages link to each other and to operations automatically. Operation pages keep readers on the page, their types open in the Schema UI.
You can also resolve the links yourself:
'use client';
import { createGraphQLPage } from '@fumadocs/graphql/ui';
export const GraphQLPage = createGraphQLPage({
typeLinks(name) {
return `/docs/types/${name}`;
},
operationLinks(kind, name) {
return `/docs/${kind}/${name}`;
},
});Return undefined for types/operations without their own page.
Custom Layout
You can customize how operation and type pages are laid out.
'use client';
import { createGraphQLPage } from '@fumadocs/graphql/ui';
export const GraphQLPage = createGraphQLPage({
content: {
renderOperationLayout(slots) {
return (
<div className="flex flex-col gap-6">
{slots.header}
{slots.playground}
{slots.description}
{slots.deprecated}
{slots.arguments}
{slots.returns}
{slots.example}
</div>
);
},
},
});| Slot | Renders |
|---|---|
header | the title, on pages with several items |
playground | the signature, like QUERY customer(id: ID!): Customer, its directives and the playground |
description | the description of operation |
deprecated | the deprecation reason |
arguments | the arguments |
returns | the return type and its fields |
example | the example request and response, beside the operation on wide pages |
Schema UI
Customize how types are rendered.
'use client';
import { createGraphQLPage } from '@fumadocs/graphql/ui';
export const GraphQLPage = createGraphQLPage({
schemaUI: {
render(options, ctx) {
// fully custom schema renderer
return <ctx.SchemaUI {...options} />;
},
},
});Internationalization
Assuming you have configured Internationalization at UI level:
import { defineI18n } from 'fumadocs-core/i18n';
import { uiTranslations } from 'fumadocs-ui/i18n';
import { graphqlTranslations } from '@fumadocs/graphql/i18n';
const i18n = defineI18n({
languages: ['en', 'cn'],
defaultLanguage: 'en',
});
export const translations = i18n
.translations()
.extend(uiTranslations())
.extend(graphqlTranslations())
.add({
cn: {
displayName: 'Chinese',
'Arguments(operation page)': '参数',
},
});See Translations for more details.
Syntax Highlighting
GraphQL pages highlight code blocks with Shiki, pass a highlighter to customize it.
'use client';
import { createGraphQLPage } from '@fumadocs/graphql/ui';
import { highlighter } from '@/lib/highlighter';
export const GraphQLPage = createGraphQLPage({ highlighter });Custom Components
Override the default heading, code block and Markdown components.
'use client';
import { createGraphQLPage } from '@fumadocs/graphql/ui';
export const GraphQLPage = createGraphQLPage({
components: {
Heading({ id, depth, ...props }) {
const Tag = `h${depth}` as const;
return <Tag id={id} {...props} />;
},
CodeBlock({ lang, code }) {
return <pre data-lang={lang}>{code}</pre>;
},
},
});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 GraphQL pages, built on the headless layer.
npx @fumadocs/cli add graphql/pageIt installs <GraphQLPage /> itself, your components/api-page.tsx is no longer needed.
import { GraphQLPage } from '@/components/api-page';
import { GraphQLPage } from '@/components/graphql/page'; Parts
Install only the pieces you want to edit, and pass them back through components. The playground has no slot there: an installed graphql/operation renders it, or return <OperationPlayground /> from playground.render.
| Component | Contents |
|---|---|
graphql/operation | operations, with their arguments and examples |
graphql/type-docs | named types, with their fields and usages |
graphql/schema-ui | the type, argument and field details |
graphql/playground | the interactive playground |
'use client';
import { createGraphQLPage } from '@fumadocs/graphql/ui';
import { Operation } from '@/components/graphql/operation';
import { TypeDocs } from '@/components/graphql/type-docs';
export const GraphQLPage = createGraphQLPage({
components: {
Operation,
TypeDocs,
},
});How is this guide?
Last updated on
