Anatomy of an artifact
A template artifact is a directory published to object storage under {name}/{version}/. Once
published, that prefix is immutable; the platform caches artifacts aggressively (in-memory and
at the CDN) precisely because a version can never change underneath anyone.
{name}/{version}/├── manifest.json # REQUIRED: identity, format, what you support├── layout.liquid # OPTIONAL: the page chrome, when supports.layout is true├── sections/ # REQUIRED: one {type}.liquid per supported section type│ └── *.liquid├── pages/ # OPTIONAL: display bodies for pages in supports.pageTemplates│ └── *.liquid└── assets/ └── theme.css # REQUIRED: the template's entire lookmanifest.json
Section titled “manifest.json”The manifest declares what your template is and what it supports. It’s validated against a JSON Schema at publish time; the important fields:
| Field | What it means |
|---|---|
name |
Permanent identity. Lowercase, hyphenated, stable across every version. |
version |
Semver. Immutable once published, a fix is a new version. |
format |
The contract major you’re written against, currently port60-liquid@1. |
supports.pages |
Section based page bodies you render: currently home and about. |
supports.sections |
Which section types you ship renderers for. |
supports.islands |
Every island your renderers place. |
supports.layout |
True when you ship layout.liquid and own the chrome, see Layouts. |
supports.pageTemplates |
Route specific data views you render. Listings are events and articles; details are course and article. See Page templates. |
compositions |
Your preferred composition per page: the ordered section types the design is built around, each with a role. core carries the design (an organisation removing one is warned, never stopped), recommended is on by default, optional is offered. A page an organisation never edited renders this composition, the kit preview renders it, and the Pages editor offers it as the order to reset to. Every type must be in supports.sections and belong to that page. |
requiresCapabilities |
Capabilities the design needs to work as intended. This is checked against the artifact and used for catalogue matching. It never grants an entitlement. |
suitsProfiles |
Organisation profiles the design was composed for. This improves recommendations but never hides or unlocks a feature. |
fonts |
Webfont stylesheet URLs the platform loads in <head>. |
settings.schema |
Your own theming knobs (colour schemes etc.), see Theming. |
Two support rules matter:
- Sections you don’t support are omitted, never an error. If a charity authors a section your template has no renderer for, that section silently doesn’t render. Support the catalogue broadly, but you’ll never crash for missing one.
- Every island you place must be declared in
supports.islands; the validator enforces placed ⊆ declared ⊆ platform registry. - Every required capability needs a visible surface. The validator rejects a capability claim that has no matching section, page template, island or context declaration in the artifact.
sections/*.liquid
Section titled “sections/*.liquid”One file per supported section type, named exactly after it (hero.liquid renders hero
sections). Each is a self-contained fragment written in the
Port60 dialect, there is no include mechanism and no partials in contract
v1, and sections never contain chrome (that’s the layout’s job).
Each renderer receives the render context: the section object (typed per
the section catalogue) and brand.
Renderers must survive the minimal fixture of every type they support, the least content a
charity can author. The validator renders both fixtures; if your hero falls over when eyebrow
is absent, you don’t publish.
assets/theme.css
Section titled “assets/theme.css”Your whole look, one file. It layers on top of the platform base stylesheet, which owns mechanics (layout plumbing, form controls, island internals) and exposes CSS tokens for everything brandable. Your CSS:
- overrides tokens under
:root:root(doubled specificity so the theme wins), - styles your own section markup (class names are yours, the starter uses an
lq-prefix), - may restyle islands only through their published styling API.
What an artifact may NOT contain
Section titled “What an artifact may NOT contain”- No JavaScript. Behaviour is platform-owned; templates place islands.
- No network calls, no data fetching. The platform feeds renderers everything they get.
- No unsanitised HTML output.
| rawis for the contract’s richtext fields only. - No file inclusion,
include/render/layoutare excluded from the dialect and fail at parse time.

