GraphQL
Drop in a GraphQL schema and get a native API reference — one real page per operation and per type, in your sidebar and search.
Point Blume at a GraphQL schema and it generates a native API reference: one real page per root field — queries, mutations, and subscriptions — plus one page per named type (objects, input objects, enums, interfaces, unions, and custom scalars). Every page shows arguments, defaults, deprecations, and usage backlinks, alongside a generated example operation, code samples, and an interactive Try it panel. Because each page is a genuine Blume page, it gets its own URL, shows up in site search and llms.txt, and gets an Open Graph image — the same as any hand-written doc.
The reference is the graphql() adapter from blume/reference, listed under reference beside any OpenAPI or AsyncAPI adapters:
import { defineConfig } from "blume";
import { graphql } from "blume/reference";
export default defineConfig({
reference: [
graphql({
spec: "./schema.graphql",
endpoint: "https://api.example.com/graphql",
}),
],
});
That mounts the reference at /graphql (an overview page), with root fields at /graphql/queries/<field>, /graphql/mutations/<field>, and /graphql/subscriptions/<field>, and types grouped by kind at /graphql/objects/<type>, /graphql/enums/<type>, and so on.
The spec is either a path to a local file in your project or an http(s) URL, and accepts two formats:
- SDL text — a
.graphqlfile with type definitions. Directives the file uses without declaring them, such as Apollo Federation’s@keyor AppSync’s@aws_*, are ignored. - An introspection result — the JSON produced by running the standard introspection query, either the raw
{ "__schema": … }shape or the full{ "data": { "__schema": … } }response envelope.
The endpoint is the live GraphQL API URL. A schema, unlike an OpenAPI document, names no server — so the endpoint is what the Try it panel and the generated code samples target. Leave it off and the samples render with a placeholder URL readers replace.
The reference doesn’t add a header tab on its own. To surface it, point a navigation tab at its route — this also scopes the reference sidebar:
navigation: {
tabs: [{ label: "GraphQL", path: "/graphql" }],
}
Generate GraphQL docs from your schema walks through it from a schema to a deployed site, with a Try it panel that queries a sandbox.
Generated examples
Every operation page carries a complete, valid example operation — one variable per argument, typed off the schema, with a bounded-depth selection set over the return type — plus matching example variables and an example response that mirrors the same selection. A variable whose argument declares a default starts at that default, and the selection leaves deprecated fields out. Code samples show the exact HTTP request (a JSON POST of { query, variables }) in each configured language. The same languages as openapi() are available, and codeSamples: false shows none:
reference: [
graphql({
spec: "./schema.graphql",
codeSamples: ["curl", "js"], // any language openapi() offers
}),
],
An id Blume doesn’t generate a sample for is left out, with a BLUME_GRAPHQL_UNKNOWN_CODE_SAMPLE warning that lists the ones it does.
Type pages
Named types get their own deep-linkable pages, grouped by kind in the sidebar: fields and input fields with their types linked, enum values, union members, interface implementations, and a Used by section listing the operations that return or accept the type and the other types that reference it. Spec-defined scalars (String, Int, …) don’t get pages; custom scalars do, including their specifiedBy URL.
Multiple schemas
Each entry in sources renders one schema on its own route. A per-source endpoint overrides the adapter’s:
reference: [
graphql({
endpoint: "https://api.example.com/graphql",
sources: [
{ label: "Public API", spec: "./schema.graphql" },
{
label: "Admin API",
route: "/graphql-admin",
spec: "./admin.graphql",
endpoint: "https://admin.example.com/graphql",
},
],
}),
],
spec is shorthand for a single-entry sources. Schemas that need different display options go in separate graphql() adapters, each with its own route. Each source takes the same per-source controls as openapi(): includeInSearch, includeInLlms, noindex, and seoDescriptionSuffix (here the generated sentence names the query, mutation, or type — “Reference for the pets query in the GraphQL API.”).
Try it playground
Query and mutation pages render an interactive panel: edit the request body (the query and variables), point it at your endpoint or a custom URL, and send — the code samples update live so what you copy is byte-for-byte what was sent. Disable it with playground: false. Subscription pages show the generated operation and an example event instead: subscriptions run over a stateful transport (WebSocket or SSE) that the playground’s single HTTP POST can’t speak.
A schema doesn’t say how its API authenticates, so the panel sends no credentials until auth does. It takes the same shape as api.auth for hand-written endpoint pages: method is bearer, basic, key (an API key in a header), or none, and name is the header an API key goes in (x-api-key by default). Every operation page then gets an Authorization section, the panel a credential field that works like the OpenAPI one, and the code samples a placeholder credential. A per-source auth overrides the adapter’s:
reference: [
graphql({
spec: "./schema.graphql",
endpoint: "https://api.example.com/graphql",
auth: { method: "bearer" },
}),
],
If your GraphQL API doesn’t allow cross-origin requests from the docs site, route sends through a CORS proxy — a URL of your own, or true for the built-in /_api-proxy endpoint (under your basePath, if you set one; it needs server output: a host adapter such as deployment: vercel() from blume/deploy). The built-in proxy only forwards to origins your documented specs declare — each configured GraphQL endpoint, plus any absolute servers[].url from a documented OpenAPI spec — so a public docs deployment can’t be aimed at other hosts. That makes endpoint required for a working proxy: without one, the proxy has no origin to allow for this reference and refuses every send (the build warns about this). The same body limit, header forwarding, and response headers apply as for the OpenAPI proxy.
reference: [
graphql({
spec: "./schema.graphql",
endpoint: "https://api.example.com/graphql",
playground: { proxy: true },
}),
],
There is no Scalar counterpart for GraphQL: the scalar() embed reads OpenAPI and AsyncAPI documents only, so a GraphQL reference is always rendered natively.