Skip to main content

What the Validator Checks

Type: ReferenceCreated: Last reviewed: Team: Platform
published

Why docs are validated

The handbook is plain Markdown in a Git repo, so nothing structurally stops a doc from shipping with a missing owner_team, a broken heading ladder, or an unsafe HTML tag. The validator is what keeps the rules in Fill the Frontmatter, the heading conventions, and The Audio Layer from being merely advisory. It enforces only what is mechanically checkable — style, tone, and clarity stay the reviewer's job.

The rules themselves are explained, with their reasoning, in the docs they belong to. This page is the consolidated lookup: every check in one place, and what each one does to your save.

Errors versus warnings

Every check produces one of two severities, and the difference is the whole contract:

  • Errors block the save. The doc is not written until you fix them. An invalid doc can never land.
  • Warnings surface but pass through. They flag likely problems (a too-short description, a heading that smells like two topics) without stopping you. Use judgement.

Where validation runs

The same validator code runs in three places, so the rules are identical everywhere:

  • In the editor, as you write — issues appear live in the validation gutter. This is guidance, not a gate.

  • In the API worker, at save time — this is the real chokepoint. The worker is the sole writer to the content repo, so it re-runs the validator on every save and rejects the commit if there are any errors. When that happens the API returns:

    {
    "error": "Document has 2 validation errors and was not saved",
    "code": "VALIDATION_FAILED",
    "issues": [ ]
    }
  • In CI, as a backstop — when the validation rules themselves change, a workflow re-validates the entire content repo to catch any already-committed doc the new rules would now reject.

One exception: the audio narration rules are skipped at the save gate, because the .audio.txt companion is a separate file written separately. They run in the editor and in CI only.

The rule catalog

Frontmatter rules

The YAML metadata block at the top of every doc.

RuleSeverityWhat it flags
frontmatter/missingErrorThe doc has no YAML frontmatter block at all.
frontmatter/required-fieldErrorA required field is absent: title, description, doc_type, owner_team, status, or created.
frontmatter/enumErrordoc_type or status holds a value outside its allowed set.
frontmatter/owner-team-formatErrorowner_team is an email instead of a team slug.
frontmatter/owner-team-unknownErrorowner_team is not a slug in the team registry.
frontmatter/date-formatErrorcreated or last_reviewed is not an ISO YYYY-MM-DD date.
frontmatter/future-reviewErrorlast_reviewed is dated in the future.
frontmatter/sidebar-label-forbiddenErrorsidebar_label is present; the sidebar must show the title.
frontmatter/description-shortWarningdescription is under 20 characters — too short to be useful in search.
frontmatter/description-longWarningdescription is over 200 characters — keep it to one sentence.

Heading rules

Heading levels and hygiene in the body.

RuleSeverityWhat it flags
headings/no-body-h1ErrorAn H1 appears in the body; the page H1 is rendered from title.
headings/min-h2ErrorThe page has no H2; section boundaries are required for audio and search.
headings/no-level-skipErrorA heading jumps a level, such as H2 straight to H4.
headings/trailing-punctuationWarningA heading ends with punctuation.
headings/no-formattingWarningA heading contains backtick, bold, or italic markup.
headings/single-topicWarningA heading likely combines two topics (contains a comma or the word "and").

Body markdown rules

Code blocks, images, HTML, JSX, admonitions, and embeds.

RuleSeverityWhat it flags
markdown/code-block-languageErrorA fenced code block has no language tag (use text for plain output).
markdown/image-altErrorAn image has empty alt text.
markdown/directive-allowlistErrorA ::: directive is not a known admonition (note, tip, info, warning, danger).
markdown/jsx-allowlistErrorA JSX component is not on the registered list (Tabs, TabItem, Details).
markdown/forbidden-htmlErrorA forbidden HTML tag such as script, an inline event handler, or a style attribute was used.
markdown/video-srcErrorA video tag is missing src or points outside /api/videos/.
markdown/iframe-srcErrorAn iframe is missing src or its host is not YouTube or Loom.
markdown/inline-htmlWarningAn HTML tag outside the allow-list was used.

Audio narration rules

Checked only when a companion .audio.txt exists — in the editor and CI, not at the save gate.

RuleSeverityWhat it flags
audio/missing-markerErrorA body heading has no matching ##/### marker in the narration file.
audio/orphan-markerErrorA narration marker matches no H2/H3 heading in the doc.