@homepages/template-kit 0.9.0-dev-20260719224319 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. package/CHANGELOG.md +29 -59
  2. package/README.md +14 -4
  3. package/dist/contracts/fill-treatments.d.ts +23 -0
  4. package/dist/index.d.ts +2 -2
  5. package/dist/index.js +2 -2
  6. package/dist/islands/discover.js +1 -1
  7. package/dist/islands/esbuild-plugin.js +1 -1
  8. package/dist/islands/wrap.d.ts +9 -1
  9. package/dist/media/resolve-fixture-media.d.ts +22 -0
  10. package/dist/package.js +1 -1
  11. package/dist/schema/resolve-section-ref.d.ts +4 -0
  12. package/dist/schema/rows.d.ts +9 -0
  13. package/dist/schema/section-nav.d.ts +5 -1
  14. package/dist/schema/slot-types.d.ts +1 -1
  15. package/dist/ssr.d.ts +7 -2
  16. package/dist/ssr.js +6 -2
  17. package/guide/INDEX.md +5 -0
  18. package/guide/check.md +1 -0
  19. package/guide/dev.md +1 -0
  20. package/guide/llms.txt +11 -3
  21. package/guide/upgrading.md +12 -8
  22. package/package.json +4 -16
  23. package/dist/canvas-core/chrome-css.d.ts +0 -24
  24. package/dist/canvas-core/chrome-css.js +0 -403
  25. package/dist/canvas-core/chrome.d.ts +0 -49
  26. package/dist/canvas-core/chrome.js +0 -147
  27. package/dist/canvas-core/frame.d.ts +0 -20
  28. package/dist/canvas-core/frame.js +0 -23
  29. package/dist/canvas-core/hidden-tabs.d.ts +0 -16
  30. package/dist/canvas-core/hidden-tabs.js +0 -84
  31. package/dist/canvas-core/resolve-target.js +0 -55
  32. package/dist/canvas-core/scroll.d.ts +0 -10
  33. package/dist/canvas-core/scroll.js +0 -15
  34. package/dist/canvas-core/section-dom.d.ts +0 -6
  35. package/dist/canvas-core/section-dom.js +0 -43
  36. package/dist/canvas-core/srcdoc.d.ts +0 -8
  37. package/dist/canvas-core/srcdoc.js +0 -77
  38. package/dist/canvas-core/types.d.ts +0 -76
  39. package/dist/canvas-core.d.ts +0 -9
  40. package/dist/canvas-core.js +0 -9
  41. package/dist/cli/check/config.js +0 -41
  42. package/dist/cli/check/css.js +0 -131
  43. package/dist/cli/check/diagnostics.js +0 -37
  44. package/dist/cli/check/index.js +0 -94
  45. package/dist/cli/check/loader.js +0 -149
  46. package/dist/cli/check/paths.js +0 -15
  47. package/dist/cli/check/relativize.js +0 -18
  48. package/dist/cli/check/render-invariants.js +0 -24
  49. package/dist/cli/check/resolve-tool.js +0 -38
  50. package/dist/cli/check/section-assets.js +0 -58
  51. package/dist/cli/check/stages/deps.js +0 -337
  52. package/dist/cli/check/stages/lint.js +0 -46
  53. package/dist/cli/check/stages/render.js +0 -98
  54. package/dist/cli/check/stages/size.js +0 -274
  55. package/dist/cli/check/stages/tree.js +0 -206
  56. package/dist/cli/check/stages/typecheck.js +0 -46
  57. package/dist/cli/check/stages/validate/catalog-exhaustiveness.js +0 -18
  58. package/dist/cli/check/stages/validate/facts.js +0 -19
  59. package/dist/cli/check/stages/validate/formatter-contract.js +0 -14
  60. package/dist/cli/check/stages/validate/group-contract.js +0 -21
  61. package/dist/cli/check/stages/validate/index.js +0 -66
  62. package/dist/cli/check/stages/validate/list-scalar-contract.js +0 -22
  63. package/dist/cli/check/stages/validate/nav-contract.js +0 -93
  64. package/dist/cli/check/stages/validate/nested-slot-contract.js +0 -12
  65. package/dist/cli/check/stages/validate/object-list-contract.js +0 -31
  66. package/dist/cli/check/stages/validate/orchestrator.js +0 -241
  67. package/dist/cli/check/stages/validate/produced-by-contract.js +0 -18
  68. package/dist/cli/check/stages/validate/row-contract.js +0 -31
  69. package/dist/cli/check/stages/validate/select-contract.js +0 -13
  70. package/dist/cli/check/stages/validate/source-contract.js +0 -21
  71. package/dist/cli/check/stages/validate/variant-contract.js +0 -15
  72. package/dist/cli/check/workspace.js +0 -99
  73. package/dist/cli/dev/build-css.js +0 -97
  74. package/dist/cli/dev/catalog.js +0 -35
  75. package/dist/cli/dev/compose-template.js +0 -39
  76. package/dist/cli/dev/content-override.js +0 -58
  77. package/dist/cli/dev/diagnostics.js +0 -68
  78. package/dist/cli/dev/discover.js +0 -35
  79. package/dist/cli/dev/fill-state.js +0 -77
  80. package/dist/cli/dev/index.js +0 -42
  81. package/dist/cli/dev/inspect.js +0 -38
  82. package/dist/cli/dev/island-bootstrap.js +0 -38
  83. package/dist/cli/dev/island-canvas-bootstrap.js +0 -204
  84. package/dist/cli/dev/island-map.js +0 -35
  85. package/dist/cli/dev/island-transform.js +0 -31
  86. package/dist/cli/dev/manifest-instances.js +0 -31
  87. package/dist/cli/dev/render-section.js +0 -24
  88. package/dist/cli/dev/screenshot-target.js +0 -24
  89. package/dist/cli/dev/section-page.js +0 -91
  90. package/dist/cli/dev/server.js +0 -511
  91. package/dist/cli/dev/slot-schema.js +0 -12
  92. package/dist/cli/dev/structure-summary.js +0 -119
  93. package/dist/cli/dev/tailwind.js +0 -32
  94. package/dist/cli/dev/tsconfig-paths-plugin.js +0 -90
  95. package/dist/cli/dev/vite-server.js +0 -39
  96. package/dist/cli/dev/workspace.js +0 -63
  97. package/dist/cli/link/index.js +0 -74
  98. package/dist/cli/link/overlay.js +0 -59
  99. package/dist/cli/link/watch.js +0 -25
  100. package/dist/cli/new/emit.js +0 -48
  101. package/dist/cli/new/index.js +0 -69
  102. package/dist/cli/new/scaffold/section/_Renderer.tsx +0 -20
  103. package/dist/cli/new/scaffold/section/_fill-spec.ts +0 -18
  104. package/dist/cli/new/scaffold/section/_fixtures.ts +0 -13
  105. package/dist/cli/new/scaffold/section/_schema.ts +0 -24
  106. package/dist/cli/new/scaffold/template/_manifest.json +0 -9
  107. package/dist/cli/new/scaffold/template/sections/hero/ExpandableText.tsx +0 -45
  108. package/dist/cli/new/scaffold/template/sections/hero/Renderer.tsx +0 -40
  109. package/dist/cli/new/scaffold/template/sections/hero/components/Feature.tsx +0 -14
  110. package/dist/cli/new/scaffold/template/sections/hero/fill-spec.ts +0 -29
  111. package/dist/cli/new/scaffold/template/sections/hero/fixtures.ts +0 -41
  112. package/dist/cli/new/scaffold/template/sections/hero/schema.ts +0 -60
  113. package/dist/cli/new/scaffold/template/theme.css +0 -24
  114. package/dist/cli/new/scaffold/template/theme.ts +0 -27
  115. package/dist/cli/new/scaffold-assets.js +0 -20
  116. package/dist/cli/pack/collect.js +0 -44
  117. package/dist/cli/pack/guards.js +0 -57
  118. package/dist/cli/pack/index.js +0 -66
  119. package/dist/cli/pack/manifest.js +0 -15
  120. package/dist/cli/pack/zip.js +0 -86
  121. package/dist/cli/theme/generate.js +0 -43
  122. package/dist/cli/theme/index.js +0 -33
  123. package/dist/cli/theme/load-theme.js +0 -69
  124. package/dist/cli.d.ts +0 -1
  125. package/dist/cli.js +0 -138
  126. package/dist/dev-client/assets/index-CJa9G1Na.css +0 -1
  127. package/dist/dev-client/assets/index-C_1atZs4.js +0 -450
  128. package/dist/dev-client/index.html +0 -13
  129. package/dist/tokens.css +0 -21
package/CHANGELOG.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @homepages/template-kit
2
2
 
3
- ## 0.9.0-dev-20260719224319
3
+ ## 0.9.0
4
4
 
5
5
  ### Minor Changes
6
6
 
@@ -24,6 +24,34 @@
24
24
  `resolveImportedFile`, `resetClientFileCache`) that the plugin's rules consume
25
25
  over the peer edge.
26
26
 
27
+ - f868a43: **Breaking:** the CLI has moved to its own package, `@homepages/template-cli`.
28
+ Installing the kit no longer installs the `template-kit` command, and the
29
+ `./canvas-core` subpath is gone.
30
+
31
+ The command itself is unchanged — it is still `template-kit dev`, `template-kit
32
+ check`, and so on. Add the new package as a devDependency alongside your existing
33
+ kit dependency:
34
+
35
+ ```
36
+ npm i -D @homepages/template-cli
37
+ ```
38
+
39
+ The kit stays the package your templates import, under the same name and with the
40
+ same authoring API, so no `import` in a workspace changes. The CLI declares the kit
41
+ as a `peerDependency`, which is what guarantees a workspace resolves exactly one
42
+ copy of it.
43
+
44
+ Why: the CLI and its dev playground were 53% of the kit's published bytes while the
45
+ code that reaches a visitor's browser was under 1%, and they change on playground
46
+ cadence rather than contract cadence. Sharing one version number meant a
47
+ playground fix and an authoring-contract change were indistinguishable in the
48
+ number a template author reads.
49
+
50
+ `./ssr` additionally now exports `wrapClientModuleMagic`, `flattenLayout`,
51
+ `isShortSlot`, `resolveSectionRef`, `resolveAnchorMap` and `parseTreatment` — the
52
+ node-side schema and island helpers the CLI reaches across the peer edge. They are
53
+ deliberately absent from the authoring barrel: a renderer never imports `./ssr`.
54
+
27
55
  - b7bfc96: Fixtures state media asset ids instead of URLs, and the kit resolves them.
28
56
 
29
57
  A fixture now states what a saved page actually holds — `{ photo_id, alt }` — and
@@ -57,69 +85,11 @@
57
85
 
58
86
  ### Patch Changes
59
87
 
60
- - 10f53a7: `template-kit dev`'s canvas hover/select ring no longer overflows the page's
61
- x-axis when hovering a full-bleed section (e.g. a hero or header flush with
62
- both page edges). The ring's geometry inflated the target's bounding rect by
63
- a fixed offset on every side with no bound, so a rect already touching the
64
- document edge pushed the ring 2px past it, growing the iframe's horizontal
65
- scroll extent. The ring box is now clamped to `[0, containerWidth]`.
66
- - f3f6d70: `template-kit check` no longer fails on a tsconfig `paths` alias (e.g.
67
- `"@/platform/*": ["../platform/*"]`) or on a section whose contract files
68
- share a module large enough for esbuild to code-split. Previously the
69
- loader's css-stub plugin decided "external vs. bundle" from the specifier's
70
- own text, so a `paths`-resolved alias got re-emitted as a literal bare
71
- import Node couldn't resolve; separately, the loader's build applied
72
- `publicPath` to code-split `chunk-*.js` cross-imports the same way it does
73
- to real asset files, producing an import path Node couldn't resolve either.
74
- Both are now decided from the actual resolved file, and `publicPath` is no
75
- longer set on the loader's build.
76
- - 1c2c2db: `template-kit dev`'s preview server no longer 500s on `/runtime/base.css`.
77
- The route resolved the file at a path the build never emits to
78
- (`dist/css/base.css`; the build copies it flat to `dist/base.css`), so every
79
- section rendered unstyled — Tailwind-derived colors and layout were silently
80
- missing everywhere, only arbitrary-value element geometry survived. The
81
- route now checks the built (flat) path first and falls back to the source
82
- (`src/css/`) layout, so it resolves correctly both from an installed kit and
83
- when running the CLI unbuilt via `tsx` during kit development.
84
- - 989d23e: `template-kit dev` gains an optional `--diagnostics-cmd` flag: point it at any
85
- command that prints `{"violations": [...]}` JSON for a `--template`/`--section`
86
- pair, and the standalone section preview
87
- (`/sections/<template>/<section>/<fixture>`) shows a dismissible banner when it
88
- reports violations. Unset by default — no behavior change for a workspace that
89
- doesn't configure it.
90
- - e1d5792: `template-kit dev`'s preview server now compiles a template's theme-color
91
- Tailwind utilities (`bg-primary`, `text-ink`, `bg-background`, etc.) instead
92
- of silently dropping them. `assembleTemplateCss` used to concatenate the
93
- compiled theme (`compileThemeToCss`, the `@theme inline` alias layer plus
94
- its `:root` custom props) onto Tailwind's CLI output _after_ the CLI had
95
- already run, so the theme's color tokens were never part of the build graph
96
- Tailwind scanned — `@theme` outside that graph is inert, and silently so, so
97
- any utility built on a template color never got generated. No error, no
98
- warning: every section rendered with correct layout but default
99
- black-on-white text and backgrounds. The theme partial is now written to the
100
- dev cache and `@import`ed into the Tailwind entry ahead of the section
101
- `@source` scans, mirroring how the registry's own publish pipeline
102
- (`ci/build-css.ts`) has always assembled it. `fontFaces` is still prepended
103
- to the final bundle separately, since a nested `@import url(...)` doesn't
104
- hoist out of an imported partial.
105
- - 2e36277: Escape `>` and `&` as well as `<` in the dev server's island map, matching the escaping used by published pages.
106
88
  - 1c4c7dd: Island hydration is now nesting-safe: `hydrateIslands` skips any island marker
107
89
  nested inside another marker, so an island can render another island without the
108
90
  child being hydrated twice (once by its parent root, once independently). Enables
109
91
  interactive islands (accordion, card-slider, carousel) to wrap existing leaf
110
92
  islands (expandable-text) on published pages.
111
- - ff1d6de: `template-kit dev`'s canvas mirror now shows the Islands inspector panel for a
112
- section-level selection, not just a slot selection. A `fill-parent`/`fill-self`
113
- island with no owning slot of its own only ever gets its shield dropped by a
114
- section-level click, so the panel previously could show it as `shielded` but
115
- never `interactive`. Existing slot-selection behavior (edit panel + Islands
116
- list) is unchanged.
117
- - 41d0e88: `template-kit dev` now honors a workspace's tsconfig `paths` when resolving
118
- imports, the same way `check` already does via esbuild's native tsconfig
119
- lookup. Previously the dev server's Vite instance had no `paths` awareness at
120
- all, so a workspace mapping (e.g. `"@/lib/*": ["../lib/*"]`) that made `check`
121
- pass left `dev` 500ing with `Cannot find module`. A workspace with no `paths`
122
- mapping is unaffected.
123
93
 
124
94
  ## 0.8.0
125
95
 
package/README.md CHANGED
@@ -1,7 +1,9 @@
1
1
  # @homepages/template-kit
2
2
 
3
3
  The authoring surface for HomePages marketing-section templates: schema system,
4
- contract primitives, the theme system, and the `template-kit` CLI.
4
+ contract primitives, and the theme system. The `template-kit` command lives in its
5
+ own package, [`@homepages/template-cli`](#install) — the kit is what your templates
6
+ `import`.
5
7
 
6
8
  **Status: 0.0.x.** The **schema system** (the section authoring contract and the closed
7
9
  vocabulary it validates against), the **contract primitives**, and the **theme system**
@@ -31,9 +33,16 @@ Prefer to wire a workspace by hand? See **Install** below.
31
33
 
32
34
  ```bash
33
35
  npm install @homepages/template-kit react react-dom
36
+ npm install -D @homepages/template-cli # the `template-kit` command
34
37
  npm install -D typescript eslint @typescript-eslint/parser esbuild # the authoring toolchain
35
38
  ```
36
39
 
40
+ The **command is `template-kit`; the package that provides it is
41
+ `@homepages/template-cli`** — a package/bin mismatch in the same spirit as
42
+ `typescript`/`tsc`. Everything you write is imported from `@homepages/template-kit`;
43
+ the CLI declares the kit as a peer dependency, so a workspace resolves exactly one
44
+ copy of it.
45
+
37
46
  React 19 is a **peer dependency** — the kit never bundles its own copy.
38
47
 
39
48
  The kit has exactly **one runtime dependency** (`zod`). The authoring toolchain the
@@ -97,6 +106,7 @@ Full contract: **[guide/primitives.md](guide/primitives.md)**.
97
106
  | `@homepages/template-kit/browser` | Browser helpers for published pages (site config, signed ingest) |
98
107
  | `@homepages/template-kit/styles.css` | The global Tailwind preamble: the breakpoint ladder, the spacing base unit, the motion defaults, kit source registration |
99
108
  | `@homepages/template-kit/base.css` | Cascade-layer order, the three reset gaps Tailwind's preflight leaves, `.tr-section`, and the motion tokens |
109
+ | `@homepages/template-cli` | The `template-kit` command (its own package) |
100
110
  | `@homepages/eslint-plugin-template` | ESLint flat-config preset (its own package) |
101
111
  | `@homepages/template-kit/tsconfig` | tsconfig preset (`"extends"`) |
102
112
 
@@ -158,7 +168,7 @@ section also has a standalone page, and so does the whole template at
158
168
  payload), and `/api/screenshot` (a full-page PNG, section or whole template). Like
159
169
  `check`, it runs **your** toolchain — Vite and Tailwind resolved from your workspace,
160
170
  installed with `npm i -D vite @vitejs/plugin-react tailwindcss @tailwindcss/cli` — not
161
- shipped by the kit. Full contract: **[guide/dev.md](guide/dev.md)**.
171
+ shipped by either package. Full contract: **[guide/dev.md](guide/dev.md)**.
162
172
 
163
173
  ## Checking a workspace
164
174
 
@@ -229,5 +239,5 @@ that vocabulary — your template names its own.
229
239
 
230
240
  Don't — changesets owns `package.json`'s version. There is nothing else to keep
231
241
  in step with it: `KIT_VERSION` is read from `package.json` and inlined at build
232
- time, and the test suite asserts `template-kit --version` against `package.json`
233
- to prove the inlining happened.
242
+ time, and the test suite asserts it against `package.json` to prove the inlining
243
+ happened.
@@ -0,0 +1,23 @@
1
+ //#region src/contracts/fill-treatments.d.ts
2
+ declare const GENERATED_KINDS: readonly ["text", "list<text>"];
3
+ type GeneratedKind = (typeof GENERATED_KINDS)[number];
4
+ declare const COMPUTED_FNS: readonly ["haversine_miles", "mint_id"];
5
+ type ComputedFn = (typeof COMPUTED_FNS)[number];
6
+ declare const CATALOG_FIELDS: readonly ["key", "label", "icon", "slot"];
7
+ type CatalogField = (typeof CATALOG_FIELDS)[number];
8
+ type Treatment = {
9
+ kind: "source";
10
+ path: string | null;
11
+ } | {
12
+ kind: "computed";
13
+ fn: ComputedFn;
14
+ } | {
15
+ kind: "catalog";
16
+ field: CatalogField;
17
+ } | {
18
+ kind: "generated";
19
+ outKind: GeneratedKind;
20
+ };
21
+ declare function parseTreatment(raw: string): Treatment | null;
22
+ //#endregion
23
+ export { CATALOG_FIELDS, COMPUTED_FNS, CatalogField, ComputedFn, GENERATED_KINDS, GeneratedKind, Treatment, parseTreatment };
package/dist/index.d.ts CHANGED
@@ -34,8 +34,8 @@ import { TokenNameSchema, TokenTheme, TokenThemeSchema, compileThemeToCss } from
34
34
  * Read from package.json and inlined at build time, so it cannot drift: changesets
35
35
  * owns package.json's version, and a hardcoded constant here would have to be
36
36
  * hand-edited on every release — on a branch changesets force-pushes, which would
37
- * silently discard the edit. `dist/cli.js --version` is asserted against
38
- * package.json to prove the inlining actually happened.
37
+ * silently discard the edit. src/index.test.ts asserts it against package.json to
38
+ * prove the inlining actually happened.
39
39
  */
40
40
  declare const KIT_VERSION: string;
41
41
  //#endregion
package/dist/index.js CHANGED
@@ -27,8 +27,8 @@ import { TokenNameSchema, TokenThemeSchema, compileThemeToCss } from "./design-s
27
27
  * Read from package.json and inlined at build time, so it cannot drift: changesets
28
28
  * owns package.json's version, and a hardcoded constant here would have to be
29
29
  * hand-edited on every release — on a branch changesets force-pushes, which would
30
- * silently discard the edit. `dist/cli.js --version` is asserted against
31
- * package.json to prove the inlining actually happened.
30
+ * silently discard the edit. src/index.test.ts asserts it against package.json to
31
+ * prove the inlining actually happened.
32
32
  */
33
33
  const KIT_VERSION = version;
34
34
 
@@ -1,6 +1,6 @@
1
1
  import { isClientComponentFile } from "./detect.js";
2
- import { readdir } from "node:fs/promises";
3
2
  import { extname, join } from "node:path";
3
+ import { readdir } from "node:fs/promises";
4
4
 
5
5
  //#region src/islands/discover.ts
6
6
  const COMPONENT_EXTS = /* @__PURE__ */ new Set([".tsx", ".jsx"]);
@@ -1,7 +1,7 @@
1
1
  import { islandKey } from "./detect.js";
2
2
  import { wrapClientModuleSource } from "./wrap.js";
3
- import { readFile } from "node:fs/promises";
4
3
  import { basename, extname } from "node:path";
4
+ import { readFile } from "node:fs/promises";
5
5
 
6
6
  //#region src/islands/esbuild-plugin.ts
7
7
  const LOADER = {
@@ -1,5 +1,13 @@
1
1
  import MagicString from "magic-string";
2
2
  //#region src/islands/wrap.d.ts
3
+ /**
4
+ * The codemod as a `MagicString`, so a caller (the Vite plugin) can emit a
5
+ * hi-res sourcemap alongside the rewritten code. Returns null on the same terms
6
+ * as `wrapClientModuleSource` — a non-client module or one with no default
7
+ * export. The rebound original is `__trIslandReal`; it still flows through the
8
+ * consumer's JSX/TS transform unchanged.
9
+ */
10
+ declare function wrapClientModuleMagic(code: string, islandKey: string): MagicString | null;
3
11
  /**
4
12
  * Rewrite a client module's source so its default export renders through
5
13
  * `IslandMarker` with `islandKey`. Returns null when `code` is not a client
@@ -9,4 +17,4 @@ import MagicString from "magic-string";
9
17
  */
10
18
  declare function wrapClientModuleSource(code: string, islandKey: string): string | null;
11
19
  //#endregion
12
- export { wrapClientModuleSource };
20
+ export { wrapClientModuleMagic, wrapClientModuleSource };
@@ -0,0 +1,22 @@
1
+ //#region src/media/resolve-fixture-media.d.ts
2
+ /**
3
+ * `resolveFixtureMedia` over a built fixture set — the form every node-only caller
4
+ * (the SSR loader, `template-kit check`) actually needs.
5
+ */
6
+ declare function resolveFixtureSetMedia<T extends {
7
+ props: unknown;
8
+ }>(fixtures: T[]): T[];
9
+ /** A fixture stating a media asset id the pack does not carry. */
10
+ type UnresolvedMedia = {
11
+ /** Where the id sits — `photo_id`, `video_id`, `floor_plans[].id`. */
12
+ field: string;
13
+ id: string;
14
+ };
15
+ /**
16
+ * Every media asset id a fixture states that the pack does not carry. Run over
17
+ * PRE-resolution props — after resolution the id is gone, replaced by the empty
18
+ * default.
19
+ */
20
+ declare function findUnresolvedMedia(props: unknown): UnresolvedMedia[];
21
+ //#endregion
22
+ export { UnresolvedMedia, findUnresolvedMedia, resolveFixtureSetMedia };
package/dist/package.js CHANGED
@@ -1,5 +1,5 @@
1
1
  //#region package.json
2
- var version = "0.9.0-dev-20260719224319";
2
+ var version = "0.9.0";
3
3
 
4
4
  //#endregion
5
5
  export { version };
@@ -0,0 +1,4 @@
1
+ //#region src/schema/resolve-section-ref.d.ts
2
+ declare function resolveSectionRef(templateKey: string, ref: string): string;
3
+ //#endregion
4
+ export { resolveSectionRef };
@@ -0,0 +1,9 @@
1
+ //#region src/schema/rows.d.ts
2
+ type LayoutEntry = string | readonly [string, string];
3
+ declare function flattenLayout(layout: readonly LayoutEntry[]): string[];
4
+ declare function isShortSlot(slot: {
5
+ type: string;
6
+ size?: string;
7
+ }): boolean;
8
+ //#endregion
9
+ export { LayoutEntry, flattenLayout, isShortSlot };
@@ -3,5 +3,9 @@ type SectionNav = {
3
3
  selfAnchor: string;
4
4
  anchors: Record<string, string>;
5
5
  };
6
+ declare function resolveAnchorMap(sections: ReadonlyArray<{
7
+ key: string;
8
+ anchor: string;
9
+ }>): Record<string, string>;
6
10
  //#endregion
7
- export { SectionNav };
11
+ export { SectionNav, resolveAnchorMap };
@@ -11,8 +11,8 @@ declare function slotDefTypes(): SlotType[];
11
11
  declare const ContentSlot: z.ZodObject<{
12
12
  type: z.ZodEnum<{
13
13
  number: "number";
14
- select: "select";
15
14
  text: "text";
15
+ select: "select";
16
16
  image: "image";
17
17
  image_collection: "image_collection";
18
18
  list: "list";
package/dist/ssr.d.ts CHANGED
@@ -1,11 +1,16 @@
1
+ import { resolveAnchorMap } from "./schema/section-nav.js";
1
2
  import { ResolvedFixture } from "./schema/fixture-schema.js";
2
3
  import "./schema/index.js";
3
4
  import { hasClientDirective, isClientFile, resetClientFileCache, resolveImportedFile } from "./islands/client-directive.js";
4
5
  import { isClientComponentFile, islandKey } from "./islands/detect.js";
5
- import { wrapClientModuleSource } from "./islands/wrap.js";
6
+ import { wrapClientModuleMagic, wrapClientModuleSource } from "./islands/wrap.js";
6
7
  import { findSectionIslands } from "./islands/discover.js";
7
8
  import { islandTransformEsbuildPlugin } from "./islands/esbuild-plugin.js";
8
9
  import { DEV_MEDIA_URL_PREFIX, MediaAsset, MediaKind, getMediaAsset, listMediaAssets, mediaPackHasFile, packRelativeFromUrl } from "./media/pack.js";
10
+ import { UnresolvedMedia, findUnresolvedMedia, resolveFixtureSetMedia } from "./media/resolve-fixture-media.js";
11
+ import { Treatment, parseTreatment } from "./contracts/fill-treatments.js";
12
+ import { LayoutEntry, flattenLayout, isShortSlot } from "./schema/rows.js";
13
+ import { resolveSectionRef } from "./schema/resolve-section-ref.js";
9
14
  import { ComponentType } from "react";
10
15
  //#region src/ssr/index.d.ts
11
16
  type LoadedSection = {
@@ -43,4 +48,4 @@ declare function loadSectionBundle(dir: string, load?: SectionModuleLoader): Pro
43
48
  */
44
49
  declare function renderSectionHtml(renderer: ComponentType<Record<string, unknown>>, props: Record<string, unknown>): string;
45
50
  //#endregion
46
- export { DEV_MEDIA_URL_PREFIX, LoadedSection, type MediaAsset, type MediaKind, SectionModuleLoader, findSectionIslands, getMediaAsset, hasClientDirective, isClientComponentFile, isClientFile, islandKey, islandTransformEsbuildPlugin, listMediaAssets, loadSectionBundle, mediaPackHasFile, nativeSectionLoader, packRelativeFromUrl, renderSectionHtml, resetClientFileCache, resolveImportedFile, wrapClientModuleSource };
51
+ export { DEV_MEDIA_URL_PREFIX, type LayoutEntry, LoadedSection, type MediaAsset, type MediaKind, SectionModuleLoader, type Treatment, type UnresolvedMedia, findSectionIslands, findUnresolvedMedia, flattenLayout, getMediaAsset, hasClientDirective, isClientComponentFile, isClientFile, isShortSlot, islandKey, islandTransformEsbuildPlugin, listMediaAssets, loadSectionBundle, mediaPackHasFile, nativeSectionLoader, packRelativeFromUrl, parseTreatment, renderSectionHtml, resetClientFileCache, resolveAnchorMap, resolveFixtureSetMedia, resolveImportedFile, resolveSectionRef, wrapClientModuleMagic, wrapClientModuleSource };
package/dist/ssr.js CHANGED
@@ -3,9 +3,13 @@ import { DEV_MEDIA_URL_PREFIX, getMediaAsset, listMediaAssets, mediaPackHasFile,
3
3
  import { findUnresolvedMedia, resolveFixtureSetMedia } from "./media/resolve-fixture-media.js";
4
4
  import { hasClientDirective, isClientFile, resetClientFileCache, resolveImportedFile } from "./islands/client-directive.js";
5
5
  import { isClientComponentFile, islandKey } from "./islands/detect.js";
6
- import { wrapClientModuleSource } from "./islands/wrap.js";
6
+ import { wrapClientModuleMagic, wrapClientModuleSource } from "./islands/wrap.js";
7
7
  import { findSectionIslands } from "./islands/discover.js";
8
8
  import { islandTransformEsbuildPlugin } from "./islands/esbuild-plugin.js";
9
+ import { parseTreatment } from "./contracts/fill-treatments.js";
10
+ import { flattenLayout, isShortSlot } from "./schema/rows.js";
11
+ import { resolveSectionRef } from "./schema/resolve-section-ref.js";
12
+ import { resolveAnchorMap } from "./schema/section-nav.js";
9
13
  import { createElement } from "react";
10
14
  import { basename, join } from "node:path";
11
15
  import { pathToFileURL } from "node:url";
@@ -61,4 +65,4 @@ function renderSectionHtml(renderer, props) {
61
65
  }
62
66
 
63
67
  //#endregion
64
- export { DEV_MEDIA_URL_PREFIX, findSectionIslands, getMediaAsset, hasClientDirective, isClientComponentFile, isClientFile, islandKey, islandTransformEsbuildPlugin, listMediaAssets, loadSectionBundle, mediaPackHasFile, nativeSectionLoader, packRelativeFromUrl, renderSectionHtml, resetClientFileCache, resolveImportedFile, wrapClientModuleSource };
68
+ export { DEV_MEDIA_URL_PREFIX, findSectionIslands, findUnresolvedMedia, flattenLayout, getMediaAsset, hasClientDirective, isClientComponentFile, isClientFile, isShortSlot, islandKey, islandTransformEsbuildPlugin, listMediaAssets, loadSectionBundle, mediaPackHasFile, nativeSectionLoader, packRelativeFromUrl, parseTreatment, renderSectionHtml, resetClientFileCache, resolveAnchorMap, resolveFixtureSetMedia, resolveImportedFile, resolveSectionRef, wrapClientModuleMagic, wrapClientModuleSource };
package/guide/INDEX.md CHANGED
@@ -11,6 +11,11 @@ This tree **ships in the npm tarball** (`guide/` is listed in `package.json`'s
11
11
  LLM agents, reading it from inside `node_modules`. Keep it free of internal-only
12
12
  detail.
13
13
 
14
+ Every `template-kit <command>` on these pages is spelled exactly as you type it.
15
+ The package that provides that command is `@homepages/template-cli`, a
16
+ devDependency alongside the kit — see [Upgrading](upgrading.md) for its separate
17
+ version line.
18
+
14
19
  | Doc | What it covers | Read when you're touching... |
15
20
  |---|---|---|
16
21
  | `quickstart.md` | The cold-start tutorial: create a workspace, preview the starter's `hero` section, read its four files, make one edit, and check it — owns the author-loop anchor every recipe links to | your first section, end to end |
package/guide/check.md CHANGED
@@ -28,6 +28,7 @@ one or pass `--all`.
28
28
  ### What it needs installed
29
29
 
30
30
  ```bash
31
+ npm i -D @homepages/template-cli # provides the `template-kit` command
31
32
  npm i -D typescript eslint @typescript-eslint/parser esbuild @homepages/eslint-plugin-template
32
33
  ```
33
34
 
package/guide/dev.md CHANGED
@@ -28,6 +28,7 @@ command runs until you interrupt it (Ctrl-C).
28
28
  ### What it needs installed
29
29
 
30
30
  ```bash
31
+ npm i -D @homepages/template-cli # provides the `template-kit` command
31
32
  npm i -D vite @vitejs/plugin-react tailwindcss @tailwindcss/cli
32
33
  ```
33
34
 
package/guide/llms.txt CHANGED
@@ -1,8 +1,8 @@
1
1
  # @homepages/template-kit
2
2
 
3
3
  > The authoring kit for HomePages marketing-section templates. This corpus ships
4
- > inside the npm package so an agent can read it locally, versioned in lockstep
5
- > with the code it describes.
4
+ > inside the npm package so an agent can read it locally, versioned with the
5
+ > authoring contract it describes.
6
6
 
7
7
  Status: 0.x — pre-1.0, so a minor is the breaking axis and a patch carries features
8
8
  as well as fixes; see [Upgrading](upgrading.md). The schema system, the contract
@@ -13,6 +13,12 @@ implemented — see [Check](check.md), [Theme and CSS](theme-and-css.md#generati
13
13
  [Dev](dev.md), [Pack](pack.md), and [Adding templates](new.md); its remaining
14
14
  commands arrive with the surfaces they drive.
15
15
 
16
+ The **command is `template-kit`; the package that provides it is
17
+ `@homepages/template-cli`**, a devDependency alongside the kit. It versions on its
18
+ own line and declares the kit as a peer dependency, so a workspace resolves exactly
19
+ one kit. Every command written in this corpus is spelled the same either way — only
20
+ the install line names the CLI package.
21
+
16
22
  Everything an author writes a section against is imported from the package root —
17
23
  `@homepages/template-kit`. The exceptions are deliberate: the two CSS entries
18
24
  (`./styles.css`, `./base.css`), and `./fixtures` — the golden scenarios, which only
@@ -102,7 +108,9 @@ and [Pick a scenario](recipes/pick-a-scenario.md).
102
108
  patch (0.4.0 → 0.4.1) carries features AND fixes and `npm update` takes it, while
103
109
  a minor (0.4.x → 0.5.0) is breaking and needs an explicit
104
110
  `npm install @homepages/template-kit@^0.5.0` — a 0.x caret never crosses a minor.
105
- Submissions are accepted against the current kit line and the one before it.
111
+ `@homepages/template-cli` and `@homepages/eslint-plugin-template` each version on
112
+ their own line and update separately. Submissions are accepted against the current
113
+ kit line and the one before it.
106
114
  - [Adding templates](new.md): the `template-kit new <template>` and
107
115
  `template-kit new-section <template>/<section>` CLI commands — scaffolding a new
108
116
  template with a working starter section, or adding a bare section (the four
@@ -43,19 +43,21 @@ npm run check
43
43
  CHANGELOG in the package (`node_modules/@homepages/template-kit/CHANGELOG.md`) for
44
44
  what changed and why.
45
45
 
46
- ## The lint preset upgrades separately
46
+ ## The CLI and the lint preset upgrade separately
47
47
 
48
- `@homepages/eslint-plugin-template` is its own package with its own version line,
49
- so the kit's number tells you nothing about it and `npm update
50
- @homepages/template-kit` never moves it. Update it the same way, on its own:
48
+ `@homepages/template-cli` (which provides the `template-kit` command) and
49
+ `@homepages/eslint-plugin-template` (the lint preset) are each their own package on
50
+ their own version line, so the kit's number tells you nothing about them and `npm
51
+ update @homepages/template-kit` never moves them. Update each on its own:
51
52
 
52
53
  ```bash
54
+ npm update @homepages/template-cli
53
55
  npm update @homepages/eslint-plugin-template
54
56
  ```
55
57
 
56
- It declares the kit as a **peer dependency**, so its range says which kit line it
57
- supports. If `npm install` reports a peer conflict after a kit minor, the preset is
58
- the package to bump — not the kit to hold back.
58
+ Both declare the kit as a **peer dependency**, so each one's range says which kit
59
+ line it supports. If `npm install` reports a peer conflict after a kit minor, the
60
+ package to bump is the one reporting it — not the kit to hold back.
59
61
 
60
62
  ## How long you have
61
63
 
@@ -74,4 +76,6 @@ npm ls @homepages/template-kit # what you have installed
74
76
  npm view @homepages/template-kit version # the current release
75
77
  ```
76
78
 
77
- The same two commands work for `@homepages/eslint-plugin-template`.
79
+ The same two commands work for `@homepages/template-cli` and
80
+ `@homepages/eslint-plugin-template`. `template-kit --version` prints the pair the
81
+ command is actually running as `<cli> (kit <kit>)`.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@homepages/template-kit",
3
- "version": "0.9.0-dev-20260719224319",
4
- "description": "Authoring kit for HomePages marketing-section templates: schema system, contract primitives, theme tokens, and the template-kit CLI.",
3
+ "version": "0.9.0",
4
+ "description": "Authoring kit for HomePages marketing-section templates: schema system, contract primitives, theme tokens, and the design-system CSS layer.",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",
7
7
  "engines": {
@@ -22,9 +22,6 @@
22
22
  "tsconfig.base.json",
23
23
  "CHANGELOG.md"
24
24
  ],
25
- "bin": {
26
- "template-kit": "dist/cli.js"
27
- },
28
25
  "exports": {
29
26
  ".": {
30
27
  "types": "./dist/index.d.ts",
@@ -50,10 +47,6 @@
50
47
  "types": "./dist/rules.d.ts",
51
48
  "default": "./dist/rules.js"
52
49
  },
53
- "./canvas-core": {
54
- "types": "./dist/canvas-core.d.ts",
55
- "default": "./dist/canvas-core.js"
56
- },
57
50
  "./styles.css": "./dist/styles.css",
58
51
  "./base.css": "./dist/base.css",
59
52
  "./tsconfig": "./tsconfig.base.json",
@@ -64,10 +57,9 @@
64
57
  ],
65
58
  "scripts": {
66
59
  "prepack": "npm run build",
67
- "build": "tsdown && node scripts/build-dev-client.mjs && node scripts/build-cli-assets.mjs",
60
+ "build": "tsdown",
68
61
  "typecheck": "tsc --noEmit",
69
62
  "lint": "eslint .",
70
- "pretest": "node test/link-fixture-workspace.mjs",
71
63
  "test": "node --import tsx --test 'src/**/*.test.ts' 'src/**/*.test.tsx'",
72
64
  "lint:pkg": "publint --strict && attw --pack . --profile esm-only --exclude-entrypoints styles.css base.css",
73
65
  "verify:consumer": "node scripts/verify-consumer.mjs",
@@ -81,15 +73,12 @@
81
73
  "devDependencies": {
82
74
  "@arethetypeswrong/cli": "^0.18.5",
83
75
  "@eslint/js": "^9.39.4",
84
- "@playwright/test": "^1.60.0",
85
76
  "@tailwindcss/cli": "^4.3.0",
86
77
  "@types/jsdom": "^21.1.7",
87
78
  "@types/node": "^20.17.10",
88
79
  "@types/react": "^19.0.0",
89
80
  "@types/react-dom": "^19.0.0",
90
81
  "@typescript-eslint/parser": "^8.60.1",
91
- "@vitejs/plugin-react": "^4.3.4",
92
- "chokidar": "^4.0.1",
93
82
  "esbuild": "^0.28.1",
94
83
  "eslint": "^9.39.4",
95
84
  "jsdom": "^26.1.0",
@@ -100,8 +89,7 @@
100
89
  "tsdown": "0.22.7",
101
90
  "tsx": "^4.19.2",
102
91
  "typescript": "^5.7.2",
103
- "typescript-eslint": "^8.60.1",
104
- "vite": "^6.0.5"
92
+ "typescript-eslint": "^8.60.1"
105
93
  },
106
94
  "dependencies": {
107
95
  "magic-string": "^0.30.21",
@@ -1,24 +0,0 @@
1
- import { MarkerAttrs } from "./types.js";
2
- //#region src/canvas-core/chrome-css.d.ts
3
- /**
4
- * Custom properties the chrome CSS reads but deliberately does not declare —
5
- * the host must set them on the iframe document's root element. This is the
6
- * host's obligation, not a suggestion: an adapter that skips one leaves the
7
- * declared inline fallback in force, which renders plausibly and silently
8
- * wrong rather than failing.
9
- *
10
- * - `--we-panel-w`: the floating panel's measured width, mirrored onto the
11
- * iframe root so the page card's right padding clears it. Unset, the card
12
- * lays out against the 436px base-width fallback and drifts out of alignment
13
- * whenever the real panel is any other width.
14
- * - `--we-content`: the host's interior scaling unit, mirrored in so hidden-tab
15
- * chrome scales with the rest of the UI. Unset, it pins to the 1px fallback
16
- * and the tabs stay laptop-sized while every surrounding surface scales.
17
- *
18
- * Anything added here must actually be read by the kernel; the token test
19
- * fails on a stale entry.
20
- */
21
- declare const HOST_INJECTED_PROPERTIES: readonly ["--we-panel-w", "--we-content"];
22
- declare function buildChromeCss(markers: MarkerAttrs): string;
23
- //#endregion
24
- export { HOST_INJECTED_PROPERTIES, buildChromeCss };