Skip to Content
DocumentationFeaturesPlatformPage types & schemas

Page types & schemas

Every page in the mesh has a page type — a typed contract that says both how to write it and what shape it must take. A page type is always a pair: a template and a schema.

What it is

Each entry under page_types in gtmesh.config.yaml names a template and a schema:

  • The template (templates/<type>.md) is the prose theory — the editorial guidance the article-writer follows when filling the body.
  • The schema (schemas/<type>.schema.yaml) is the structure — a JSON Schema that apply scaffolds an empty skeleton from, and that validate/seal enforce with ajv. The SSG renders against the same contract.

Two schema systems, never conflated: zod validates the registry; JSON Schema / ajv validates page YAML structure. Page types live entirely in the second world.

Why it matters

Typed contracts are what keep programmatic content consistent at scale. The schema guarantees a review page always carries a rubric and a verdict block, a comparison always carries its entity pair, and so on — so a thousand generated pages share one shape the SSG can render and AI answer engines can parse. The template guarantees they share one voice. Because the schema is checked at seal, a page that doesn’t conform simply cannot ship.

How it works

Selection is deterministic. Each page type carries a when predicate (a section, and/or a role, and/or the page’s resolved entity_kind) and plan picks the type whose predicate matches — first match wins, so specific rules sit above catch-alls. A kind: commercial_* project selects the money-layer types (product, tool, directory, trust); a content site selects entity-hub, educational, guide, and friends.

Typing hubs by entity class. A demand-minted hub (entity-aware classification) carries no section, so when: { role: hub } would collapse every hub onto one type. Add when: { entity_kind: … } (the entity node’s class label) to give each its own type — manufacturer-hub, industry-hub — placed above the generic entity-hub catch-all. Beyond the template/schema, this aligns the minted hub’s identity with a hand-authored typed seed of the same class, so the demand folds into the seed rather than minting a duplicate page. See Tuning §5 for the full recipe and Folding demand into a hub for why the alignment matters.

The key is entity_kind, not class. page_types.when isn’t validated for unknown keys, so when: { class: … } is silently ignored — the hub falls through to the generic entity-hub, its type no longer matches the typed seed, and you get a stray page with no error. If a typed hub won’t fold, check this first.

Catalog types. A page type can carry catalog: true to declare that it embodies an entity — a product, a category/manufacturer hub. Only catalog types emit the HAS_<axis> domain edges that file a page into the money layer; content types (guide, educational, comparison, …) merely mention entities, so they stay uncatalogued and emit only the topical MEMBER_OF membership that routes them up. The flag is opt-in and additive — see the HAS_<axis> gate for why it matters. The scaffold ships catalog: true on product and entity-hub.

Every page validates as the {type, meta, content} envelope (additionalProperties: false, with type as a const discriminator). meta is the render projection — slug is apply-owned, the editorial fields (metaTitle/title/navTitle/metaDescription) are writer-authored. content is the typed body.

A type can also carry schema variantsschema_variants plus variant_when lets one type resolve to a different schema by context. The scaffold’s educational type, for example, renders thin when a sibling hub exists in the same product cluster and full otherwise; plan resolves which one applies.

Key files & flags

ThingWhat it is
gtmesh.config.yaml page_typesThe list of types: each idtemplate + schema + when
page_types[].catalogtrue marks a type that embodies an entity → emits HAS_<axis> domain edges
templates/<type>.mdProse theory for the writer
schemas/<type>.schema.yamlThe structural contract (JSON Schema)
schemas/common.schema.yamlShared types, merged then locally $ref-ed
schema_variants / variant_whenResolve one type to a variant schema by context
gtmesh page validate <slug>Check a page against its schema (ajv) + editorial lints
Last updated on