Frontmatter
Validate YAML metadata keys with front directives, including presence, allow-lists, dates, placeholders, patterns, and closure.
Bishop: "I may be synthetic, but I'm not stupid." Metadata deserves the same treatment: small rules, clear boundaries, no mystery cargo in the hold.
front declares rules for YAML frontmatter. It is a structural marker, written as front <key> for one metadata key, or as bare front noExtraKeys to close the whole metadata set. It has no end tag.
The frontmatter reader handles the common subset — the leading --- … --- block with top-level key: value pairs. Nested maps, lists, and block scalars are out of scope for the front <key> rules, which target one top-level key each.
<!-- mdv: front status required oneof=draft,review,published -->
<!-- mdv: front date date=iso -->
<!-- mdv: front noExtraKeys -->That contract says:
statusmust exist, and it must bedraft,review, orpublished.datemust be an ISO date if it is present.- no other frontmatter keys are allowed.
It validates a document like this:
---
status: review
date: 2026-06-28
---
# Mission logWhat it catches
Point that same contract at a document where the metadata is wrong on every axis:
---
status: shipped
date: last-tuesday
author: dana
---
# Mission logmission.md:1 error [frontmatter-not-allowed-value] The frontmatter key "status" is "shipped", which is not an allowed value (draft, review, published).
mission.md:2 error [frontmatter-bad-date] The frontmatter key "date" is "last-tuesday", which is not an ISO date.
mission.md error [unexpected-frontmatter-key] The frontmatter key "author" is not one the schema declares.Two more cases worth knowing:
- A missing or empty required key both report
[missing-frontmatter-key]("required, but is missing or empty") — an emptystatus:is treated the same as omitting it. - A duplicated key emits a
[duplicate-frontmatter-key]warning, and the first value is the one validated — so a stray seconddate:doesn't silently override the real one.
Rules
| rule | what it checks |
|---|---|
required | the key must be present |
optional | the key may be absent |
oneof=a,b,c | the value must be one of the listed options |
date=iso | the value must be ISO-shaped — YYYY-MM-DD or a full timestamp. A regex check, not a calendar check, so an impossible date like 2026-13-99 still matches. It is a content concern (the real date is human-owned), so it surfaces under validateState, not validateSyntax |
noPlaceholder | placeholder values like TODO or TBD are rejected |
pattern=/regex/ | the value must match the regex |
front noExtraKeys | no frontmatter key is allowed unless the contract declares it |
Use front noExtraKeys when the metadata shape is part of the contract, like a release note with exactly status and date. Leave the fence open when authors need room for local metadata from another tool.