Fumadocs

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.

components/api-page.tsx
'use client';
import { createGraphQLPage } from '@fumadocs/graphql/ui';

export const GraphQLPage = createGraphQLPage({
  // config
});

Playground

Enable the interactive playground on operation pages by configuring an endpoint, operations are sent over HTTP POST.

components/api-page.tsx
'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: {
      Authorization: 'Bearer <token>',
    },
  },
});

You can replace the default fetcher, e.g. to proxy requests:

components/api-page.tsx
'use client';
import { createGraphQLPage } from '@fumadocs/graphql/ui';

export const GraphQLPage = createGraphQLPage({
  playground: {
    async fetcher(request) {
      const res = await fetch('/api/proxy', {
        method: 'POST',
        headers: request.headers,
        body: JSON.stringify({ query: request.query, variables: request.variables }),
      });

      return {
        type: 'response',
        status: res.status,
        time: 0,
        body: await res.text(),
        contentType: res.headers.get('Content-Type') ?? '',
      };
    },
  },
});

Or replace the playground UI entirely with render:

components/api-page.tsx
'use client';
import { createGraphQLPage } from '@fumadocs/graphql/ui';

export const GraphQLPage = createGraphQLPage({
  playground: {
    render({ kind, name, operation }) {
      return <div>my playground</div>;
    },
  },
});

Subscriptions

The default fetcher sends operations over HTTP POST, which cannot serve subscriptions — the Run button is disabled on subscription pages unless a custom fetcher is provided.

Cross-linking

Type & operation references are cross-linked automatically when baseUrl is passed to your source (see createGraphQL()).

You can also resolve the links yourself:

components/api-page.tsx
'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.

components/api-page.tsx
'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.description}
          {slots.deprecated}
          {slots.directives}
          {slots.playground}
          {slots.arguments}
          {slots.returns}
          {slots.example}
        </div>
      );
    },
    renderTypeLayout(slots) {
      return (
        <div className="flex flex-col gap-6">
          {slots.header}
          {slots.description}
          {slots.directives}
          {slots.relations}
          {slots.usages}
          {slots.fields}
          {slots.values}
          {slots.scalar}
        </div>
      );
    },
  },
});

Schema UI

Customize how types are rendered.

components/api-page.tsx
'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:

layout.shared.tsx
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 use Shiki for code blocks. You can customize the highlighter and themes.

components/api-page.tsx
'use client';
import { createGraphQLPage } from '@fumadocs/graphql/ui';
import { defaultShikiFactory } from 'fumadocs-core/highlight/shiki/full';

export const GraphQLPage = createGraphQLPage({
  shiki: defaultShikiFactory,
  shikiOptions: {
    themes: {
      light: 'github-light',
      dark: 'github-dark',
    },
  },
});

Custom Components

Override the default heading, code block and Markdown components.

components/api-page.tsx
'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 fumadocs/graphql/page

It installs <GraphQLPage /> itself, your components/api-page.tsx is no longer needed.

mdx-components.tsx
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.

ComponentContents
fumadocs/graphql/operationoperations, with their arguments and example
fumadocs/graphql/type-docsnamed types, with their relations and fields
fumadocs/graphql/schema-uithe type, argument and field details
fumadocs/graphql/playgroundthe interactive playground
components/api-page.tsx
'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

On this page