document frontmatter
rule
every authored .mdx file, and every required .md file whose consumer allows
it, starts with valid YAML frontmatter. every key is snake_case, including
nested keys. frontmatter is queryable data that becomes a SQLite column or
field; it follows table and column naming rules, never camelCase or PascalCase.
a document that cannot be parsed, classified, or discovered by metadata is not
organized enough to be a project contract.
why
frontmatter is the corpus's query interface. once a key becomes a database
column, its spelling is a stable contract for every index, join, and automated
check that consumes it; snake_case is the column-naming rule that keeps those
consumers working across moves and renames. decorative or inconsistently cased
metadata forces consumers to guess, so they diverge or skip the field. the
invariant: classification and discovery depend on stable typed fields, never on
filenames or folder inference.
required fields
---title: short exact document namevisibility: privatestatus: draftkind: standard---
title— shortest exact human name for the document's responsibility.visibility— who may see the document; never inferred from a folder.status—draft,approved,implemented,superseded, or another defined lifecycle state.kind— artifact class:catalog,domain,standard,specification,decision,runbook,reference.
add typed project-specific fields only when they support discovery or an
automated check — e.g. canonical_url, content_policy, owner,
updated_at, generated. no decorative metadata.
choose metadata by a reader or machine question
| field | question it answers | owner |
|---|---|---|
title | what exact responsibility does this document explain? | author, using the glossary. |
visibility | who may receive or render this content? | content/security decision. |
status | is this draft, approved, implemented, superseded, or otherwise current? | owning decision process. |
kind | how should indexers, renderers, and agents classify it? | documentation taxonomy. |
| provenance/hash/generated time | can a tool prove source or freshness? | generator/verifier, not hand edit. |
| domain/capability/owner | where does an agent find the contract? | domain owner when discovery needs it. |
if no reader, index, validation, visibility rule, or freshness gate consumes a field, do not add it. metadata is a query interface, not a decorative header.
| invalid key | canonical key |
|---|---|
canonicalUrl | canonical_url |
sourceRepo | source_repo |
implementationHash | implementation_hash |
updatedAt | updated_at |
pathSegments | path_segments |
the same rule applies to generated provenance: change the generator/schema and regenerate every mirror; never hand-edit generated pages to rename a key.
decision process
| shortcut | failure | selected direction |
|---|---|---|
| infer visibility from the folder | a copied or embedded document silently changes exposure | declare visibility explicitly. |
| use a filename as the only classification | moves/renames break discovery and queries | keep stable typed metadata. |
| hand-update generator-owned timestamps/hashes | evidence claims a check that did not happen | run the owning generator/verifier. |
| introduce free-form status words | indexes cannot distinguish lifecycle states | use a defined status vocabulary. |
good and bad
bad
---title: query key ownershippathSegments: [curly, contracts, query-key-ownership]updatedAt: today---
camel-case keys cannot become stable database columns, and today is not
queryable freshness evidence. every downstream consumer either fails to read
the fields or forks its own spelling workaround — two vocabularies for the same
fact. the drift is silent: nothing breaks at author time, only at the first
join, index rebuild, or freshness check that queries a column nobody wrote.
good
---title: query key ownershippath_segments: [curly, contracts, query-key-ownership]updated_at: 2026-08-25visibility: privatestatus: draftkind: standard---
every key is a stable field name and every value has a defined consumer, so an index, a join, and an automated check read the same fact without adaptation, and documents move or rename without breaking classification. the metadata becomes a real query surface: lifecycle sweeps, visibility audits, and freshness gates are one SQL statement instead of a manual review of every file.
verification
- parse frontmatter through the owning schema.
- query a representative field in the document index.
- confirm every machine-owned field is consistent with its generator/verifier.
- check a move or filename rename leaves classification and links intact — consumers read metadata rather than infer it.
do not
- write an MDX document without frontmatter.
- omit frontmatter from a required Markdown file unless its consumer requires an exact non-frontmatter opening.
- put frontmatter after prose, an HTML comment, or a title.
- duplicate metadata in a filename when the parser can read the canonical field.
- use camelCase, PascalCase, hyphenated, or space-separated frontmatter keys.
- hand-edit frontmatter owned by a generator; change its source contract and regenerate instead.