Fumadocs

createGraphQL()

The GraphQL server instance.

GraphQL Server

The main config for Fumadocs GraphQL.

It should not be referenced in browser environments.

input

The GraphQL schemas to read from, either:

  • an array of file paths/URLs to SDL files.
  • a record of schema id -> input.

Record inputs accept SDL file paths/URLs, SDL text, introspection results, GraphQLSchema instances, and functions returning them.

import { createGraphQL } from '@fumadocs/graphql/server';

export const graphql = createGraphQL({
  input: ['./schema.graphql'],
});

You can pass an array of SDL files to merge them into a single schema, type extensions (e.g. extend type Query) are supported.

import { createGraphQL } from '@fumadocs/graphql/server';

export const graphql = createGraphQL({
  input: {
    api: ['./base.graphql', './orders.graphql'],
  },
});

disableCache

Disable caching of loaded schemas. Useful during development when schemas change frequently.

import { createGraphQL } from '@fumadocs/graphql/server';

export const graphql = createGraphQL({
  input: ['./schema.graphql'],
  disableCache: true,
});

Generating Pages

staticSource() and dynamicSource() generate pages for your loader(), they share the same options.

lib/source.ts
export const source = loader(
  {
    docs: docs.toFumadocsSource(),
    graphql: await graphql.staticSource({
      baseDir: 'graphql',
      baseUrl: '/docs',
    }),
  },
  // ...
);

per

Customize the content of pages, default to item.

modecontentfile path
itemeach operation & named type{name}.mdx
fileeverything in same schema{file_name}.mdx
customsee belowN/A

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

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

await graphql.staticSource({
  per: 'custom',
  toPages(builder) {
    builder.create({
      type: 'operation',
      path: 'my-orders.mdx',
      info: { title: 'My Orders' },
      item: { kind: 'query', name: 'orders' },
    });
  },
});

groupBy

For per: 'item', customize how generated pages are grouped into folders, default to kind.

modefolders
kindby their kind, e.g. queries/, objects/
noneno folders

You can also pass a function that returns the group name of an entry:

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

await graphql.staticSource({
  groupBy: (entry) => (entry.type === 'operation' ? 'operations' : 'types'),
});

includeOperations & includeTypes

For per: 'item', filter the operations (query/mutation/subscription fields) and named types to generate pages for, default to true.

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

await graphql.staticSource({
  // skip subscriptions
  includeOperations: (kind, field) => kind !== 'subscription',
  // skip internal types
  includeTypes: (type) => !type.name.startsWith('Internal'),
});

name & slugify

Customize the file name of generated pages.

GraphQL names are already URL-safe, hence the original name (including its case) is kept by default.

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

await graphql.staticSource({
  name: (entry) => entry.item.name.toLowerCase(),
});

slugify converts group names (and item names by default) into URL-friendly segments.

baseUrl

The baseUrl of your loader().

When specified, links of generated pages are pre-generated and passed to the UI, so type & operation references are cross-linked automatically.

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

await graphql.staticSource({
  baseUrl: '/docs',
});

meta

Generate meta.json files to customize the page tree, disabled by default.

folderStylepage tree
foldera folder per group (default)
separatora separator per group, with pages under it
import { graphql } from '@/lib/graphql';

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

Loader Plugin

loaderPlugin() decorates GraphQL pages in your page tree:

  • a query/mutation/subscription badge per operation page.
  • a strikethrough on deprecated operations.
lib/source.ts
export const source = loader(
  // ...
  {
    baseUrl: '/docs',
    plugins: [graphql.loaderPlugin()],
  },
);

How is this guide?

Last updated on

On this page