Docs

Authoring docs

Edit and extend the Convoy docs site — where content lives, how the sidebar is configured, and what stays in sync with code.

The public docs site lives under apps/docs/. Content is MDX under apps/docs/content/docs/. This page documents the site's conventions so a contributor can make edits with confidence and without breaking the sidebar.

Where content lives

apps/docs/content/docs/
├── meta.json                  # Root sidebar configuration
├── index.mdx                  # /docs (landing)
├── <section>/
│   ├── meta.json              # Optional per-folder config
│   ├── index.mdx              # /docs/<section>
│   └── <page>.mdx             # /docs/<section>/<page>

Each .mdx file becomes one page. Every folder can have a meta.json to control its title and its page ordering.

Local development

From the repo root:

pnpm docs:dev             # https://docs.convoy.localhost
pnpm docs:types:check     # Typegen + MDX + tsc --noEmit
pnpm docs:build           # Production build
pnpm docs:lint            # Biome

Run types:check, build, and lint before opening a PR. Biome is strict about JSON formatting — small meta.json pages arrays must be on a single line; multi-line arrays for longer lists.

meta.json basics

{
  "title": "Section title",
  "description": "Shown under the title.",
  "defaultOpen": false,
  "collapsible": true,
  "pages": ["index", "first-page", "second-page"]
}
FieldPurpose
titleSidebar label.
descriptionOptional, mostly informational.
defaultOpenInitial-load state for collapsible folders. Set to false so readers see a compact sidebar; the folder containing the active page auto-expands anyway.
collapsibleWhether the folder collapses at all.
pagesExplicit page ordering. Use "<name>" for a file, "<folder>" for a nested folder, and "---[icon]Label---" for a section separator.

The root-meta flattening gotcha

This one trips people up.

The root apps/docs/content/docs/meta.json uses separators to define the visible sidebar sections (Getting started, Deploy Convoy, CLI & AI integrations, etc.). For most sections, root meta lists each page individually — e.g.

"---[terminal]CLI & AI integrations---",
"cli/index",
"cli/api-keys",
"cli/install",

When root meta lists a page path explicitly, root owns that page at priority 2. A folder-level meta.json inside cli/ would try to claim the same pages, but root has already claimed them, so the folder's pages ordering is ignored for the sidebar.

Practical rule:

  • To add or reorder pages in a flat section (Using Convoy, Operations, Contributing, Reference), edit the root meta.json. The section's own meta.json is used only for the folder's title in nested contexts.
  • To add or reorder pages in a collapsible sub-folder (e.g. cli/mcp/, cli/dev-container/), edit that folder's meta.json. Root lists the folder path (cli/mcp), not its children, so the folder's meta is authoritative.

If you add a new page and it doesn't appear in the sidebar, check whether root meta needs a new entry.

Section separators and icons

Root meta uses the ---[icon]Name--- syntax to draw visual separators for top-level sections. Available icons are registered in apps/docs/app/lib/source.ts:

const iconMap: Record<string, LucideIcon> = {
  "book-open": BookOpen,
  code: Code,
  compass: Compass,
  "layout-grid": LayoutGrid,
  rocket: Rocket,
  sparkles: Sparkles,
  terminal: Terminal,
  wrench: Wrench,
};

To use a new icon, import it from lucide-react and add it to the map with a stable kebab-case key. Separators without an icon still render; they just don't carry a glyph.

MDX components available in pages

The default Fumadocs MDX components are registered in apps/docs/app/components/mdx.tsx. Notable additions:

  • <Cards> / <Card title="…" description="…" href="…" /> — used on the landing to surface audience paths.
  • <Mermaid chart={} /> — for sequence and flowchart diagrams. Preferred over ASCII art when the diagram has more than three nodes.
  • Standard markdown: tables, code fences (including language-mermaid blocks, which render the same as the component), <kbd> keys.

What stays in sync with code

A few docs pages mirror specific code modules. Whenever you change the code, update the page in the same PR — otherwise readers get a misleading reference.

PageSource of truth
using/keyboard-shortcuts.mdxSHORTCUT_GROUPS in apps/web/components/blocks/sidebar/keyboard-shortcuts-dialog.tsx and the key literals in apps/web/lib/browser/hotkeys.ts.
reference/mcp-tools.mdxgetToolDefinitions() in apps/web/convex/mcp/tools.ts.
reference/config-toml.mdxConfigFileSchema in apps/cli/src/lib/config/types.ts and the profile resolver in profile.ts.
contributing/cli-architecture-and-lifecycle.mdxcliNormalizedEventValidator in apps/web/convex/lib/contracts/validators.ts and the runtime files under apps/web/convex/cli/lib/runtimes/.
reference/cli-commands.mdxThe commander definitions under apps/cli/src/commands/ (and addGlobalOptions in apps/cli/src/cli.ts).
reference/roadmap.mdxCLI_RUNTIME_SLUGS in apps/web/convex/cli/lib/runtimes/contracts.ts and the CLI-side runners under apps/cli/src/agent/runtimes/. Promote a runtime from "config only" to "supported" when the CLI-side runner lands.
reference/glossary.mdxDomain concepts introduced in the spec. Add an entry when a new term enters the product vocabulary.

Section landings

The convention for landing pages (<section>/index.mdx) is:

  1. Short intro paragraph.
  2. One or two context sections if needed (what this section covers, how it relates to the rest of the docs).
  3. End with a ## Next steps pointer list — 3–6 links, each with a one-phrase rationale.

Exceptions: landings whose whole body is already the pointer list (the Reference index, the Operations index) skip the separate "Next steps" block to avoid duplication.

Deploying the docs

The docs site is a static build. See Deploy the Docs Site for the hosting setup.

See also

On this page