template.yaml manifest plus supporting prose (TEMPLATE.md, composition.md, hooks.md, prompt-cookbook.md). Public templates are served from the hosted content library (Supabase); your own author into workspace/templates/<slug>/ (user-local). The old repo-public templates/<category>/<slug>/ folder was retired in #084. This page is the wire-format spec: the manifest Zod schema, the two kinds, the segment categories, the slug discipline, and the version gate.
Full example
A minimalvibe-style template at workspace/templates/brand-story/template.yaml:
vibe-reference template adds a composition.md walkthrough plus a reference/ folder of worked artifacts alongside the manifest. Both kinds use the same schema.
File layout
workspace/templates/ is flat (no category subdir). When a slug exists in both, workspace overrides repo — per AGENTS invariant #10.
Zod schema
cli/lib/schemas/template.ts exports TemplateYamlSchema. Field-by-field:
| Field | Type | Default | Validation |
|---|---|---|---|
version | 1 (literal) | — | required; loader rejects unknown values with E_TEMPLATE_VERSION_UNSUPPORTED |
id | string | — | required; kebab-case; passes validateSlug() |
aliases | string[] | [] | old slugs the template shipped as; kept ≥ one major-release cycle |
kind | "vibe-reference" or "vibe-style" | — | required |
category | enum (5 values) | — | required; see table below |
name | string | — | required; min length 1 |
description | string | — | required; min length 1 |
tags | string[] | [] | free-form discovery tags |
requires | TemplateRequires | {} | declares brand / persona / ref dependencies |
scenes | SceneTemplate[] | [] | optional scene scaffolding |
estimated_cost_usd | number | — | optional; non-negative |
estimated_duration_s | number | — | optional; positive |
references | string[] | [] | asset slugs or paths the template uses |
category — the five segment-persona folders
templates/. The lint walks only these five.
kind — vibe-reference vs vibe-style
| Kind | What ships | Use it when |
|---|---|---|
vibe-reference | Manifest + composition.md walkthrough + reference/ worked artifacts | The template encodes a full production: scene scaffolding, named refs, ready-to-render prompts. |
vibe-style | Manifest + hooks.md + prompt-cookbook.md (prose only) | The template encodes a cookbook — hooks, camera vocab, worked example prompts — without a fixed scene list. |
vibe-reference templates ship in repo; 38 vibe-style. Both kinds are loadable by ralphy template use <slug>.
requires
diagnoseRequiredInputs() checks the user’s project inputs against this block and returns the first missing requirement. Callers map the result to E_TEMPLATE_INPUT_MISSING. The refs field is a single count for v1.0; the 3-slot {cref, sref, pref} shape lands post-launch (decision D-02).
scenes — optional scaffolding
vibe-reference templates fill this in. vibe-style templates leave it as [].
A worked vibe-reference scenes block:
Scenario conforming to cli/lib/schemas/scene.ts → ScenarioSchema. The full scene shape (with vo_text, camera, lighting, gesture, broll, refs, notes) is the scenarist’s output contract, not the template’s input. See Memory schemas and the scenarist playbook for the downstream shape.
Gesture vocabulary
When the template’sdirection field hints at a body-language beat, the scenarist may attach a gesture to the resulting scene. The vocabulary is the finite enum in cli/lib/schemas/gestures.ts:
Scene.notes (the free-text escape hatch), never in direction. The enum is closed by design (decision D-06) — adapters silently omit unknown values rather than throw, so a forward-compatible PR that adds a new gesture degrades gracefully on older binaries.
Slug discipline
Slugs are kebab-case. The regex:Banned tokens
DENIED_SLUG_TOKENS in cli/lib/schemas/template.ts blocks real-creator and brand tokens from appearing in slugs. The match is whole-token (delimited by start, end, or hyphen) so arogant-pov is fine but joe-rogan-pod is not.
Currently denied:
TEMPLATE.md / composition.md — never in the slug. The rule is decision D-05: archetypal slugs only.
validateSlug(slug) returns {ok: true} or {ok: false, reason, token?}. Callers build E_TEMPLATE_SLUG_INVALID from the rejection payload.
Version gating
template.yaml must declare version: 1. The loader in cli/lib/templater/loader.ts → parseTemplateManifest() reads the version field first; if it is not in SUPPORTED_VERSIONS = [1], the loader calls raiseError("E_TEMPLATE_VERSION_UNSUPPORTED", {version, id}) and exits.
scenes[] eventually gains a required field, the loader keeps a v1 reader alive for at least one major-release cycle (decision D-03). Authors bump version: 2 only when the schema breaks compatibly.
Manifest discovery
locateTemplateManifest(dir) prefers template.yaml, then falls back to template.json for not-yet-migrated templates (02.05.04 migration window). Both shapes parse through the same Zod schema. New templates should land as .yaml only.
Slug resolution
ralphy template use <slug> resolves a slug across both tiers:
- Search
workspace/templates/<slug>/template.yaml. - If not found, look the slug up in the public content library (Supabase).
- If still not found, search aliases (
aliases: [old-slug]).
Validation
The manifest parses through the v1 Zod loader (cli/lib/templater/loader.ts) on every ralphy template show / use. It enforces:
- The category is one of
TEMPLATE_CATEGORIES. - The slug passes
validateSlug()— kebab-case, no banned tokens. template.yaml(or legacytemplate.json) is present and parses without throwing.
lint:templates script was retired with the templates/ folder in #084 — there is no longer a committed repo catalog to walk.)
Authoring checklist
- Pick a category. One of
b2b-saas,dtc-commerce,creator-lifestyle,entertainment-viral,cinematic-narrative. - Pick a slug. Kebab-case, no creator names.
- Decide the kind.
vibe-referenceif you’re shipping a full production with refs;vibe-styleif you’re shipping a prompt cookbook. - Write
template.yamlatworkspace/templates/<slug>/. Start withversion: 1, fill required fields, default the rest. - Write
TEMPLATE.md. Human-readable overview. Creator references go here, not in the slug. - For
vibe-reference: addcomposition.md(the narrated walkthrough) andreference/(worked artifacts). - For
vibe-style: addhooks.md(hook library) andprompt-cookbook.md(per-modality fragments). - Run
ralphy template register <slug>thenralphy template suggest "<your test brief>". Verify the new template surfaces with a sensible score. - To publish to the public Library, use the
templater/dev-publish-templatepath.
Related
- CLI:
ralphy template—list,suggest,use,show. - Library — every published template, browsable.
- Concepts: templates — what a template is, narrated.
cli/lib/schemas/template.ts— the Zod source.cli/lib/templater/loader.ts— the loader / validator.