Skip to content
HomePagesHomePages template kit

TemplateManifest

Zod schema for the object a template's `template.ts` builds via `defineTemplate`: a discriminated union on `output`, the artifact class.

Zod schema for the object a template’s template.ts builds via defineTemplate: a discriminated union on output, the artifact class. Validates a BUILT object, not parsed JSON, and owns a template’s static composition only: identity (key, a name of at most two words, output), its formats acceptance set (websites hold exactly the geometry-less website singleton; image and document templates one or more of their own class’s formats), its ordered pages (each page’s label, optionality, ordered section instances, and — websites only — path), its canvases (the editing-surface grouping, always explicit on the wire), and optional intake preview chrome. Cross-section reconcile rules are not part of this schema — they compile into the template logic bundle instead.

Pages are the composition unit in every class: a single-page template is a one-page template, declared exactly as a five-page one is. There is no flat sections shape.

Import from @homepages/template-kit.

const TemplateManifest: z.ZodDiscriminatedUnion<[z.ZodObject<{ key: z.ZodString; name: z.ZodString; output: z.ZodLiteral<"website">; formats: z.ZodTuple<[z.ZodObject<{ id: z.ZodString; label: z.ZodString; category: z.ZodEnum<{ website: "website"; "social-post": "social-post"; story: "story"; brochure: "brochure"; flyer: "flyer"; postcard: "postcard"; presentation: "presentation"; }>; }, z.core.$strict>], null>; pages: z.ZodArray<z.ZodObject<{ id: z.ZodString; label: z.ZodString; path: z.ZodString; optional: z.ZodDefault<z.ZodBoolean>; sections: z.ZodArray<z.ZodObject<{ section: z.ZodString; instance_id: z.ZodString; required: z.ZodDefault<z.ZodBoolean>; }, z.core.$strict>>; }, z.core.$strict>>; canvases: z.ZodArray<z.ZodObject<{ id: z.ZodString; label: z.ZodString; pages: z.ZodArray<z.ZodString>; }, z.core.$strict>>; preview: z.ZodOptional<z.ZodObject<{ blurb: z.ZodString; intents: z.ZodArray<z.ZodEnum<{ for_sale: "for_sale"; for_rent: "for_rent"; }>>; types: z.ZodArray<z.ZodEnum<{ single_family: "single_family"; condo_townhome: "condo_townhome"; multi_family: "multi_family"; investment: "investment"; }>>; demoUrl: z.ZodOptional<z.ZodNullable<z.ZodString>>; }, z.core.$strict>>; }, z.core.$strict>, z.ZodObject<{ key: z.ZodString; name: z.ZodString; output: z.ZodLiteral<"image">; formats: z.ZodArray<z.ZodObject<{ width: z.ZodNumber; height: z.ZodNumber; id: z.ZodString; label: z.ZodString; category: z.ZodEnum<{ website: "website"; "social-post": "social-post"; story: "story"; brochure: "brochure"; flyer: "flyer"; postcard: "postcard"; presentation: "presentation"; }>; preset: z.ZodOptional<z.ZodString>; }, z.core.$strict>>; pages: z.ZodArray<z.ZodObject<{ id: z.ZodString; label: z.ZodString; optional: z.ZodDefault<z.ZodBoolean>; sections: z.ZodArray<z.ZodObject<{ section: z.ZodString; instance_id: z.ZodString; required: z.ZodDefault<z.ZodBoolean>; }, z.core.$strict>>; }, z.core.$strict>>; canvases: z.ZodArray<z.ZodObject<{ id: z.ZodString; label: z.ZodString; pages: z.ZodArray<z.ZodString>; }, z.core.$strict>>; preview: z.ZodOptional<z.ZodObject<{ blurb: z.ZodString; intents: z.ZodArray<z.ZodEnum<{ for_sale: "for_sale"; for_rent: "for_rent"; }>>; types: z.ZodArray<z.ZodEnum<{ single_family: "single_family"; condo_townhome: "condo_townhome"; multi_family: "multi_family"; investment: "investment"; }>>; demoUrl: z.ZodOptional<z.ZodNullable<z.ZodString>>; }, z.core.$strict>>; }, z.core.$strict>, z.ZodObject<{ key: z.ZodString; name: z.ZodString; output: z.ZodLiteral<"document">; formats: z.ZodArray<z.ZodUnion<readonly [z.ZodObject<{ width: z.ZodNumber; height: z.ZodNumber; id: z.ZodString; label: z.ZodString; category: z.ZodEnum<{ website: "website"; "social-post": "social-post"; story: "story"; brochure: "brochure"; flyer: "flyer"; postcard: "postcard"; presentation: "presentation"; }>; preset: z.ZodOptional<z.ZodString>; }, z.core.$strict>, z.ZodObject<{ width: z.ZodString; height: z.ZodString; dpi: z.ZodNumber; bleed: z.ZodOptional<z.ZodString>; id: z.ZodString; label: z.ZodString; category: z.ZodEnum<{ website: "website"; "social-post": "social-post"; story: "story"; brochure: "brochure"; flyer: "flyer"; postcard: "postcard"; presentation: "presentation"; }>; preset: z.ZodOptional<z.ZodString>; }, z.core.$strict>]>>; pages: z.ZodArray<z.ZodObject<{ id: z.ZodString; label: z.ZodString; optional: z.ZodDefault<z.ZodBoolean>; sections: z.ZodArray<z.ZodObject<{ section: z.ZodString; instance_id: z.ZodString; required: z.ZodDefault<z.ZodBoolean>; }, z.core.$strict>>; }, z.core.$strict>>; canvases: z.ZodArray<z.ZodObject<{ id: z.ZodString; label: z.ZodString; pages: z.ZodArray<z.ZodString>; }, z.core.$strict>>; preview: z.ZodOptional<z.ZodObject<{ blurb: z.ZodString; intents: z.ZodArray<z.ZodEnum<{ for_sale: "for_sale"; for_rent: "for_rent"; }>>; types: z.ZodArray<z.ZodEnum<{ single_family: "single_family"; condo_townhome: "condo_townhome"; multi_family: "multi_family"; investment: "investment"; }>>; demoUrl: z.ZodOptional<z.ZodNullable<z.ZodString>>; }, z.core.$strict>>; }, z.core.$strict>], "output">
  • on parse when a composition rule is violated, each with an error naming the rule — a name of more than two words, duplicate page id, duplicate format id, one instance_id listed twice on the same page (listing an instance on SEVERAL pages is legal and means one shared instance rendered on each), a rendered template with no format or with every page optional, a preset-tagged format whose geometry does not match the library entry for that tag, a website format set that is not exactly [presets.website], a canvas rule — no canvases, a duplicate canvas id, an empty canvas, a canvas naming an unknown page, a page on no canvas or on two (canvases must partition the pages) — or a website page rule — duplicate path, no root page or more than one, an optional root page, a non-root path that is not a single lowercase-kebab segment. Format geometry bounds (positive dimensions, the 72–600 dpi window, bleed ≥ 0, no mixed physical/pixel dimensions) are enforced by the format schemas themselves.