ESLint preset
The authoring-lint preset shipped as `@homepages/eslint-plugin-template` — setup and scope. Per-rule reference lives in `rules/`.
@homepages/eslint-plugin-template is a flat-config ESLint preset carrying every
authoring rule the kit enforces one file at a time, under the template-kit/*
rule namespace.
npm i -D @homepages/eslint-plugin-template eslint @typescript-eslint/parserimport kit from "@homepages/eslint-plugin-template";export default kit;That is the whole setup — no plugin registration, no parser wiring, no tsconfig.
The preset registers its rules and sets languageOptions (parser included) itself,
so those two lines are a complete config.
The preset ships as its own package rather than a kit subpath because it needs a different dependency tree: ESLint and the parser, not React. That keeps a linter out of the production install of every app that renders a template — the kit’s main entry is a set of React primitives, and it must not drag one in.
ESLint and the parser are peer dependencies, so you install them yourself; the preset
resolves them from your workspace. If you see
Cannot find package '@typescript-eslint/parser', that is the install line above
missing.
The preset is syntactic only — it never sets parserOptions.project or
projectService. Nothing it enforces requires type information, which is what
keeps setup to zero extra config; a consumer’s own tsconfig.json is never
consulted.
The preset is consumed once at a workspace root and lints every section
nested under templates/**; there are no per-template config files. It ships
three config entries, matched by glob rather than by directory depth:
| Entry | Files | Rules |
|---|---|---|
template-kit/authoring |
**/*.ts, **/*.tsx |
the eleven file-scoped rules — see rules/ |
template-kit/contract-files |
**/Renderer.tsx, **/schema.ts, **/fill-spec.ts, **/fixtures.ts |
no-client-directive-in-contract |
template-kit/renderer |
**/Renderer.tsx |
props-from-schema |
Server-vs-client scoping is decided per file, by the "use client" directive
prologue — see server vs client for what that means
and exactly which rules stop at that boundary.
The rules
Section titled “The rules”Every rule the preset enforces — what it bans, why, and a before/after fix — is
documented once, per id, in rules/. Rules scoped to a single
file are enforced here, by this preset; rules scoped to the tree — a missing
contract file, a slot declared in schema.ts but unmarked in Renderer.tsx, a CSS
budget — cannot be expressed one-file-at-a-time and belong to
template-kit check under the same template-kit/<id> namespace. One
namespace, two venues: the id printed by either failure resolves to exactly one page.