template-invalid
"A template's template.ts is missing, unloadable, or violates the composition contract."
Venue: check — A template’s template.ts is missing, unloadable, or violates the composition contract.
A template folder (templates/<key>/) must have a template.ts at its root, and that
file must:
- exist — a template folder with none at all reports this once, naming the missing file;
- load, and default-export a
defineTemplate({ … })result — the file is compiled and evaluated, so a syntax error, an unresolvable import, or a missing default export all report here; - declare a composition —
key,name,output,scope, andpages, built bycomposePagesoverpage()entries whose sections come fromcomposeSections; object key order is page order; - name itself in at most two words — the display name goes on one truncating line
in the picker card, the editor chrome and the dashboard, so
"Classic Carousel"passes and"Classic Listing Carousel"is refused; the description belongs to thepreviewblurb; - declare a valid site map — page ids and paths unique, every page labelled and
carrying at least one section, exactly one page at
"/"(never optional), and every other path one lowercase-kebab segment; - declare a valid canvas grouping, when it declares one — explicit
canvases(built bycomposeCanvasesovercanvas()entries) must partition the pages: every page on exactly one canvas, no canvas empty, canvas ids unique, every canvas labelled; omitcanvasesfor the class default; - agree with its own folder — the declared
keymust match the template folder name it lives in; - reference real sections — every composed entry must resolve to a section this workspace actually has;
- satisfy the whole-composition nav contract — the cross-section rules that need the full, resolved section set rather than any one section in isolation.
Every violation collects into the same run; a composition with several wrong references reports all of them together.
Reason
Section titled “Reason”A section’s own declarations describe that section in isolation — they say nothing about
which page it appears on, or in what order. template.ts is where that composition is
declared: the whole site map in one file, and the only place a downstream consumer (the
publisher, the fill pipeline, the editor) can go to learn a template’s actual shape.
Most of that contract is enforced by the compiler: composeSections resolves every entry
against the section’s real schema, so a renamed section stops compiling in your editor
instead of failing a run later. This rule is the rest of it — what needs the whole
composition at once.
Read the message: it names the template, the section instance, and what’s wrong. Missing entirely, add one. Otherwise, fix the field the message points at.
Before
Section titled “Before”templates/acme-modern/ template.ts sections/ hero/import { composePages, composeSections, defineTemplate, page, presets } from "@homepages/template-kit";
import { schema as heroSchema } from "./sections/hero/schema";
export const sections = composeSections({ hero: { schema: heroSchema, instanceId: "hero-1", required: true },});
export default defineTemplate({ key: "acme-classic", name: "Acme Classic", output: "website", formats: [presets.website], scope: "global", pages: composePages({ home: page("Home", "/", [sections.hero]) }), reconcile: [],});Template "acme-modern": declared key "acme-classic" does not match the template folder name "acme-modern".import { composePages, composeSections, defineTemplate, page, presets } from "@homepages/template-kit";
export const sections = composeSections({ hero: { schema: heroSchema, instanceId: "hero-1", required: true },});
export default defineTemplate({ key: "acme-modern", name: "Acme Modern", output: "website", formats: [presets.website], scope: "global", pages: composePages({ home: page("Home", "/", [sections.hero]) }), reconcile: [],});See also
Section titled “See also”- The schema system — what a template declares and the shape it is validated against.
schema-invalid— the same kind of cross-reference check, one level down, on a single section’s own contract files.no-templates— reported instead when the workspace has notemplates/<key>/folder to check at all.