@homepages/template-kit 0.1.0 → 0.3.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.
- package/CHANGELOG.md +220 -0
- package/README.md +70 -16
- package/dist/base.css +36 -48
- package/dist/cli/check/config.js +37 -0
- package/dist/cli/check/css.js +117 -0
- package/dist/cli/check/diagnostics.js +32 -0
- package/dist/cli/check/index.js +87 -0
- package/dist/cli/check/loader.js +142 -0
- package/dist/cli/check/paths.js +15 -0
- package/dist/cli/check/relativize.js +18 -0
- package/dist/cli/check/render-invariants.js +24 -0
- package/dist/cli/check/resolve-tool.js +38 -0
- package/dist/cli/check/stages/deps.js +337 -0
- package/dist/cli/check/stages/lint.js +46 -0
- package/dist/cli/check/stages/render.js +101 -0
- package/dist/cli/check/stages/size.js +158 -0
- package/dist/cli/check/stages/tree.js +207 -0
- package/dist/cli/check/stages/typecheck.js +46 -0
- package/dist/cli/check/stages/validate/catalog-exhaustiveness.js +18 -0
- package/dist/cli/check/stages/validate/facts.js +18 -0
- package/dist/cli/check/stages/validate/formatter-contract.js +14 -0
- package/dist/cli/check/stages/validate/group-contract.js +21 -0
- package/dist/cli/check/stages/validate/index.js +66 -0
- package/dist/cli/check/stages/validate/list-scalar-contract.js +22 -0
- package/dist/cli/check/stages/validate/nav-contract.js +93 -0
- package/dist/cli/check/stages/validate/nested-slot-contract.js +12 -0
- package/dist/cli/check/stages/validate/object-list-contract.js +31 -0
- package/dist/cli/check/stages/validate/orchestrator.js +241 -0
- package/dist/cli/check/stages/validate/produced-by-contract.js +18 -0
- package/dist/cli/check/stages/validate/row-contract.js +31 -0
- package/dist/cli/check/stages/validate/select-contract.js +13 -0
- package/dist/cli/check/stages/validate/source-contract.js +21 -0
- package/dist/cli/check/stages/validate/variant-contract.js +15 -0
- package/dist/cli/check/workspace.js +86 -0
- package/dist/cli/theme/generate.js +43 -0
- package/dist/cli/theme/index.js +33 -0
- package/dist/cli/theme/load-theme.js +69 -0
- package/dist/cli.js +22 -4
- package/dist/contracts/fill-treatments.js +47 -0
- package/dist/design-system/theme.d.ts +30 -299
- package/dist/design-system/theme.js +112 -83
- package/dist/eslint/rules/image-bare-needs-reason.js +6 -1
- package/dist/eslint/rules/no-client-directive-in-contract.js +6 -1
- package/dist/eslint/rules/no-client-runtime-in-server.js +5 -1
- package/dist/eslint/rules/no-css-import-from-render-path.js +8 -2
- package/dist/eslint/rules/no-hex.js +84 -7
- package/dist/eslint/rules/no-inline-style.js +5 -1
- package/dist/eslint/rules/no-nondeterminism.js +5 -1
- package/dist/eslint/rules/no-raw-element.js +6 -1
- package/dist/eslint/rules/props-from-schema.js +6 -1
- package/dist/eslint/rules/serializable-island-props.js +5 -1
- package/dist/eslint/rules/slot-marker-literal.js +6 -1
- package/dist/eslint.js +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/package.js +1 -1
- package/dist/primitives/Image.js +1 -1
- package/dist/rules/registry.js +16 -0
- package/dist/schema/fill-spec.d.ts +80 -590
- package/dist/schema/fixture-schema.d.ts +5 -81
- package/dist/schema/manifest.d.ts +39 -475
- package/dist/schema/resolve-section-ref.js +10 -0
- package/dist/schema/rows.js +10 -0
- package/dist/schema/section-nav.js +9 -0
- package/dist/schema/section-schema.d.ts +51 -437
- package/dist/schema/slot-types.d.ts +12 -16
- package/dist/styles.css +31 -88
- package/docs/INDEX.md +5 -3
- package/docs/check.md +121 -0
- package/docs/eslint.md +25 -50
- package/docs/llms.txt +26 -11
- package/docs/primitives.md +5 -0
- package/docs/rules/INDEX.md +65 -0
- package/docs/rules/audit-severity.md +91 -0
- package/docs/rules/bundle-binary-asset.md +102 -0
- package/docs/rules/bundle-incomplete.md +117 -0
- package/docs/rules/css-reason.md +94 -0
- package/docs/rules/determinism-drift.md +112 -0
- package/docs/rules/fixtures-invalid.md +96 -0
- package/docs/rules/image-bare-needs-reason.md +117 -0
- package/docs/rules/license-denied.md +114 -0
- package/docs/rules/lockfile-missing.md +68 -0
- package/docs/rules/lockfile-stale.md +88 -0
- package/docs/rules/manifest-invalid.md +99 -0
- package/docs/rules/missing-slot-marker.md +140 -0
- package/docs/rules/no-bare-css-import.md +128 -0
- package/docs/rules/no-client-directive-in-contract.md +111 -0
- package/docs/rules/no-client-runtime-in-server.md +143 -0
- package/docs/rules/no-css-import-from-render-path.md +118 -0
- package/docs/rules/no-hex.md +163 -0
- package/docs/rules/no-inline-style.md +121 -0
- package/docs/rules/no-nondeterminism.md +100 -0
- package/docs/rules/no-raw-element.md +100 -0
- package/docs/rules/no-templates.md +87 -0
- package/docs/rules/parse-error.md +76 -0
- package/docs/rules/props-from-schema.md +119 -0
- package/docs/rules/render-invariant.md +165 -0
- package/docs/rules/schema-invalid.md +96 -0
- package/docs/rules/serializable-island-props.md +146 -0
- package/docs/rules/server-vs-client.md +105 -0
- package/docs/rules/sidebar-order.md +109 -0
- package/docs/rules/single-react.md +97 -0
- package/docs/rules/size-renderer-bundle.md +109 -0
- package/docs/rules/size-section-css.md +95 -0
- package/docs/rules/slot-group-marker.md +127 -0
- package/docs/rules/slot-marker-literal.md +148 -0
- package/docs/rules/typecheck.md +103 -0
- package/docs/rules/unlayered-fence.md +113 -0
- package/docs/theme-and-css.md +193 -82
- package/package.json +4 -9
- package/tsconfig.json +1 -1
package/docs/theme-and-css.md
CHANGED
|
@@ -1,119 +1,231 @@
|
|
|
1
1
|
---
|
|
2
|
-
purpose: The kit's two CSS entries,
|
|
2
|
+
purpose: The kit's two CSS entries, how a section's own CSS reaches the page, the TokenTheme a template supplies, and the breakpoint ladder.
|
|
3
3
|
status: living
|
|
4
|
-
related: [primitives.md, schema-system.md, eslint.md]
|
|
5
|
-
updated: 2026-07-
|
|
4
|
+
related: [primitives.md, schema-system.md, eslint.md, rules/INDEX.md, check.md]
|
|
5
|
+
updated: 2026-07-15
|
|
6
6
|
---
|
|
7
7
|
# Theme and CSS
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
`
|
|
9
|
+
Your template owns its design system end to end — **the token names included**. You
|
|
10
|
+
declare the tokens your design actually has in a `TokenTheme`, and `template-kit theme`
|
|
11
|
+
compiles that one declaration into the Tailwind utilities that expose them. Declare a
|
|
12
|
+
colour named `lagoon` and `bg-lagoon` exists.
|
|
13
|
+
|
|
14
|
+
The kit owns only what is true of **every** template: the breakpoint ladder, the spacing
|
|
15
|
+
base unit, the motion defaults, the reset gaps Tailwind's preflight leaves, and the
|
|
16
|
+
section box model. It ships no colour, font, type, radius or shadow of its own, and there
|
|
17
|
+
is no shared file for you to edit to make a token of yours usable.
|
|
13
18
|
|
|
14
19
|
Two CSS entries ship, and they are not interchangeable.
|
|
15
20
|
|
|
16
21
|
| Entry | What it is | How it loads |
|
|
17
22
|
|---|---|---|
|
|
18
|
-
| `@homepages/template-kit/styles.css` | The Tailwind
|
|
19
|
-
| `@homepages/template-kit/base.css` | Cascade-layer order, the reset
|
|
23
|
+
| `@homepages/template-kit/styles.css` | The global Tailwind preamble: breakpoint ladder, `--spacing`, motion defaults, and `@source` registration of the kit's compiled JS | imported into **your Tailwind entry**, after Tailwind |
|
|
24
|
+
| `@homepages/template-kit/base.css` | Cascade-layer order, the three reset gaps Tailwind's preflight leaves, `.tr-section`, `.tr-image-frame`, and the motion tokens | its **own stylesheet** on the page — not part of the Tailwind entry |
|
|
20
25
|
|
|
21
|
-
##
|
|
26
|
+
## Your Tailwind entry
|
|
22
27
|
|
|
23
28
|
```css
|
|
24
29
|
/* your CSS entry */
|
|
25
30
|
@import "tailwindcss";
|
|
26
31
|
@import "@homepages/template-kit/styles.css";
|
|
32
|
+
@import "./theme.css"; /* generated by `template-kit theme` from theme.ts */
|
|
27
33
|
```
|
|
28
34
|
|
|
29
|
-
|
|
30
|
-
`@import "tailwindcss"` may exist per build graph — yours. Two double-emit Tailwind's
|
|
31
|
-
preflight reset (`box-sizing` declared twice, several KB of duplicate base layer), and
|
|
32
|
-
nothing errors to tell you.
|
|
35
|
+
Three constraints, all of them silent when broken:
|
|
33
36
|
|
|
34
|
-
|
|
35
|
-
`
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
`@
|
|
37
|
+
- **Import Tailwind exactly once per build graph.** `styles.css` deliberately does not
|
|
38
|
+
`@import "tailwindcss"` itself — yours does. Two double-emit Tailwind's preflight reset
|
|
39
|
+
(`box-sizing` declared twice, several KB of duplicate base layer), and nothing errors.
|
|
40
|
+
- **Your generated theme must be imported here, inside the Tailwind build graph.** It
|
|
41
|
+
contains an `@theme` block, which is a Tailwind directive: anywhere outside the graph it
|
|
42
|
+
is inert, and you get a stylesheet with no token utilities and no error explaining why.
|
|
43
|
+
- **Import it after `styles.css`**, so the kit's globals are in place before your tokens
|
|
44
|
+
land on top of them.
|
|
39
45
|
|
|
40
|
-
|
|
46
|
+
`styles.css` also carries an `@source` line registering the kit's own shipped `dist` for
|
|
47
|
+
Tailwind's class scan. That is how the utility classes baked into the kit's primitives
|
|
48
|
+
(`Image`'s `object-cover`, …) reach your compiled CSS; it also overrides Tailwind's default
|
|
49
|
+
exclusion of `node_modules`. You do not need to add a `@source` for the kit yourself.
|
|
41
50
|
|
|
42
|
-
|
|
51
|
+
## `TokenTheme` — your template's design system
|
|
43
52
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
53
|
+
A template's `theme.ts` exports a `TokenTheme`: six open records of tokens, plus the
|
|
54
|
+
document defaults that dress the page. `theme.ts` is the file you write; run
|
|
55
|
+
`template-kit theme` to compile it into the `theme.css` your Tailwind entry imports
|
|
56
|
+
(see [Generating `theme.css`](#generating-themecss) below).
|
|
48
57
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
must be present on the page too. The layer order it declares is:
|
|
58
|
+
```ts
|
|
59
|
+
import type { TokenTheme } from "@homepages/template-kit";
|
|
52
60
|
|
|
53
|
-
|
|
54
|
-
|
|
61
|
+
export const theme: TokenTheme = {
|
|
62
|
+
colors: { ink: "#111418", page: "#ffffff", "surface-alt": "#f4f4f5", lagoon: "#1c6e7d" },
|
|
63
|
+
fonts: { sans: '"Inter", system-ui, sans-serif', display: '"Canela", Georgia, serif' },
|
|
64
|
+
type: { base: "1rem", "2xl": "1.5rem", display: "clamp(2.5rem, 6vw, 4.5rem)" },
|
|
65
|
+
radii: { md: "6px", pill: "9999px" },
|
|
66
|
+
shadows: { card: "0 1px 2px rgb(0 0 0 / 0.06)" },
|
|
67
|
+
layout: { "container-max": "1280px", "header-height": "72px" },
|
|
68
|
+
|
|
69
|
+
// Optional font-loading block, emitted ahead of everything else.
|
|
70
|
+
fontFaces: '@import url("https://fonts.example/inter.css");',
|
|
71
|
+
|
|
72
|
+
// Which of YOUR tokens dress the document.
|
|
73
|
+
document: { font: "sans", color: "ink", background: "page", fontSize: "base" },
|
|
74
|
+
};
|
|
55
75
|
```
|
|
56
76
|
|
|
57
|
-
|
|
77
|
+
Nothing is required to exist. Tailwind's own defaults survive underneath your tokens —
|
|
78
|
+
`text-2xl`, `rounded-lg`, `red-500` all still work — so a sparse theme is a working theme.
|
|
79
|
+
(The breakpoint ladder is the one exception: `sm:`, `xl:` and `2xl:` are deliberately
|
|
80
|
+
switched off. See below.)
|
|
58
81
|
|
|
59
|
-
|
|
82
|
+
### Namespaces and the utilities they produce
|
|
60
83
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
84
|
+
Each record maps to one Tailwind theme namespace. A token's key is emitted **verbatim**
|
|
85
|
+
into both the custom property and the utility — no camelCase-to-kebab transform, so what
|
|
86
|
+
you type is what you get.
|
|
64
87
|
|
|
65
|
-
|
|
66
|
-
|
|
88
|
+
| Record | Custom property | Tailwind utilities | Example |
|
|
89
|
+
|---|---|---|---|
|
|
90
|
+
| `colors` | `--tr-color-<name>` | `bg-`, `text-`, `border-`, `ring-`, `fill-`, `stroke-`, … | `lagoon` → `bg-lagoon` |
|
|
91
|
+
| `fonts` | `--tr-font-<name>` | `font-<name>` | `display` → `font-display` |
|
|
92
|
+
| `type` | `--tr-text-<name>` | `text-<name>` | `2xl` → `text-2xl` |
|
|
93
|
+
| `radii` | `--tr-radius-<name>` | `rounded-<name>` | `pill` → `rounded-pill` |
|
|
94
|
+
| `shadows` | `--tr-shadow-<name>` | `shadow-<name>` | `card` → `shadow-card` |
|
|
95
|
+
| `layout` | `--tr-<name>` | *(none)* | `header-height` → `var(--tr-header-height)` |
|
|
67
96
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
97
|
+
`layout` has no Tailwind utility namespace, so its tokens get a `--tr-*` value and no
|
|
98
|
+
utility — reference them with `var()` from your own CSS.
|
|
99
|
+
|
|
100
|
+
### Token names
|
|
101
|
+
|
|
102
|
+
Kebab-case: `[a-z0-9]` groups separated by single hyphens (`ink`, `ink-soft`, `bp2`).
|
|
103
|
+
`TokenNameSchema` is exported if you want to validate names yourself.
|
|
104
|
+
|
|
105
|
+
**One token, one utility.** Two utility names cannot share a token — if you want both
|
|
106
|
+
`bg-brand` and `bg-primary`, declare both.
|
|
107
|
+
|
|
108
|
+
### The `document` block
|
|
109
|
+
|
|
110
|
+
Required. It names which of your **own** tokens dress the page — the `body` font-family,
|
|
111
|
+
colour, background, and font-size. `font` and `fontSize` resolve against `fonts` and
|
|
112
|
+
`type`; `color` and `background` resolve against `colors`.
|
|
113
|
+
|
|
114
|
+
Every reference is validated against your declared tokens, in its own group: a typo, or a
|
|
115
|
+
colour name where a font belongs, fails at parse rather than rendering an unthemed page in
|
|
116
|
+
silence.
|
|
83
117
|
|
|
84
|
-
|
|
118
|
+
### Validation
|
|
119
|
+
|
|
120
|
+
`TokenThemeSchema` validates the object at runtime, and it is `.strict()` — an unknown
|
|
121
|
+
top-level key is an error rather than a silently-dead set of tokens.
|
|
122
|
+
|
|
123
|
+
## Generating `theme.css`
|
|
124
|
+
|
|
125
|
+
`template-kit theme` loads `templates/<key>/theme.ts`, validates its `theme` export
|
|
126
|
+
against `TokenThemeSchema`, and writes `templates/<key>/theme.css` — the file your
|
|
127
|
+
Tailwind entry imports.
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
template-kit theme # infer the template from cwd, or the workspace's one template
|
|
131
|
+
template-kit theme <template> # generate one named template's theme.css, by its key
|
|
132
|
+
template-kit theme --all # generate every template in the workspace
|
|
85
133
|
```
|
|
86
134
|
|
|
87
|
-
`
|
|
88
|
-
|
|
89
|
-
|
|
135
|
+
`theme.css` is generated — it opens with a header saying so, and it is not meant to be
|
|
136
|
+
hand-edited. Re-run `template-kit theme` after changing `theme.ts` and commit the
|
|
137
|
+
regenerated file alongside it.
|
|
138
|
+
|
|
139
|
+
A missing `theme.ts`, a `theme.ts` that doesn't export `theme`, or a `theme` that fails
|
|
140
|
+
`TokenThemeSchema` all fail the command with a message naming the file and the problem —
|
|
141
|
+
nothing is written in that case.
|
|
142
|
+
|
|
143
|
+
In order, the file it writes contains:
|
|
144
|
+
|
|
145
|
+
1. your `fontFaces` block, if you set one;
|
|
146
|
+
2. `@theme inline { --color-<name>: var(--tr-color-<name>); … }` — the alias layer, which
|
|
147
|
+
is what brings your token utilities into existence;
|
|
148
|
+
3. `:root { --tr-color-<name>: <value>; … }` — the values behind those aliases;
|
|
149
|
+
4. `body { … }` — your `document` defaults, written as `var()` indirections so a runtime
|
|
150
|
+
`:root` override still cascades to the page.
|
|
151
|
+
|
|
152
|
+
Deterministic: keys are sorted, so the same theme always content-hashes identically.
|
|
153
|
+
|
|
154
|
+
## Colour in sections
|
|
155
|
+
|
|
156
|
+
A section carries no palette of its own, in server-rendered code or inside an island — the
|
|
157
|
+
`template-kit/no-hex` [lint rule](rules/no-hex.md) flags a hard-coded hex literal in a
|
|
158
|
+
colour context, and a CSS colour function anywhere, without exempting `"use client"` files
|
|
159
|
+
the way most of the preset's other rules do. Sections spend the theme's tokens; the theme
|
|
160
|
+
is where a colour is named.
|
|
161
|
+
|
|
162
|
+
For a colour the theme does not name — a hover, active, or pressed step, or a translucent
|
|
163
|
+
tint — derive it from the tokens that *are* named, with a `color-mix()` over theme-derived
|
|
164
|
+
arguments:
|
|
165
|
+
`hover:bg-[color-mix(in_srgb,var(--tr-color-primary)_80%,var(--tr-color-surface))]`. Such a
|
|
166
|
+
mix composes a colour out of the theme rather than stating one, and is the single colour
|
|
167
|
+
function `no-hex` allows — it carves out no other.
|
|
168
|
+
|
|
169
|
+
## How a section's CSS reaches the page
|
|
170
|
+
|
|
171
|
+
A section's compiled CSS layer is assembled from two sources, both automatic — you
|
|
172
|
+
never write an import to make either happen:
|
|
173
|
+
|
|
174
|
+
1. **Hand-written CSS, collected by path.** Every `.css` file inside the section's
|
|
175
|
+
folder — `styles.css` and any other stylesheet nested under it — is picked up by
|
|
176
|
+
walking the folder, wherever it sits, and concatenated into `@layer sections`. A
|
|
177
|
+
template's own hand-written stylesheet is collected the same way, into
|
|
178
|
+
`@layer template`.
|
|
179
|
+
2. **Package CSS, harvested from the render path.** The build also bundles
|
|
180
|
+
`Renderer.tsx`'s module graph — and any component that carries `export const
|
|
181
|
+
enhancer` — and pulls in whatever `.css` those imports resolve to. A bare specifier
|
|
182
|
+
(`import "swiper/css";`) resolves into `node_modules` and lands in the same
|
|
183
|
+
`@layer sections`; that is the sanctioned way for a third-party package's
|
|
184
|
+
stylesheet to reach the page.
|
|
185
|
+
|
|
186
|
+
Two constraints follow directly, and both are enforced by lint:
|
|
187
|
+
|
|
188
|
+
- **Don't re-import your own stylesheet.** It is already collected by path —
|
|
189
|
+
importing it again from a `.ts`/`.tsx` file only double-emits it, and can smuggle a
|
|
190
|
+
stray `@layer` statement into a nested layer.
|
|
191
|
+
See [`no-css-import-from-render-path`](rules/no-css-import-from-render-path.md).
|
|
192
|
+
- **`@import` never works inside hand-written CSS, package or local.** An `@import`
|
|
193
|
+
landing inside `@layer sections` / `@layer template` is invalid CSS, and the
|
|
194
|
+
browser drops it silently rather than erroring — the package's styling is simply
|
|
195
|
+
missing from the published page. Reach a package's stylesheet from code instead.
|
|
196
|
+
See [`no-bare-css-import`](rules/no-bare-css-import.md).
|
|
90
197
|
|
|
91
|
-
|
|
198
|
+
## The page's stylesheets
|
|
92
199
|
|
|
93
|
-
|
|
94
|
-
utility is named after **the variable**, not the role key — so `surfaceAlt` is
|
|
95
|
-
`bg-surface-alt`, and `primaryStrong` is `bg-primary-darker`. Read the mapping off the
|
|
96
|
-
exported `COLOR_ROLE_VARS` (and `FONT_ROLE_VARS`, `TYPE_STEP_VARS`, `RADIUS_VARS`,
|
|
97
|
-
`SHADOW_VARS`, `LAYOUT_VARS` for the other scales), or let your editor autocomplete the
|
|
98
|
-
`ColorRole` union:
|
|
200
|
+
A published page loads, in order:
|
|
99
201
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
202
|
+
1. **`base.css`** — layer order, the reset gaps, `.tr-section`, `.tr-image-frame`, motion
|
|
203
|
+
tokens.
|
|
204
|
+
2. **Your compiled Tailwind bundle** — your entry: `@import "tailwindcss"` + the kit's
|
|
205
|
+
`styles.css` + your compiled theme + the utilities your section markup uses.
|
|
206
|
+
|
|
207
|
+
The layer order `base.css` declares is:
|
|
208
|
+
|
|
209
|
+
```css
|
|
210
|
+
@layer theme, base, components, sections, template, utilities;
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
Utilities come last, so a Tailwind utility always beats the reset's element defaults.
|
|
214
|
+
|
|
215
|
+
### base.css requires a Tailwind entry
|
|
216
|
+
|
|
217
|
+
`base.css` does **not** ship a reset. Your entry's `@import "tailwindcss"` brings
|
|
218
|
+
Tailwind's preflight, and preflight is the reset — box-sizing, margins, list-style, the
|
|
219
|
+
button and anchor resets. `base.css` carries only the three declarations preflight does
|
|
220
|
+
not make: `font-smoothing`, `button { cursor: pointer }` (Tailwind v4 leaves buttons at
|
|
221
|
+
`cursor: default`), and `svg { max-width: 100% }` (preflight caps only `img` and
|
|
222
|
+
`video`).
|
|
223
|
+
|
|
224
|
+
Ship `base.css` without a Tailwind entry on the page and you get an unreset page.
|
|
225
|
+
|
|
226
|
+
`base.css` references **no design token of yours** — nothing global is opinionated about
|
|
227
|
+
your brand. Its one tintable surface is the `Image` frame's placeholder fill; see
|
|
228
|
+
[`Image`](primitives.md#image--the-defensive-image-primitive).
|
|
117
229
|
|
|
118
230
|
## The breakpoint ladder
|
|
119
231
|
|
|
@@ -145,8 +257,7 @@ memory — enough to make it evict a live WebGL map's layer on scroll, blanking
|
|
|
145
257
|
they stop consuming that memory.
|
|
146
258
|
|
|
147
259
|
The kit does **not** apply this for you — it has a real cost (below), and only you know
|
|
148
|
-
whether your page needs it. If it does, add the rule to
|
|
149
|
-
`@import "tailwindcss"; @import "@homepages/template-kit/styles.css";` — the third
|
|
260
|
+
whether your page needs it. If it does, add the rule to your Tailwind entry — the second
|
|
150
261
|
stylesheet the page loads:
|
|
151
262
|
|
|
152
263
|
```css
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@homepages/template-kit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Authoring kit for HomePages marketing-section templates: schema system, contract primitives, theme tokens, and the template-kit CLI.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"type": "module",
|
|
@@ -58,6 +58,7 @@
|
|
|
58
58
|
"build": "tsdown",
|
|
59
59
|
"typecheck": "tsc --noEmit",
|
|
60
60
|
"lint": "eslint .",
|
|
61
|
+
"pretest": "node test/link-fixture-workspace.mjs",
|
|
61
62
|
"test": "node --import tsx --test 'src/**/*.test.ts' 'src/**/*.test.tsx'",
|
|
62
63
|
"lint:pkg": "publint --strict && attw --pack . --profile esm-only --exclude-entrypoints styles.css base.css",
|
|
63
64
|
"verify:consumer": "node scripts/verify-consumer.mjs",
|
|
@@ -67,15 +68,9 @@
|
|
|
67
68
|
"release": "changeset publish"
|
|
68
69
|
},
|
|
69
70
|
"peerDependencies": {
|
|
70
|
-
"eslint": "^9.0.0",
|
|
71
71
|
"react": "^19.0.0",
|
|
72
72
|
"react-dom": "^19.0.0"
|
|
73
73
|
},
|
|
74
|
-
"peerDependenciesMeta": {
|
|
75
|
-
"eslint": {
|
|
76
|
-
"optional": true
|
|
77
|
-
}
|
|
78
|
-
},
|
|
79
74
|
"devDependencies": {
|
|
80
75
|
"@arethetypeswrong/cli": "^0.18.5",
|
|
81
76
|
"@changesets/cli": "^2.29.8",
|
|
@@ -85,6 +80,7 @@
|
|
|
85
80
|
"@types/node": "^20.17.10",
|
|
86
81
|
"@types/react": "^19.0.0",
|
|
87
82
|
"@types/react-dom": "^19.0.0",
|
|
83
|
+
"@typescript-eslint/parser": "^8.60.1",
|
|
88
84
|
"esbuild": "^0.28.1",
|
|
89
85
|
"eslint": "^9.39.4",
|
|
90
86
|
"jsdom": "^26.1.0",
|
|
@@ -98,7 +94,6 @@
|
|
|
98
94
|
"typescript-eslint": "^8.60.1"
|
|
99
95
|
},
|
|
100
96
|
"dependencies": {
|
|
101
|
-
"
|
|
102
|
-
"zod": "^3.23.8"
|
|
97
|
+
"zod": "^4.4.3"
|
|
103
98
|
}
|
|
104
99
|
}
|
package/tsconfig.json
CHANGED