Skip to content

The template kit

@port60/template-kit is the local half of the platform: the same contract, dialect, validator and preview renderer the engine runs in production, packaged as a CLI. If it validates on your machine, it validates at upload, the two cannot drift.

Terminal window
p60-template-kit create <dir>

A working template from the platform starter: renders immediately, validates clean, and comes briefed for AI agents (AGENTS.md/CLAUDE.md) with npm scripts wired. The folder name becomes the template name and the label derives from it; --name/--label override the identity when it should differ from the folder.

Terminal window
p60-template-kit dev [dir] [--port 4400]

Live preview over the contract’s kind fixtures with realistic, non-interactive island skeletons for worship rails, events, donation widgets and other platform features. The skeletons use each island’s stable styling API, so theme CSS can be judged without a platform account. Files are re-read per request, so refresh is the reload; validation re-runs in the terminal on save.

What the preview is, precisely, so nothing surprises you at upload:

  • Two compositions, as the platform composes them. When your manifest declares compositions, / and /about render your composition for that page, in your order, with the optional entries left out, against the catalogue’s sample content. Without one, / renders the sections you declare that the catalogue assigns to the home page and /about the ones it assigns to about, each in manifest order. A template that does not declare about in supports.pages sees the platform’s own About body there, as it would live. Your own compositions and copy come from the pages block of preview-content.json (below).
  • Routed platform surfaces. The bar at the top links to /about, /events, /services, /donate, /articles, /campaigns and /courses, each wearing your chrome and, where you ship one, your page template.
  • What leads is switchable. The bar’s Leads with links (or ?focus=donate|volunteer|none on any URL) set the site focus: the primary_action_widget island in your hero becomes the donation widget, the volunteer sign-up, or nothing, and site.focus, site.actions, the header button and the hero’s section.action follow. The studio renders the default, giving.
  • Behaviours run. The platform’s behaviour runtime is inlined, so reveals, carousels, accordions, tabs, and menus built on the nav behaviour work as in production. Only the older chrome hooks (data-nav-burger, data-nav-drop) stay inert in the preview; they work on a live site and on a development version of your own site.
  • Knobs and Looks switch. Knobs render at their defaults; the bar’s Looks links (or ?look=Name on any URL) apply one of your manifest.looks, and ?p60s-<key>=<value> sets a single knob, exactly as Appearance does for a charity. Values are checked the way production checks them: a select value outside the knob’s options and an unknown font family fall back to the default.
  • Webfonts load. The dev preview loads your manifest.fonts and your font knobs’ families from the platform’s provider mirror, so type is judged for real. The studio review render stays network-dead and shows the fallback stacks.
  • Icons resolve. item.iconSvg is supplied for a Lucide icon name, as live; render item.icon as the fallback for anything else.

Photographic fixtures: set P60_FIXTURE_IMAGES=https://your-image-host before dev and the built-in fixture image references load <kind>-<seed>.jpg from that one origin instead of the sealed inline art; the preview admits exactly that host. Your own photographs go in a preview/ folder beside the template: the dev server serves them at /preview/<file> (images only), so a preview-content.json can point imageUrl values at /preview/hero.jpg. Unset and without the folder, the preview stays fully network-dead. Images you place next to the template are never packaged, see what the zip contains.

Terminal window
p60-template-kit validate [dir] [--json]

The conformance checks the platform runs at upload, manifest schema, dialect, fixture renders, island discipline, the two-way supports honesty, render budgets. --json emits {ok, errors, warnings, manifest, provenSupports}: supports as an output, a clean pass is what turns your declarations into proven capability, and it’s the feedback loop AI agents iterate against.

Terminal window
p60-template-kit package [dir]

Validates, then produces dist/<name>-<version>.zip containing exactly the contract-shaped file set, the artifact your studio’s upload accepts as-is. dist/ is wiped and recreated on every run and is gitignored by the scaffold.

Terminal window
p60-template-kit model [--json]

The content model in hand: every site.content.* collection with its bound, onward link and fields. --json emits the registry verbatim for agents. The dev server renders the same reference with live example data at /model.

Terminal window
p60-template-kit content [dir] [--out file]
p60-template-kit dev [dir] --content my-org.json

Bring your own content and imagery. content EJECTS every collection plus the brand, the menu (nav) and the home and about compositions (pages, each declared section with its sample copy), fully populated with the canonical organisation, as one editable JSON file; edit the copy in place, reorder or drop sections, swap imageUrl values for your own hosted images or a preview/ folder, and dev --content renders your data on every surface; the preview admits exactly the image hosts your file names and nothing else. The shape stays the platform’s (schema-checked on every read: a section type must be in the catalogue and its fields must be ones the section declares), the data becomes yours; the file is hot-reloaded, never packaged, and refused at upload.

Terminal window
p60-template-kit login
p60-template-kit whoami
p60-template-kit logout

Sign in from the terminal. login runs the Keycloak device flow (the browser approves), stores an offline token in ~/.port60, and discovers your studio workspace automatically; whoami shows who is signed in and which workspace; logout signs this machine out and revokes its token. By default the kit talks to Port60’s hosted stack; set P60_AUTH_BASE / P60_API_BASE / P60_REALM / P60_CLIENT_ID to point it at a local or self-hosted environment.

Terminal window
p60-template-kit publish [dir] [--no-submit]

Validate, package, upload to your studio and submit the version for review, in one command. The dashboard upload in Publishing still works, this is the same result from the terminal (--no-submit uploads without submitting).

Terminal window
p60-template-kit publish [dir] --ci

The same from a GitHub Actions workflow: no login, the run’s own OIDC token is the credential, and the repository must be trusted in Studio (once, for the whole studio). See Publish from GitHub Actions for the workflow.

Terminal window
npx @port60/template-kit@latest upgrade

Your scaffold pins the kit as a devDependency and every npm script runs that local copy, so the whole enforcement surface, contract, content model, validator, fixtures, preview, behaviour runtime, upgrades with one install. upgrade does it properly: it installs the latest kit into your pin, regenerates AGENTS.md/CLAUDE.md (they are the kit’s generated briefing, stale the moment the contract moves, your own notes belong in README.md), prints the kit, contract and content-model versions now in force, and re-runs the full conformance check so you immediately see what, if anything, the newer contract asks of your template.

Your template sources are never touched, and the contract is add-only within a major, an upgrade can inform you, it cannot break you. New collections, fields and behaviours simply become available; anything the validator newly asks for appears in the report, not in production. See Versioning for why published versions stay safe regardless.

  1. Upload the zip in your studio (tenant admin → Studio → your template → Versions), the platform re-runs validation and stores the artifact in quarantine.
  2. Submit the validated version for review.
  3. A Port60 reviewer approves; the artifact is promoted to the live catalogue, privately delivered to your commissioning charity or listed on the marketplace at your price.

Versions are immutable once reviewed; ship fixes as a new semver. The name in your manifest is your claimed identity, it must match the template you created in the studio.