@getvitops/cli 4.1.0 → 6.0.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@getvitops/cli",
3
- "version": "4.1.0",
3
+ "version": "6.0.0",
4
4
  "description": "CLI for the Vitops design-system generator: generate, init, and validate a design-system.json.",
5
5
  "license": "MIT",
6
6
  "bin": {
@@ -22,8 +22,8 @@
22
22
  "access": "public"
23
23
  },
24
24
  "dependencies": {
25
- "@getvitops/generator": "4.1.0",
26
- "@getvitops/utils": "4.1.0"
25
+ "@getvitops/generator": "6.0.0",
26
+ "@getvitops/utils": "6.0.0"
27
27
  },
28
28
  "devDependencies": {
29
29
  "vitest": "^4.1.9"
package/skill/SKILL.md CHANGED
@@ -22,6 +22,83 @@ colour roles, fluid type/space scales, component patterns, animation effects).
22
22
  **Core rule:** prefer the framework's utility + component classes over hand-written CSS or
23
23
  ad-hoc values — they encode the tokens, respond to dark mode, and update with the system.
24
24
 
25
+ ## Layout foundations — apply these before fetching anything
26
+
27
+ Six classes carry the structure of nearly every page. They are stated here rather than
28
+ left to `vitops docs classes` because the failure mode is not disagreement, it is **not
29
+ knowing there was a decision to make** — writing a container by hand looks like ordinary
30
+ CSS competence, so nothing prompts you to go look. Every row below has been found in real
31
+ downstream sites.
32
+
33
+ | About to write… | Write this instead |
34
+ | ------------------------------------------------------- | ----------------------------------------------- |
35
+ | a `wrap` / `wrapper` / `container` / `inner` class | **`centered`** — never invent a container class |
36
+ | `max-width` + `margin-inline: auto` | **`centered`** |
37
+ | `padding-block` on a section to separate it | **`region`** |
38
+ | margins between headings, paragraphs, lists | **`rhythm`** on the container |
39
+ | `display: grid` + `grid-template-columns: repeat(n, …)` | **`subgrid`** |
40
+ | `repeat(auto-fit, minmax(…))` | **`grid-auto`** (or `subgrid`, below) |
41
+ | `display: flex` + `gap` for a row of buttons/badges | **`cluster`** |
42
+
43
+ **`centered` is not a max-width box, which is why hand-rolling it never quite works.** It is
44
+ a grid of _named tracks_, so a child widens itself (`breakout`, `spotlight`, `fullbleed`)
45
+ without the parent knowing. A bespoke `.wrap` renders identically until the first full-bleed
46
+ image, and then the only way out is more hand-written CSS. There is no case where inventing a
47
+ container class is correct.
48
+
49
+ **More than one card means `subgrid`.** This is the most under-used class in the framework,
50
+ and the reason it gets skipped is that a plain `grid` _looks_ right — it aligns the outer
51
+ boxes. It cannot align the tranches **inside** them, so across three cards the headings sit
52
+ at three heights, the bodies start at three points, and the CTAs float wherever the copy
53
+ ended. `subgrid` re-declares the parent's row tracks on each item so head / body / footer
54
+ share row lines regardless of content length. Write
55
+ `<ul class="subgrid subgrid-cols-3" role="list">` with `<li class="card subgrid-card">` items —
56
+ a set of cards is a list — and set `--subgrid-row-span` (or `subgrid-rows-<n>`) to the number of
57
+ row bands each card holds. In Astro use `<Subgrid />`, which renders the slot verbatim: **author
58
+ the `<li>` items yourself.**
59
+
60
+ **`role="list"` is not optional on a hand-written one.** `subgrid` is markerless on `ul`/`ol`,
61
+ and Safari + VoiceOver stop announcing a marker-less `<ul>` as a list — so the marker reset
62
+ silently costs the semantics the `<ul>` was chosen for. `<Subgrid />` adds it for you.
63
+
64
+ **When the whole card is a link, the card is still the grid item** — and there are two ways to
65
+ do it, both keeping the accessible name on real text rather than on a whole card of it:
66
+
67
+ | Want | Use |
68
+ | ------------------------------------ | ------------------------------------------ |
69
+ | no JS at all | `stretched-link` — **text not selectable** |
70
+ | selectable text and a clickable card | `<Cards>` / `<wc-cards>` — needs JS |
71
+
72
+ - `stretched-link` goes on a link **inside** the card (usually the heading); its `::after`
73
+ covers it. `subgrid-card` already carries the required `position: relative`; on a bare `card`
74
+ add `relative`. Anything else interactive in the card needs **`raised`** — `relative` alone
75
+ does not work, because a positioned element at `z-index: auto` cannot rise above an explicit
76
+ one. The cost is inherent to the technique: the overlay takes the pointer-drag, so the card's
77
+ text can no longer be selected.
78
+ - `<Cards>` wraps the list in `<wc-cards>`, which adds no overlay and instead distinguishes a
79
+ click from the end of a drag. Text stays selectable; with no JS the card's own link still
80
+ works, and the pointer cursor appears only once the element upgrades. It emits its own
81
+ `<wc-cards>` — do not add your own wrapper.
82
+ - **Never layer the two.** The overlay wins, so you lose selection _and_ the JS never runs.
83
+ `vitops lint` reports the combination.
84
+
85
+ `<li><a class="card">` is the wrong shape and **it renders fine**, which is why it keeps being
86
+ written: the `<li>` is the grid item, so the anchor is an ordinary block inside it and the
87
+ tranches within the anchor never reach the parent's shared row lines — the alignment is
88
+ silently absent, and the anchor does not fill the cell either. Putting the anchor in the
89
+ grid's place (`<ul><a></ul>`) is invalid HTML. `vitops lint` reports this shape.
90
+
91
+ The one honest alternative is **`grid-auto`** — an auto-fit track (`--grid-min`, `--grid-gap`)
92
+ for items with **no internal tranches to align**: a gallery, a logo wall, a row of icons. Never
93
+ hand-write `repeat(auto-fit, minmax(…))`; that is `grid-auto`. The moment an item has an
94
+ eyebrow and a heading and a footer, `subgrid` is the one that lines them up.
95
+
96
+ **`vitops lint` reports all six of these**, in CSS, in `<style>` blocks and in markup — a
97
+ hand-rolled container, a repeated-item grid, and a loop that renders cards outside a
98
+ `subgrid`. They report as `suggestion`, so they do not fail the build unless `--strict`.
99
+ Run it before considering a page done; if it names one of these, the fix is the class, not a
100
+ justification for the CSS.
101
+
25
102
  ## Getting the current reference docs
26
103
 
27
104
  Run **`vitops docs <topic>`** — it prints the reference as markdown to stdout, generated
@@ -56,7 +133,17 @@ never stale and always names the project's actual tokens. (If `vitops` isn't on
56
133
  emits no CSS, so it composes: `--format css,design`. The live reference above is
57
134
  richer; DESIGN.md is for handing the identity to a tool that doesn't have this skill.
58
135
  - `vitops init` / `vitops validate` — scaffold / check a config. `validate` routes on the
59
- file's shape, so it checks a site config as a site config.
136
+ file's shape, so it checks a site config as a site config. It also resolves every
137
+ `var(--…)` the config authors against the tokens it emits, so a reference to a token
138
+ that does not exist is a build failure rather than a declaration that silently does
139
+ nothing.
140
+ - `vitops lint [--src <dir>] [--fix]` — **run this after a major bump.** It finds
141
+ framework classes and design-system tokens in your source that resolve to nothing, and
142
+ it is the migration tool for anything the changelog says was renamed. `--fix` rewrites
143
+ pre-1.0 colour-grammar token references in one pass (several of those renames rotate, so
144
+ applying them one at a time compounds them); everything else it reports needs a decision
145
+ and is left alone.
146
+ - Every subcommand takes `-h` / `--help`.
60
147
 
61
148
  **The config may be a `design-system.json` or the site config that embeds one.** Every
62
149
  `--input` (and the Vite plugin / Astro integration equivalent) accepts either; a site
@@ -66,10 +153,15 @@ there — do not create a second file for the tooling's sake.
66
153
 
67
154
  ## Which tier provides a pattern
68
155
 
69
- A pattern (tree, carousel, dialog, card, …) may be provided by up to four tiers, and they
70
- **compose** rather than compete: CSS framework classes, a `<wc-*>` web component, an Astro
71
- component, a Bricks element. **Run `vitops docs components`** for the full table — which
72
- tiers each pattern has, and the exact call to write.
156
+ A pattern (tree, carousel, dialog, card, …) may be provided by up to **three tiers**, and they
157
+ **compose** rather than compete: (1) CSS framework classes, (2) a `<wc-*>` web component,
158
+ (3) a platform wrapper that generates the markup — an Astro component or a Bricks element.
159
+ **Run `vitops docs components`** for the full table — which tiers each pattern has, and the
160
+ exact call to write.
161
+
162
+ **Astro and Bricks are the same tier, not tiers 3 and 4.** Both are HTML generators built on
163
+ the classes and elements of tiers 1 and 2 — siblings chosen by which platform you are on. No
164
+ project uses both, and neither outranks the other.
73
165
 
74
166
  Three things to know before you write markup:
75
167
 
@@ -83,6 +175,30 @@ Three things to know before you write markup:
83
175
  HTML is the no-JS fallback and must be semantic and usable on its own. If you find yourself
84
176
  wanting a component that renders from nothing, that pattern is in the wrong tier.
85
177
 
178
+ ## Astro rendering mode
179
+
180
+ Nothing vitops emits needs a server — the CSS, favicons and web-component bundles are
181
+ build-time artifacts, and the components progressively enhance markup that is already
182
+ complete in the HTML. So the default is static, and the rule differs by project kind:
183
+
184
+ - **A plain Astro site:** keep `output: 'static'` and add `export const prerender = false`
185
+ only on the individual routes that genuinely need per-request work (a form `POST` handler,
186
+ an auth-gated page, per-visitor content). Don't switch the whole site to `output: 'server'`
187
+ for a couple of dynamic routes.
188
+ - **An EmDash site:** `output: 'server'` is required (the admin, media/API routes, preview
189
+ and scheduled publishing all need a server), so prerendering is opt-in per route. Put
190
+ `export const prerender = true` on every page that doesn't need per-request data, and give
191
+ dynamic routes (`[slug].astro`, `[...slug].astro`) a `getStaticPaths()` that queries the
192
+ collection at build time. A route with no `prerender` export is re-rendered on every
193
+ request.
194
+
195
+ A prerendered page reflects the database as of the last build, so publishing from the admin
196
+ needs a redeploy to appear. Leave a route server-rendered only where that is unacceptable —
197
+ the preview route, anything personalised, anything that must go live within seconds.
198
+
199
+ Note `@astrojs/sitemap` lists prerendered routes only, so an unmarked route on a server site
200
+ is also missing from the sitemap. (EmDash serves its own sitemap from the database.)
201
+
86
202
  ## Fonts: vitops names them, it does not load them
87
203
 
88
204
  `design-system.json`'s `fonts` block holds **stacks only** — each entry emits a