Author a schema for your metadata standard
Your metadata standard already exists, even if it only lives in a style guide or in people’s heads: “every page needs a type,” “timestamp should be an ISO date,” “API pages must declare a version.” A JSON Schema turns those agreements into a file that docmeta can enforce on every commit. This page walks through writing that schema, from a minimal one-field example up to the fuller built-in OKF schema, and shows how a document points itself at the schema you wrote.
A schema is just a JSON file
Section titled “A schema is just a JSON file”docmeta validates against standard JSON Schema. If you can write JSON, you can write a docmeta schema; there is no docmeta-specific schema format to learn. A schema describes the frontmatter object: which keys are required, what type each value should be, and whether unexpected keys are allowed.
Here is the smallest schema worth shipping. It says: the metadata must be an object, it must have a title, and that title must be a non-empty string.
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "required": ["title"], "properties": { "title": { "type": "string", "minLength": 1 } }}This is the extra.schema.json fixture that docmeta’s own test suite runs, so you can trust it compiles and validates exactly as shown. Four things are doing the work:
"$schema"at the top names the JSON Schema dialect this file is written in: here, draft 2020-12. docmeta reads this line to pick the right validation engine. (This is the schema’s own dialect declaration. It is different from the$schemakey you put in a document to choose a schema, covered below.)"type": "object"says the metadata is a set of key/value pairs, which frontmatter always is."required": ["title"]is the list of fields that must be present. A document missingtitlefails validation."properties"describes individual fields.titlemust be a string, andminLength: 1rejects an emptytitle:that a contributor left blank.
A document with this frontmatter passes:
---title: Getting started---A document with empty or missing title fails. That is the whole loop: declare the shape, and docmeta holds every file to it.
Required vs. recommended fields
Section titled “Required vs. recommended fields”The single most important decision in a metadata schema is which fields are required and which are merely recommended. JSON Schema models this with one list:
- Required: list the field in
"required". Its absence is a hard failure. - Recommended (optional): describe the field in
"properties"but leave it out of"required". If the field is present, docmeta checks its type and format; if it’s absent, that’s fine.
This distinction is what lets you encode a standard that has a strict core and a softer edge. In the example below, type is mandatory, while title and tags are validated when present but never demanded:
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "required": ["type"], "properties": { "type": { "type": "string", "minLength": 1 }, "title": { "type": "string" }, "tags": { "type": "array", "items": { "type": "string" } } }}Constrain values with types and formats
Section titled “Constrain values with types and formats”Requiring a field guarantees it exists; constraining it guarantees it’s usable. JSON Schema gives you the building blocks, and docmeta supports the standard format checks through ajv-formats. Two formats come up constantly in document metadata:
Use "format": "date-time" to require an ISO 8601 timestamp. This catches the classic fat-fingered date: 2026-13-01, June 5th, or a bare 2026-06-25 where a full timestamp was expected.
"timestamp": { "type": "string", "format": "date-time", "description": "ISO 8601 datetime of last meaningful change."}Passes: 2026-06-25T14:30:00Z
Fails: June 5th, 2026-13-01
Use "format": "uri" for fields that must hold a well-formed URI, such as a canonical resource link. This checks the shape of the URI; it does not fetch the URL.
"resource": { "type": "string", "format": "uri", "description": "A URI uniquely identifying the underlying asset."}Passes: https://example.com/asset/42
Fails: not a url, example.com (no scheme)
Beyond formats, the everyday constraints carry most of the weight:
enum: restrict a field to a fixed set of values, ideal for a controlledtypeorstatus:"enum": ["guide", "reference", "tutorial"].minLength: reject empty strings ("minLength": 1).array+items: validate every element of a list, as with thetagsexample above.
Decide whether unknown fields are allowed
Section titled “Decide whether unknown fields are allowed”By default, JSON Schema lets a document carry fields your schema never mentions. Whether to permit that is a deliberate choice, controlled by additionalProperties:
"additionalProperties": true(or omitting it): extra keys are tolerated. Contributors can add experimental or tool-specific frontmatter without tripping the check. This is the lenient default and a good fit for a young or shared standard."additionalProperties": false: every key must be declared in"properties". An unexpected key is a failure. Use this to catch typos liketitel:or to keep frontmatter tightly governed.
A fuller example: the built-in OKF schema
Section titled “A fuller example: the built-in OKF schema”The schema anchoring docmeta’s default set is Open Knowledge Format (OKF) v0.1, addressed as google:okf:0.1. (Run docmeta schemas for the full built-in list.) It’s a useful reference because it combines every technique on this page in a realistic standard, so reading it is the fastest way to see how the pieces fit together. When no other schema applies, docmeta falls back to a set rather than to OKF alone: google:okf:0.1 together with passo-uno:seven-action:1.0, which constrains an optional action field and requires nothing of its own.
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "google:okf:0.1", "title": "Open Knowledge Format (OKF) v0.1", "description": "Frontmatter schema for OKF v0.1 concept files. OKF requires only `type`; all other fields are recommended, and unknown keys are explicitly tolerated.", "type": "object", "required": ["type"], "additionalProperties": true, "properties": { "type": { "type": "string", "minLength": 1, "description": "A short string identifying the kind of concept." }, "title": { "type": "string", "description": "Human-readable display name." }, "description": { "type": "string", "description": "Single-sentence summary used for indexing and previews." }, "resource": { "type": "string", "format": "uri", "description": "A URI uniquely identifying the underlying asset." }, "tags": { "type": "array", "items": { "type": "string" }, "description": "Short strings for categorization." }, "timestamp": { "type": "string", "format": "date-time", "description": "ISO 8601 datetime of last meaningful change." } }}Notice the design choices OKF makes, each one a decision you’ll face in your own schema:
- Exactly one required field (
type). OKF demands the bare minimum, so adopting it rarely breaks existing files. additionalProperties: true, stated explicitly. Unknown keys are welcome by design, because OKF is meant to be extended.- Recommended fields with real constraints.
title,description, andtagsare optional, but if present they’re checked.resourceandtimestampcarryurianddate-timeformats. - A
$idand human-readabletitle/description. These aren’t required for validation, but they document the schema for the humans who read it, and$idis what gives the built-in itsgoogle:okf:0.1address. Setting a$idin a schema file of your own does not register a new built-in id — built-ins are bundled into docmeta — so you reference your own schema by its file path or URL, never by its$id. Give it an id of your own, or leave it out; see the warning below before reusing one.
Borrow a schema instead of writing one
Section titled “Borrow a schema instead of writing one”Everything above assumes you’re defining the field set yourself. docmeta ships seven schemas you can adopt without authoring anything — the built-in schema registry lists all of them in one table, with what each constrains and which two are on by default.
If your site is built with Docusaurus, start with
docusaurus:docs:3.10 and its blog
and pages counterparts. They encode the front matter contract of Docusaurus 3.10
and require nothing, so switching one on cannot fail a page that was already
building — it only catches a sidebar_position: "2" that your site would have
rejected later. They claim none of the type or action keys below, so they
stack with any of the vocabularies. They do share tags with OKF, which allows
only strings where Docusaurus also allows tag objects — see the overlap
note before pairing
those two.
If what you need is a closed list of document types, three of the built-ins
are vocabularies: diataxis:diataxis:1.0 requires type
and constrains it to the four Diátaxis forms,
tgdp:templates:1.0 requires type and constrains it to the 25 template slugs
of The Good Docs Project, and
passo-uno:seven-action:1.0 constrains action to the seven reader actions of
the Seven-Action model. The first two
both claim type, so they are alternatives; either one pairs with the third.
The two type vocabularies each demand the key as well as constraining it, so
neither needs a partner for presence-checking — stack one with OKF for the
other OKF fields. Both schemas apply in full, in either order:
docmeta validate docs/ -s diataxis:diataxis:1.0 -s google:okf:0.1Seven-Action is the exception: it rules that an action, if present, is
legitimate, without insisting on one. That is what makes it safe to layer onto
what you already have. Every value of all three, which combinations compose, and
the crosswalk from Seven-Action to Diátaxis are in the taxonomy schemas
reference.
Point a document at its schema
Section titled “Point a document at its schema”A schema only matters once documents are validated against it. The most direct way to connect the two is to let a document name its own schema with a $schema key in its frontmatter. docmeta reads that key and validates the file against whatever it points to.
Here is a document naming the built-in OKF schema, the schema-ref.md fixture:
---$schema: google:okf:0.1type: guidetitle: Self-Describing Document---
# Self-Describing Document
This file names its own schema via `$schema`.The $schema value can be a built-in id (as here), a path to a .json file you wrote, or a URL. To point at a local schema file instead:
---$schema: ./schemas/metadata.schema.jsontype: guidetitle: My page----
Write your schema as a
.jsonfile using the patterns above, keeping the"$schema"dialect line at the top. -
Add
$schema:to a document’s frontmatter, pointing at your file (or a built-in id, or a URL). -
Validate it:
Terminal window npx docmeta validate path/to/document.mddocmeta resolves the document’s
$schema, validates the frontmatter, and reports any missing or malformed fields.