Files
2026-07-13 12:38:34 +08:00

6.7 KiB

API Reference Customization

The API reference is auto-generated from public/openapi.json using fumadocs-openapi. We customize the rendering with hooks and CSS overrides that depend on fumadocs-openapi internals.

When upgrading fumadocs-openapi, verify all customizations below still work.

Architecture

public/openapi.json          ← v3.1 spec (auto-fetched, don't edit manually)
public/openapi-v3.json       ← v3.0 spec (auto-fetched, don't edit manually)
components/api-page.tsx      ← createAPIPage config, schema render hook
components/api-page.client.tsx ← Client-side playground config
components/schema-generator.tsx ← Server-side: walks OpenAPI schema → SchemaUIGeneratedData
components/custom-schema-ui.tsx ← Client-side: renders schemas with inline expansion
app/global.css               ← CSS overrides targeting fumadocs-openapi classes

Custom Schema Rendering

We replace fumadocs-openapi's default popover-based schema rendering with Stripe-style inline expandable sections.

api-page.tsx

  • schemaUI.render hook: intercepts all schema rendering
  • Returns null for #/components/schemas/Error to hide redundant error schemas
  • Passes isResponse flag (derived from readOnly/writeOnly) to hide "Required" labels on response fields
  • generateTypeScriptSchema: false disables the TypeScript Definitions copy box
  • playground: { enabled: true } enables the interactive API playground (requests are proxied through /api/proxy)

schema-generator.tsx

  • Server component that walks OpenAPI schemas into a normalized SchemaUIGeneratedData structure
  • Handles: objects, arrays, oneOf/anyOf, allOf (merged), enums, nullable types
  • Generates info tags for default (skips {} and []) and format
  • Uses ctx.schema.getRawRef for schema identity, falls back to auto-generated IDs

custom-schema-ui.tsx

  • Client component ('use client') with Radix Collapsible for expand/collapse
  • ResponseContext threads isResponse down to suppress "Required" on response fields
  • isExpandable() checks if schemas have actual nested structure (avoids useless expand buttons for primitive unions like string | string[])
  • Enums render as compact inline badges with "Possible values:" label

CSS Overrides (fragile on upgrade)

All in app/global.css under the "OpenAPI Reference" section. These target fumadocs-openapi's internal class structure because no hooks exist for these customizations. Parameter fields (Path/Query/Header) and content type labels are rendered by built-in components with no render hooks.

Rule Purpose Why CSS-only
Hide span.text-red-400 / span.text-fd-muted-foreground Remove default * and ? field indicators Parameter fields rendered by built-in components, no hook available
::after with content: "Required" Add explicit "Required" label for required fields Same as above
div.border.rounded-lg:not(:has(*)) Hide empty schema wrapper divs (when Error schema returns null) Wrapper div rendered outside schemaUI.render hook
p.text-fd-muted-foreground.not-prose:has(> code.text-xs) Hide application/json content type labels No hook to control content type display

API Versioning (v3.0 / v3.1)

Two API versions are served side-by-side with a Stripe-style version selector in the top nav bar.

URL structure

  • v3.1 (default): /reference/... — e.g. /reference/api-reference/tools/getTools
  • v3.0: /reference/v3/... — e.g. /reference/v3/api-reference/tools/getTools
  • All existing v3.1 URLs are unchanged — no breaking changes.

How it works

lib/openapi.ts               ← Creates two OpenAPI instances (v3.1 + v3.0)
lib/source.ts                ← Combined source: v3.1 at api-reference/, v3.0 at v3/api-reference/
lib/api-version.ts           ← Shared detectApiVersion() utility (single source of truth)
lib/use-api-version.ts       ← Client hook wrapping detectApiVersion for React components
lib/filter-api-version.ts    ← Tree filter: hides V3 folder for v3.1, lifts V3 children for v3.0
app/(home)/reference/(v31)/layout.tsx ← v3.1 layout: hardcodes version, renders DocsLayout with filtered tree
app/(home)/reference/v3/layout.tsx    ← v3.0 layout: hardcodes version, renders DocsLayout with filtered tree
components/version-selector.tsx ← Dropdown in top nav, navigates between /reference/ ↔ /reference/v3/
components/api-base-url.tsx  ← Dynamic base URL: v3.1 or v3 based on current path
components/api-endpoints-table.tsx ← Endpoint tables in index pages, shows versioned paths
components/version-badge.tsx ← Badge on endpoint pages showing API version

Content structure

v3.0 has its own complete page tree under content/reference/v3/:

  • v3/index.mdx — Overview (with v3 links and base URL)
  • v3/authentication.mdx — Auth docs (with v3 curl examples)
  • v3/rate-limits.mdx, v3/errors.mdx — Duplicated non-API pages
  • v3/api-reference/ — Auto-generated index pages + OpenAPI endpoint pages
  • v3/meta.json — Sidebar ordering

SDK Reference is version-independent and shared across both trees. Meta Tools moved out of the reference tree entirely — they now live under the Toolkits tab at /toolkits/meta-tools.

Version selector behavior

  • On an API page: swaps /reference//reference/v3/ (stays on same endpoint/category)
  • On overview (/reference): navigates to /reference/v3 (v3 has its own overview)
  • Full page reload on every version switch (server re-renders layout with filtered tree)

Auto-generation pipeline (docs-update-data.yml)

  1. fetch-openapi.mjs — fetches both v3.1 and v3.0 specs from backend
  2. generate-api-index.ts — generates index pages for both api-reference/ and v3/api-reference/
  3. CI tracks: openapi.json, openapi-v3.json, api-reference/, v3/api-reference/

Adding/modifying v3 content

  • API endpoint pages are auto-generated from the OpenAPI spec — no manual work needed
  • Index pages are auto-generated by bun run generate:api-index
  • Non-API pages (v3/index.mdx, v3/authentication.mdx, etc.) are manual copies — update both versions when content changes
  • v3/meta.json and v3/api-reference/meta.json control sidebar ordering

OpenAPI Spec Notes

  • v3.1 spec is OAS 3.0.0 format
  • v3.0 spec is also OAS 3.0.0 format with the same tag structure
  • All error responses use identical #/components/schemas/Error schema
  • Error descriptions vary per endpoint and are useful
  • info.description is empty (backend issue)
  • No response examples (backend issue)
  • nullable: true (OAS 3.0) is converted by fumadocs-openapi's dereferencer
  • Some properties named deprecated are required fields (spec issue, not the OpenAPI deprecated flag)