Skip to content

Built-in Docusaurus schemas

manni meta ships the front matter contract of Docusaurus 3.10 as three built-in schemas, one per content plugin:

IdPluginFieldsUpstream referenceJSON
docusaurus:docs:3.10@docusaurus/plugin-content-docs25Docs front matterdocusaurus-docs/3.10.json
docusaurus:blog:3.10@docusaurus/plugin-content-blog20Blog front matterdocusaurus-blog/3.10.json
docusaurus:pages:3.10@docusaurus/plugin-content-pages9Pages front matterdocusaurus-pages/3.10.json

Each JSON link is the schema itself, at a permanent, version-pinned URL. A Docusaurus site’s front matter contract is the thing most likely to be checked by something other than manni meta. These are the three worth handing to another tool directly.

PropertyValue
DialectDraft 2020-12
Additional propertiesAllowed (additionalProperties: true)
Required fieldsNone, in any of the three
Reference kindbuiltin
On by defaultNo; see turning one on

Each schema has a page of its own, with its field table, an example page, and the finding a common mistake produces:

This page covers what the three share.

Docusaurus marks no front matter field as required in any of the three plugins. A page with an empty --- block builds fine. These schemas mirror that: they constrain the shape of every field the plugins document, and demand none of them.

That makes them the opposite of the taxonomy schemas, which require their key. Turning a Docusaurus schema on cannot fail a page that was already building. It can only catch a value your site would have rejected, or silently mishandled, later.

Why check what Docusaurus already validates

Section titled “Why check what Docusaurus already validates”

Docusaurus validates its own front matter at build time, so these schemas are not a substitute for it. They earn their place three ways:

  • One report instead of one failure. A Docusaurus build stops at the first bad file. manni meta validate reports every offending page in the docs set in one run, with a line number for each.
  • Before a build, not during one. Validation needs no site config, no install of Docusaurus, and no build step. It runs in seconds on a pull request that touches ten files.
  • Alongside your own standard. These schemas claim neither type nor action, so they compose with any of the taxonomy vocabularies. One command holds a page to the generator’s contract and your docs set’s conventions, attributing each failure to the schema that raised it. (Stacking with google:okf:0.1 is the one exception. Both define tags, and their definitions disagree.)

These rules hold in every Docusaurus schema that carries the fields they name. sidebar_position is a docs-only field, so the finding a quoted one produces is on the docs schema page.

draft and unlisted are mutually exclusive. Setting both to true is the one cross-field rule Docusaurus enforces, and the schemas encode it. Either flag on its own is fine. The finding lands on the field to change:

✗ docs/install.md
/unlisted must be false (line 4) [docusaurus:docs:3.10]
docusaurus:docs:3.10 unlisted: An unlisted document is published but hidden from navigation, search, and sitemaps.
Guide: https://hawkeyexl.github.io/manni/meta/reference/schemas/docusaurus-docs/

Drop unlisted (or draft) and it clears.

last_update takes author, date, or both, and nothing else. It is the only place the schemas forbid unknown keys, because a misspelled autor there is silently dropped rather than reported.

image and custom_edit_url are URI references. A site-root path like /img/social/card.png is legal. These use uri-reference rather than uri, which would wrongly reject every relative path.

Tag objects need both halves. A tag is either a plain string or an object carrying label and permalink. Half an object fails.

  • toc_min_heading_level ≤ toc_max_heading_level. Docusaurus enforces the relationship between the two; JSON Schema cannot express a comparison between sibling fields without a non-portable extension. Each is range-checked to 2–6 on its own, and an inverted pair passes here and fails at build time.
  • Unknown keys. Docusaurus calls .unknown() on its own validators, so themes and plugins routinely add front matter of their own. Being stricter than Docusaurus would fail working sites, so these schemas allow extra keys.
  • Whether a reference resolves. pagination_next, displayed_sidebar, and authors are checked for shape, not for whether the id, sidebar, or authors.yml entry they name exists.

A Docusaurus site has three content roots with three different contracts. Each root is a document set the whole site thinks in, so declare the three as collections and point one override at each:

manni.config.yaml
collections:
- name: guides
paths: [docs]
- name: blog
paths: [blog]
- name: pages
paths: [src/pages]
meta:
overrides:
- collection: guides
schemas:
- docusaurus:docs:3.10
- diataxis:diataxis:1.0
- collection: blog
schemas:
- docusaurus:blog:3.10
- collection: pages
schemas:
- docusaurus:pages:3.10

Two things about the names. docs is refused, because manni meta query builds a table of that name and each collection becomes a view beside it. So the Docusaurus docs/ root is guides here. That leaves pages free for src/pages, the root Docusaurus itself calls pages and whose schema is named for it. And once the roots are named, a run can address one of them: manni meta validate --collection blog.

The first matching override wins, so order them from most to least specific. For a one-off run, pass the id directly:

Terminal window
manni meta validate docs/ -s docusaurus:docs:3.10

The version segment is the Docusaurus minor release the contract was transcribed from, because that is where fields are added. sidebar_key is a recent arrival. A new minor arrives as a new id rather than a change to docusaurus:docs:3.10, so upgrading manni meta never retightens a check you already passed. Pin the id matching the Docusaurus you run, and move it when you upgrade.