ZeroStarter

Documentation

Manage documentation content and search.

Overview

Documentation is managed using Fumadocs and stored in web/next/content/docs/. Full-text search is powered by Orama via Fumadocs.

Source of truth

web/next/docs.config.ts is the single source for docs structure and metadata. It maps each collection (docs, console) to ordered groups; every entry is keyed by the page's URL, and subgroups nest as { "Label": [...] }:

docs: {
  "Getting Started": [
    { "/docs": { title: "Introduction", description: "..." } },
    { "/docs/getting-started/architecture": { title: "Architecture", description: "..." } },
  ],
  Manage: [
    {
      Authentication: [
        { "/docs/manage/authentication": { title: "Authentication", label: "Auth & Organizations", description: "..." } },
      ],
    },
  ],
}

title/description are the page metadata; label overrides the sidebar text when it should differ from the title.

Generated artifacts

A generator (.github/scripts/docs.ts) runs inside the web/next build and dev. From docs.config.ts it:

  • writes each page's frontmatter (slug, title, description, and label when set), so you only author the body;
  • generates content/docs/meta.json (reading order + prev/next);
  • scaffolds a stub MDX in dev for any page declared in the config but missing on disk;
  • fails the build under --strict if the config and files have drifted, with a hint to re-run the generator.

meta.json is generated and git-ignored; never edit it by hand, as the generator overwrites it.

Creating a page

  1. Add an entry under the right group in web/next/docs.config.ts, keyed by the page URL (e.g. "/docs/manage/my-page"), with its title and description.
  2. Run the dev server (or bun .github/scripts/docs.ts): it scaffolds content/docs/manage/my-page.mdx with the frontmatter filled in.
  3. Write the body. Leave the frontmatter and meta.json alone; both are regenerated from the config.

Collections

web/next/source.config.ts defines three Fumadocs collections, not just docs/console:

  • docs (content/docs/): the public documentation, indexed by search, sitemap, and llms.txt.
  • blog (content/blog/): the public blog (see Blog).
  • consoleDocs (content/console/docs/): private docs served only under the access-protected /console area.

The console collection is private by construction: its source (consoleSource in web/next/src/lib/source.ts) is intentionally not referenced by any public route, so it is excluded from public search, the sitemap, and llms.txt. docs.config.ts maps the docs and console collections to ordered sidebar groups.

Configuration

The fumadocs source is configured in web/next/source.config.ts, with its frontmatter schema extended so the generated slug/label fields are accepted:

import { pageSchema } from "fumadocs-core/source/schema"
import { defineDocs } from "fumadocs-mdx/config"
import { z } from "zod"

const docsSchema = pageSchema.extend({
  slug: z.string().optional(),
  label: z.string().optional(),
})

export const docs = defineDocs({
  dir: "content/docs",
  docs: { schema: docsSchema, postprocess: { includeProcessedMarkdown: true } },
})

includeProcessedMarkdown keeps the rendered Markdown around so the llms.txt routes can serve a plain-text version of each page.

Full-text search indexes the documentation via a route handler at web/next/src/app/api/search/route.ts. It is built from docsSource with createFromSource, which wires up the Orama index automatically:

import { createFromSource } from "fumadocs-core/search/server"

import { docsSource } from "@/lib/source"

export const { GET } = createFromSource(docsSource, {
  // https://docs.orama.com/docs/orama-js/supported-languages
  language: "english",
})

Only the docs source is indexed; the blog and the private console docs are not part of search. Because this is a real Next.js route handler, it takes precedence over the generic /api/:path* rewrite in next.config.ts (which forwards the rest of /api/* to the backend), so no dedicated search rewrite is needed.

Keyboard Shortcut

Press Cmd+K (Mac) or Ctrl+K (Windows/Linux) to open the search dialog from any docs page. The search dialog supports full-text search across the documentation, heading-level results, and keyboard navigation.