Frontmatter
Frontmatter
Every page is a .mdx file with a YAML frontmatter block. Leadtype reads three things from it: what the page is, where it lives in the nav, and how to lint it.
Minimum
title— required. Non-empty string. Renders as the page heading and as the entry text inllms.txtand the sidebar.description— optional but recommended. Becomes the routing hint inllms.txt. If omitted, the converter synthesizes one from the body during conversion (see convert behavior).group— optional. Slug of a group declared indocs.config.ts. Pages without a group are excluded from the nav and grouped indexes, but still appear in generated markdown and the rootllms-full.txtfallback.
How groups become a nav tree
Each page may declare one or more group slugs with group: <slug> or group: [a, b], so pages can be shared across multiple groups. Each group is declared once in docs.config.ts. leadtype generate loads that config automatically when it exists. The intersection produces the nav tree, the section headings in llms.txt, search metadata, and AGENTS.md grouping.
If a page declares a group slug that isn't in docs.config.ts, the build fails with unknown group "<slug>". Same source of truth, no drift.
If you do not have a docs.config.ts, the CLI infers groups from the group: values it finds. That fallback is enough for small docs sets, but use config when you need stable order, descriptions, or nested groups.
Nested groups
Declare children in the config to build deeper trees:
A page sets group: remote-source and lands in that nested slot. Only leaf groups (no children) directly contain pages; non-leaf groups are headings only.
Optional fields
The default lint schema also accepts:
| Name | Type | Default | Description |
|---|---|---|---|
icon | string | - | Icon name resolved by your sidebar component. |
deprecated | boolean | - | Marks the page as deprecated in nav and search. |
deprecatedReason | string | - | Short message paired with deprecated. |
experimental | boolean | - | Marks the page as experimental. |
canary | boolean | - | Hides from stable channels. |
new | boolean | - | Highlights the page as recently added. |
draft | boolean | - | Excludes from generation entirely. |
tags | string[] | - | Free-form tags for search facets. |
availableIn | Array<{ framework, url?, title? }> | - | Cross-framework availability map for TopicSwitcher pages. |
full | boolean | - | Layout hint for docs UIs that support full-width pages. |
lastModified and lastAuthor are filled in automatically when you pass --enrich-git to the CLI. Don't author them by hand.
Lint rules
leadtype lint enforces the schema, so violations surface in CI before they reach a build. The relevant rules:
schema— a required field is missing or has the wrong type.unknown-field— a top-level field isn't in the schema (warn by default;--error-unknownto fail).parse-error— frontmatter ormeta.jsondoesn't parse.invalid-link— a/docs/...link points to a route that doesn't exist.unresolved-placeholder— a doc URL still contains an unresolved{framework}placeholder.cross-framework-link— a framework-scoped page links to another framework's docs.
See Lint rules for the full reference and how to extend the schema.
What this gives you
Once frontmatter is consistent, the rest of the pipeline works without per-page configuration. The same group: value drives:
- The sidebar position
- The
llms.txtsection - Search metadata and AGENTS.md grouping
- The search filtering UI (if you build one)
- Cross-framework link checks in lint
One field, one source of truth.