Skip to content
HomePagesHomePages template kit

Rules

Router for the rule corpus — every `template-kit/<id>` an author can hit, and the page that explains it.

Every authoring rule the kit enforces is printed under one namespace, template-kit/<id>, and resolves to exactly one page here: guide/rules/<id>.md.

One namespace, two venues. Some rules are properties of one file (a Date.now() in a Renderer) and are enforced by the ESLint preset, which ships as its own package, @homepages/eslint-plugin-template. Others are properties of the tree (a slot declared in the schema but never marked in the JSX, a stylesheet, a dependency, a byte budget) and cannot be expressed one file at a time; those are enforced by template-kit check. You never need to know which engine produced a violation — only the id, which names its page either way.

Read server vs client first if you are here for any rule that mentions “server-rendered code” or an island. It is the one concept those rules assume, and it is explained there rather than on each of them.

Rule Venue What it enforces
no-nondeterminism eslint No clock or randomness reads in server-rendered code.
no-client-runtime-in-server eslint No effects, state, event handlers, network, or browser globals in server-rendered code.
serializable-island-props eslint Props handed to an island must be JSON-serializable.
require-island-editor eslint Every island must declare whether it is live in the editor canvas.
require-editor-reason eslint Every fork on inCanvas must carry an editor-reason: comment naming what it protects.
no-editor-globals eslint No reads of the platform’s internal __tr* canvas globals — useEditor() is the contract.
no-client-directive-in-contract eslint No “use client” in a section’s contract files.
no-node-builtins-in-contract eslint No Node built-in imports in a section’s contract files.
props-from-schema eslint A Renderer’s Props type must be derived from schema.ts, not hand-written.
no-slot-marker-literal eslint No hand-written data-slot-* attributes or string literals — markers come from the Slot primitives.
no-raw-slot-values eslint Read slot values through bindSlots/bindItems, never off the raw slots prop.
no-inline-style eslint No inline style= in server-rendered JSX. Islands are exempt.
no-hex eslint No hard-coded colours — the one legal colour function is a color-mix() over theme-derived arguments. Islands are NOT exempt.
no-css-import-from-render-path eslint No relative/absolute .css import from a section’s render path — a package’s is the sanctioned channel.
bundle-incomplete check A section folder is missing one of its contract files.
bundle-binary-asset check An unreferenced binary asset sits in a section folder.
schema-invalid check A section’s schema.ts or fill-spec.ts fails a contract assertion, or cannot be loaded.
fixtures-invalid check A section’s fixtures.ts does not satisfy the fixture-module shape.
template-invalid check A template’s template.ts is missing, unloadable, or violates the composition contract.
theme-invalid check A template’s theme.ts is missing, does not export theme, or exports one that is not a valid TokenTheme.
missing-slot-marker check Every editable slot, every per-item collection row, and every declared row field must reach the rendered DOM with a selectable marker.
unit-collection-item-marker check A collection edited as one unit must not render data-slot-item row markers.
group-ancestry check A grouped slot must be marked inside its group’s data-slot-group element.
section-unrenderable check A section that fails to load renders no fixture, so none of its markers can be proven.
island-server-frame check An island’s serverFrame declaration must match what it actually server-renders.
css-reason check A hand-written CSS file must open with a css-reason: comment.
no-bare-css-import check No @import in hand-written CSS — the browser drops it silently.
unlayered-fence check An /* unlayered: */ escape hatch must be balanced and give a reason.
section-root-margin check No margin utilities on the section root — margin opens gaps between sections.
frame-aspect-conflict check No aspect utilities on a framed element — the slot’s declared frame owns its aspect.
sidebar-order check Schema slot order must match the order the page renders them in.
rendered-class-conflict check A section must not be composed by both a website template and a rendered-class one.
rendered-no-motion check No animation or transition in an image or document class — a still frame never plays them.
rendered-no-fixed check No position: fixed or sticky in a rendered class — both bind wrongly in the stacked print document.
unknown-format-variant check A format-variant prefix must name a declared format of a template composing the section.
typecheck check The template must compile under TypeScript.
parse-error check A file could not be parsed at all — a syntax error, not a rule violation.
determinism-drift check Rendering the same fixture twice must produce byte-identical HTML.
render-invariant check Rendered output must carry no [object Object], bare null/undefined/NaN leaf, src-less <img>, or dev-media URL naming no file in the pack.
lockfile-missing check The workspace has no package-lock.json.
lockfile-stale check The lockfile does not satisfy package.json — an npm ci would fail.
single-react check The installed tree carries more than one copy of react or react-dom.
audit-severity check A dependency carries a high or critical security advisory.
size-renderer-bundle check A section’s renderer bundle exceeds its byte budget.
size-section-css check A section’s compiled CSS exceeds its byte budget.
size-island-bundle check A section’s island (browser) bundle exceeds its byte budget.
size-assets check A single static asset is heavier than the guideline. Warning only.
no-templates check The workspace has no template to check at all.
  • Server vs client — how a file is scoped, and which rules stop at the hydration boundary.
  • ESLint preset — setting the preset up in a template workspace.
  • Run check — running the gate and reading what it reports.
  • check reference — its flags, stages, thresholds and exit codes.