---
name: platform-make-template
description: "Author a NET-NEW template — a multi-screen UI flow (screen-set) for a platform blueprint. ALWAYS starts with a scan-gate: survey prior-app screens first; a template is adopted from a convergent prior-app screen-shape, never reinvented. A template is copied + host-owned (or shipped inside its plugin) — NEVER a published 'template package' (delivery-stack §3 forbids it). Module-bound templates (auth/billing/checkout flows) are BLOCKED until the backing module's @platform-modules/<core>-react sibling ships; generic content templates (landing/docs/blog/contributors) need no backing module and build now. Use on /platform-make-template or when asked to build a screen-flow/template. Holds no code rules of its own — points to delivery-stack, coding-standard §6, and mod-ui-enforcement."
---

# Make Template — Net-New Screen-Flow Authoring (scan-gated)

**Audience: AI coding agents first.** Optimize for activation, not prose — keep ladders as ladders.

A **template** = a **multi-screen flow** (screen-set) assembled from the `@platform-modules/ui-*` kit + (for module-bound flows) one module's `-react` sibling. This skill authors ONE template. Its value = a **scan-gate** that routes you to *adopt* a prior-app screen-shape instead of reinventing it, plus the **binding gate** that stops you building a template whose backing `-react` sibling does not yet ship.

> Holds **no code rules of its own.** Vocabulary + maturity gates → `docs/specs/2026-06-16-delivery-stack.md` (§2 defs, §3.1 the `-react` binding gate, §3 the never-a-package rule). Screen authoring + token discipline → `docs/standards/coding-standard.md §6` (`-react` overlay) + `docs/specs/mod-ui-enforcement/` (5 AST rules, token-only props). Catalogue shape → `docs/registry.json → templates`. Classification → `docs/specs/2026-06-17-plugins-templates-blueprints-design.md §2/§9`. This file is *process*, not doctrine.

## Step 0 — SCAN-GATE (BLOCKING — before anything else)

Before designing or writing one screen, prove the flow's shape against prior-app screens. Reinventing a screen prior apps already converged on = the same waste `/platform-make-modules` guards against, at screen grain.

1. Name the flow as a concrete screen-set (e.g. "auth = sign-in · sign-up · reset · verify · 2FA · social-callback"; "subscription-tiers = 7 screens").
2. **Survey prior-app screens — check any existing screen catalogue FIRST, do not re-explore.** If a screen/flow survey has been persisted under `docs/catalog/`, check its freshness (`CLAUDE.md §6` explore-once rule) — fresh pin → use it; stale → re-survey ONLY the changed source (read-only `Explore` haiku). If the flow is **absent** from any catalogue, run a fresh screen-grain survey via `cursor` (NOT a capability survey — read prior-app *call-sites/screens*, per `platform-orchestrator` dispatch policy).
3. **Decide on convergence — `convergence > count` (`CLAUDE.md §3`):**
   - **Prior apps converge on ONE reusable screen-shape →** adopt it (Step 4). The best-match source named in the survey is the one to lift from.
   - **Prior apps only *look* alike (lookalike, not same shape) →** NOT a template yet. Record WATCH; STOP.
   - **Zero/one prior app, no convergence →** a one-screen-shape invention is not a template (same bar as a one-consumer module). STOP unless forward-need is real and the shape is fixed (`CLAUDE.md §3` forward-need rule).

"Not a template yet — recorded WATCH" = the gate **succeeding**.

## Step 1 — Which template kind? (sets the binding gate)

Two kinds, different gates. Classify before proceeding:

- **Generic content template** (landing · docs · blog · contributors · marketing) — static-render, **no backing module on the critical path** (MD/MDX → HTML at build; React only inside opt-in islands). **Buildable now.** Consumes `ui-tokens` + `seo` + optionally `i18n-react`/`ui-primitives` (islands only).
- **Module-bound template** (auth · account · checkout · moderation · notifications flow) — a screen over one module's behaviour. **BLOCKED by the `-react` binding gate (Step 2).**

## Step 2 — Binding gate for module-bound templates (BLOCKING)

**Rule (delivery-stack §3.1): a module-bound template MUST NOT be built until its backing module has a shipped `@platform-modules/<core>-react` sibling.** §3 routes headless **behaviour** → the `-react` sibling; styled **composite** → the template. No sibling → the behaviour binding does not exist → the template is not buildable on-model.

1. Identify the backing module + confirm `status: shipped` in `registry.json → modules`.
2. Confirm a `@platform-modules/<core>-react` sibling **ships**. Today only `i18n-react` + `realtime-react` exist (verify — query the registry, do not trust this line).
3. **No sibling → STOP.** This is `-react`-sibling backlog, not template backlog. Route the work to the `-react` sibling build queue; do not hand-wire a sibling-less screen and catalogue it as a template (delivery-stack §3.1 escape-hatch note: physically possible, off-model, uncatalogued).

Generic content templates skip this step (no backing module).

## Step 3 — Classify delivery + ownership (never a package)

- **Classify by the PAIR `(granularity, delivery)`, never by size** (`plugins-templates-blueprints-design.md §9`). A template is **flow-grain**; delivery ∈ {scaffold (generic, host-owned copy) · plugin-owned (shipped inside its plugin)}.
- **NEVER build a "template package" imported via semver.** delivery-stack §3: a template is **copied, not imported** — once placed it is host-owned code. A "template module" re-creates the heavy-UI-gravity trap (accretes app policy, stops being swappable). The reusable code a template consumes IS packaged (`ui-tokens`/`ui-primitives`/`seo`/`<core>-react`); the template skeleton is the thin host-owned glue composing them.

## Step 4 — Author (adopt prior-app screen → de-name → host-owned scaffold)

- **Lift the convergent prior-app screen** named in the survey; **de-name it** — strip every source-app reference, domain entity, and source-app-specific policy (R5 host-vs-generic split, `CLAUDE.md §3`). What stays generic = the flow structure + token-styled primitives; what is host-domain = ejected to the host.
- **Token + a11y discipline is BLOCKING.** `coding-standard.md §6` (`-react` overlay) + `mod-ui-enforcement`: token-only props (no `style`/`className` escape on primitives), Radix a11y floor, RTL-ready. The 5 AST rules (`mod-ui-no-inline-style`, `-no-raw-interactive`, `-no-classname-on-primitive`, `-no-token-cast`, `-no-arbitrary-value`) are the contract — author so they pass.
- **i18n-ready:** all rendered copy routed through the `i18n` lookup, never inline string literals (`mod-www` design §3 i18n one-way-doors).
- **Public-language law (hard):** nothing the screen renders carries internal vocab (sourcing/seam/layer codes) or source-app names.

## Step 5 — Catalogue + harness

- **Catalogue in `registry.json → templates`**: `owningPlugins: []` for a generic host-copied template, or the owning plugin name; delivery = `copied`.
- **Harness** = the consuming app's build + (for UI) Playwright/axe per `docs/specs/2026-06-13-consumer-harness.md` and the harness-vehicle rule (`memory: harness-vehicle-by-surface` — UI templates → `apps/consumer` Astro+Playwright, never the `_astro` scan for server code). Not "done" until the harness visibly reddens on a broken screen.

## Build execution

A generic content template is often thin host glue → may build **in-loop**. A multi-screen adoption with real de-naming work → `cursor` in a worktree (`CLAUDE.md §4`; dispatch policy in `platform-orchestrator`). Judgment (convergence verdict, host-vs-generic split, gate pass/fail) is the main loop's alone — never delegated.
