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:

Id Plugin Fields Upstream reference JSON
docusaurus:docs:3.10 @docusaurus/plugin-content-docs 25 Docs front matter docusaurus-docs/3.10.json
docusaurus:blog:3.10 @docusaurus/plugin-content-blog 20 Blog front matter docusaurus-blog/3.10.json
docusaurus:pages:3.10 @docusaurus/plugin-content-pages 9 Pages front matter docusaurus-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.

Property Value
Dialect Draft 2020-12
Additional properties Allowed (additionalProperties: true)
Required fields None, in any of the three
Reference kind builtin
On by default No; see turning one on

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.)
Field Type Constraint
id string n/a
title string may be empty
description string may be empty
slug string n/a
sidebar_label string n/a
sidebar_position number n/a
sidebar_class_name string n/a
sidebar_key string n/a
sidebar_custom_props object n/a
displayed_sidebar string or null n/a
pagination_label string n/a
pagination_next string or null n/a
pagination_prev string or null n/a
hide_title boolean n/a
hide_table_of_contents boolean n/a
toc_min_heading_level number 2–6
toc_max_heading_level number 2–6
parse_number_prefixes boolean n/a
custom_edit_url string or null uri-reference
keywords array of string n/a
image string uri-reference
tags array string, or object with label and permalink
draft boolean not both with unlisted
unlisted boolean not both with draft
last_update object author and/or date, at least one, nothing else

sidebar_position is a number. Quoting it makes it a string, and Docusaurus rejects it. This is the most common front matter mistake these schemas catch:

✗ docs/install.md
/sidebar_position must be number (line 3) [docusaurus:docs:3.10]

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. Because JSON Schema expresses this as a conditional, it reports twice. Once on the field to change, and once on the rule as a whole:

✗ docs/install.md
/unlisted must be equal to constant (line 4) [docusaurus:docs:3.10]
(root) must match "then" schema (line 1) [docusaurus:docs:3.10]

Read the first line, then drop unlisted (or draft) and both clear.

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_leveltoc_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.