@radicool/throughline 0.14.0 → 0.16.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/README.md +2 -1
- package/adapters/codex/AGENTS.md +10 -10
- package/adapters/codex/prompts/component-builder.md +59 -15
- package/adapters/codex/prompts/document-component.md +42 -10
- package/adapters/codex/prompts/storybook-chromatic-builder.md +52 -9
- package/adapters/codex/prompts/token-crosswalk-builder.md +2 -0
- package/adapters/codex/prompts/token-sync-layer.md +64 -4
- package/adapters/cursor/.cursor/commands/document-component.md +42 -10
- package/adapters/cursor/.cursor/rules/component-builder.mdc +60 -16
- package/adapters/cursor/.cursor/rules/component-pipeline.mdc +1 -1
- package/adapters/cursor/.cursor/rules/design-system-audit.mdc +1 -1
- package/adapters/cursor/.cursor/rules/figma-environment-setup.mdc +1 -1
- package/adapters/cursor/.cursor/rules/icon-system-builder.mdc +1 -1
- package/adapters/cursor/.cursor/rules/repository-builder.mdc +1 -1
- package/adapters/cursor/.cursor/rules/retrofit-planner.mdc +1 -1
- package/adapters/cursor/.cursor/rules/storybook-chromatic-builder.mdc +53 -10
- package/adapters/cursor/.cursor/rules/token-builder.mdc +1 -1
- package/adapters/cursor/.cursor/rules/token-crosswalk-builder.mdc +3 -1
- package/adapters/cursor/.cursor/rules/token-sheet-builder.mdc +1 -1
- package/adapters/cursor/.cursor/rules/token-sync-layer.mdc +65 -5
- package/adapters/generic/AGENTS.md +10 -10
- package/adapters/generic/commands/document-component.md +42 -10
- package/adapters/generic/skills/component-builder/SKILL.md +59 -15
- package/adapters/generic/skills/storybook-chromatic-builder/SKILL.md +52 -9
- package/adapters/generic/skills/token-crosswalk-builder/SKILL.md +2 -0
- package/adapters/generic/skills/token-sync-layer/SKILL.md +64 -4
- package/package.json +1 -1
- package/references/component-doc-archetypes.md +15 -11
- package/references/component-doc-schema.md +23 -5
- package/references/doc-card-builder.md +565 -0
- package/references/doc-writing-standard.md +144 -0
- package/references/figma-component-standards.md +63 -16
- package/references/guide-voice.md +96 -0
- package/references/manifest-schema.md +24 -6
- package/references/native-adapter-config.md +930 -0
- package/references/sync-adapters.md +94 -12
- package/scripts/README.md +37 -3
- package/scripts/build-doc-card-builder.mjs +143 -0
- package/scripts/build-native-adapter-config.mjs +280 -0
- package/scripts/docs-check.mjs +18 -4
- package/scripts/docs-lint.mjs +163 -0
- package/scripts/install.mjs +14 -1
- package/scripts/lib/doc-card-plan.mjs +101 -0
- package/scripts/lib/doc-card-render.figma.js +371 -0
- package/scripts/lib/dtcg.mjs +87 -0
- package/scripts/lib/native-literal.mjs +205 -0
- package/scripts/lib/sd-native.mjs +770 -0
- package/scripts/validate-crosswalk.mjs +3 -29
- package/scripts/validate-token-output.mjs +338 -0
package/README.md
CHANGED
|
@@ -205,7 +205,8 @@ Future improvements and planned capabilities. Have a request? **[Open an issue](
|
|
|
205
205
|
- **Expanded component starters** — a larger foundational kit out of the box.
|
|
206
206
|
- **Richer status & auditing** — more from `/design-system-status`, including drift detection between Figma and code.
|
|
207
207
|
- **Built-in accessibility checks** — automatic a11y validation when tokens and components are created, so modes can't be built with poor color contrast and components can't ship with accessibility gaps. Catches issues at creation time rather than in review.
|
|
208
|
-
- **
|
|
208
|
+
- **Token fan-out to more platforms** — the DTCG token source is platform-neutral, and web targets are in daily use. Native targets are **validated per build, not assumed** — iOS/Swift is a curated adapter whose Style Dictionary configuration ships as tested code, and Android/Kotlin uses the same configuration through the Tier 2 protocol — `tokens:validate-output` checks generated native output against its source, because the stock transforms have been measured emitting wrong-but-compiling values.
|
|
209
|
+
- **Native component code generation** — producing a SwiftUI view or a Compose composable the way Storybook components are produced for React. This does not exist yet; it is a separate, larger effort than token fan-out, and the two were previously described as one roadmap item.
|
|
209
210
|
|
|
210
211
|
Versioning follows [Semantic Versioning](https://semver.org). The current version lives in [`.claude-plugin/plugin.json`](.claude-plugin/plugin.json); every release is recorded in [`CHANGELOG.md`](CHANGELOG.md).
|
|
211
212
|
|
package/adapters/codex/AGENTS.md
CHANGED
|
@@ -4,18 +4,18 @@ ThroughLine builds a design system end to end. Load the matching prompt for the
|
|
|
4
4
|
|
|
5
5
|
## ThroughLine skills
|
|
6
6
|
|
|
7
|
-
- `component-builder` — Build
|
|
7
|
+
- `component-builder` — Build Figma components — buttons, inputs, cards, badges, chips, modals, and more — with variant matrices (types, sizes, states) and icon/component/content slots bound to the design system's tokens and styles. → load `prompts/component-builder.md`.
|
|
8
8
|
- `component-pipeline` — Take a single new component from Figma to fully-built-and-storied code, end to end — build it in Figma, sync any new tokens it introduced, then build its code component and stories. → load `prompts/component-pipeline.md`.
|
|
9
|
-
- `design-system-audit` — Measure a pre-existing design system before retrofitting it onto tokens
|
|
9
|
+
- `design-system-audit` — Measure a pre-existing design system before retrofitting it onto tokens, so the retrofit is right-sized. → load `prompts/design-system-audit.md`.
|
|
10
10
|
- `figma-environment-setup` — Set up the local working folder and connect Codex to Figma so the design-system skills can read and write variables, styles, and components. → load `prompts/figma-environment-setup.md`.
|
|
11
|
-
- `icon-system-builder` — Build an icon system in Figma — a dedicated "Icons" page
|
|
12
|
-
- `repository-builder` — Graduate the local design-system folder into a real monorepo — a pnpm + Turborepo workspace with packages for tokens and UI components
|
|
13
|
-
- `retrofit-planner` — Orchestrate a full brownfield design-system retrofit end to end — audit, refine
|
|
14
|
-
- `storybook-chromatic-builder` — Stand up Storybook in the monorepo, build code components matching the Figma design system
|
|
15
|
-
- `token-builder` — Build a two-tier (primitive + semantic) design token system as Figma variables — color ramps, spacing, type scale, radius, shadows — with light/dark or brand modes. → load `prompts/token-builder.md`.
|
|
16
|
-
- `token-crosswalk-builder` — Build the brownfield token crosswalk — a persistent three-way map between each new token, the old Figma variable, and the old code identifier(s) —
|
|
17
|
-
- `token-sheet-builder` — Build
|
|
18
|
-
- `token-sync-layer` — Sync Figma design variables into code-ready token files
|
|
11
|
+
- `icon-system-builder` — Build an icon system in Figma — a dedicated "Icons" page of well-named, scalable icon components from Lucide, Tabler, Phosphor, Material, or custom SVGs. → load `prompts/icon-system-builder.md`.
|
|
12
|
+
- `repository-builder` — Graduate the local design-system folder into a real monorepo — a pnpm + Turborepo workspace with packages for tokens and UI components — and walk the user from a plain folder to local git to a GitHub remote with PRs and CI. → load `prompts/repository-builder.md`.
|
|
13
|
+
- `retrofit-planner` — Orchestrate a full brownfield design-system retrofit end to end — audit, refine, rebind, sync, baseline, code, docs, cleanup — with a human confirmation gate between every phase. → load `prompts/retrofit-planner.md`.
|
|
14
|
+
- `storybook-chromatic-builder` — Stand up Storybook in the monorepo, build code components matching the Figma design system, generate stories for every component, set up Chromatic for visual regression testing, and wire Code Connect when the user's Figma plan supports it. → load `prompts/storybook-chromatic-builder.md`.
|
|
15
|
+
- `token-builder` — Build a two-tier (primitive + semantic) design token system as Figma variables — color ramps, spacing, type scale, radius, shadows — with light/dark or brand modes, using one collection per category per tier. → load `prompts/token-builder.md`.
|
|
16
|
+
- `token-crosswalk-builder` — Build the brownfield token crosswalk — a persistent three-way map between each new token, the old Figma variable, and the old code identifier(s) — then wire the tokens:validate CI gate. → load `prompts/token-crosswalk-builder.md`.
|
|
17
|
+
- `token-sheet-builder` — Build an on-brand "Foundations" page in Figma that visually documents every variable collection and style — color ramps with swatches, the type scale, spacing, radius, shadows/elevations. → load `prompts/token-sheet-builder.md`.
|
|
18
|
+
- `token-sync-layer` — Sync Figma design variables into code-ready token files via DTCG JSON and Style Dictionary, emitting framework-specific outputs (shadcn/Tailwind, MUI, vanilla CSS, iOS Swift, Android Kotlin, or custom), and set up the reusable "sync figma tokens" command. → load `prompts/token-sync-layer.md`.
|
|
19
19
|
|
|
20
20
|
## ThroughLine commands
|
|
21
21
|
|
|
@@ -236,7 +236,9 @@ Read `.throughline/references/component-doc-schema.md` for the exact JSON
|
|
|
236
236
|
schema, the fingerprint algorithm, and the projection contract.
|
|
237
237
|
|
|
238
238
|
**Run the generation pipeline (each layer only fills what it legitimately knows;
|
|
239
|
-
stamp `provenance` per block):**
|
|
239
|
+
stamp `provenance` per block):** all authored prose follows
|
|
240
|
+
`.throughline/references/doc-writing-standard.md` — its plain
|
|
241
|
+
reference register, not this skill's guide voice.
|
|
240
242
|
|
|
241
243
|
0. **Ingest existing docs — brownfield only, runs first.** If docs already exist
|
|
242
244
|
for this component (code JSDoc/MDX/README, or a populated Figma component
|
|
@@ -255,32 +257,74 @@ stamp `provenance` per block):**
|
|
|
255
257
|
accessibility idiom to the target framework (the same field you read for variant
|
|
256
258
|
vocabulary). Provenance `framework`.
|
|
257
259
|
4. **Interview for the non-inferable.** Ask the user for brand/product-specific
|
|
258
|
-
do's & don'ts and intent. Provenance `user`.
|
|
259
|
-
|
|
260
|
-
|
|
260
|
+
do's & don'ts and intent. Provenance `user`. Write the draft to
|
|
261
|
+
`design-system/docs/components/<Name>.doc.json`, run
|
|
262
|
+
`node .throughline/scripts/docs-lint.mjs design-system/docs/components/<Name>.doc.json`,
|
|
263
|
+
and fix the warnings it raises. Do not raise a separate confirmation for
|
|
264
|
+
a warning on an `imported`/`user` block: draft the rewrite and carry it
|
|
265
|
+
into the approval gate below, shown as before/after and labelled with the
|
|
266
|
+
block's provenance. **Show the whole drafted record and get explicit
|
|
267
|
+
approval before projecting it anywhere** (Figma description, doc card,
|
|
268
|
+
manifest) — one approval covers the whole record. Blocks the user did not
|
|
269
|
+
clear keep their existing text; blocks the user did clear are stamped
|
|
270
|
+
`imported+user` so a later run neither re-asks nor rewrites them.
|
|
261
271
|
|
|
262
272
|
**Write the record and project it:**
|
|
263
273
|
|
|
264
274
|
- Write `design-system/docs/components/<Name>.doc.json` (JSON; required fields
|
|
265
275
|
`name`, `summary`, `description`).
|
|
266
276
|
- **Figma component description.** Set the component's native `description` field
|
|
267
|
-
(via `figma_set_description`)
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
277
|
+
(via `figma_set_description`) from this exact template — this is the surface
|
|
278
|
+
Dev Mode and Code Connect read, and it must be reproducible byte-for-byte by
|
|
279
|
+
any agent from the same record:
|
|
280
|
+
|
|
281
|
+
```
|
|
282
|
+
<summary>
|
|
283
|
+
|
|
284
|
+
**When to use**
|
|
285
|
+
- <whenToUse[n]>
|
|
286
|
+
|
|
287
|
+
**When not to use**
|
|
288
|
+
- <whenNotToUse[n]>
|
|
289
|
+
|
|
290
|
+
**Do**
|
|
291
|
+
- <dos[n]>
|
|
292
|
+
|
|
293
|
+
**Don't**
|
|
294
|
+
- <donts[n]>
|
|
295
|
+
|
|
296
|
+
**Accessibility**
|
|
297
|
+
- <accessibility.keyboard[n]>
|
|
298
|
+
- <accessibility.notes[n]>
|
|
299
|
+
|
|
300
|
+
<!-- tl:doc <fp> -->
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
Rules: every line is a record string **verbatim** — no re-wording, no added
|
|
304
|
+
connectives, no sentences that appear nowhere in the record. A block whose
|
|
305
|
+
source array is empty is omitted along with its bold label. The **Accessibility**
|
|
306
|
+
label is omitted only when both `accessibility.keyboard` and `accessibility.notes`
|
|
307
|
+
are empty; when one is empty its bullets are simply absent and the label stays.
|
|
308
|
+
Sections are separated by exactly one blank line, and the fingerprint marker is
|
|
309
|
+
always last.
|
|
310
|
+
- **Doc card body.** Render the card's `Usage` band with the canonical builder
|
|
311
|
+
snippet in `.throughline/references/doc-card-builder.md` (via
|
|
312
|
+
`figma_execute` with an explicit `timeout`, one card per call): fill the
|
|
313
|
+
RECORD/CANONICAL_FP slots, resolve the nine required semantic variables and
|
|
314
|
+
the `Body/Default` text style per that file's call contract, run it, and
|
|
315
|
+
verify the returned summary (`rowsRendered`, `blocksCreated`, `cardWidth`) —
|
|
316
|
+
not a screenshot. The builder creates the `Doc Fingerprint` node itself and
|
|
317
|
+
is the only thing that may build the usage body — never hand-assemble it.
|
|
276
318
|
- Compute `<fp>` as the canonical fingerprint defined in the schema reference
|
|
277
319
|
(sha256 of the projected record without `provenance`, first 16 hex chars).
|
|
278
320
|
|
|
279
321
|
**Update the manifest (fields this skill owns):** set
|
|
280
322
|
`components.meta[<Name>].doc` to `{ path, fingerprint: <fp>, surfaces: {
|
|
281
323
|
figmaDescription: { src: <fp>, render: <hash of the description text> }, docCard: {
|
|
282
|
-
src: <fp>, render: <
|
|
283
|
-
|
|
324
|
+
src: <fp>, render: <summary.renderHash>, renderer: <summary.rendererVersion> } } }`
|
|
325
|
+
— the docCard entry is stamped from the builder's returned summary, never by
|
|
326
|
+
re-reading the card. The code surfaces (`storybookMdx`) are added later by
|
|
327
|
+
`storybook-chromatic-builder`.
|
|
284
328
|
|
|
285
329
|
Run the standard doc-card visual-validation + post-build audit
|
|
286
330
|
(`.throughline/references/figma-component-standards.md`) after enriching
|
|
@@ -8,17 +8,49 @@ Ask which component to document (e.g. "Button"), then:
|
|
|
8
8
|
the `component-builder` prompt's *Author the documentation record* step —
|
|
9
9
|
ingest any existing docs first (brownfield), then infer → enrich (from
|
|
10
10
|
`.throughline/references/component-doc-archetypes.md`) → specialize →
|
|
11
|
-
interview.
|
|
12
|
-
|
|
11
|
+
interview. Authored prose follows
|
|
12
|
+
`.throughline/references/doc-writing-standard.md`. Set `updatedAt` to
|
|
13
|
+
today's date (ISO, `YYYY-MM-DD`) whenever the record is written or rewritten —
|
|
14
|
+
it is a projected field and the doc card's header renders it. Once the record is
|
|
15
|
+
written, run `node .throughline/scripts/docs-lint.mjs
|
|
16
|
+
design-system/docs/components/<Name>.doc.json` and fix its warnings. Do not
|
|
17
|
+
raise a separate confirmation for a warning on an `imported`/`user` block:
|
|
18
|
+
draft the rewrite and carry it into the approval gate below, shown as
|
|
19
|
+
before/after and labelled with the block's provenance, so one approval covers
|
|
20
|
+
the whole record. The user approves the drafted record before anything is
|
|
21
|
+
projected (Figma description, doc card, manifest). Blocks the user did not
|
|
22
|
+
clear keep their existing text; blocks the user did clear are stamped
|
|
23
|
+
`imported+user` so a later run neither re-asks nor rewrites them.
|
|
13
24
|
2. **Project it.** Write `design-system/docs/components/<Name>.doc.json`, set the
|
|
14
|
-
Figma component `description`,
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
25
|
+
Figma component `description`, rebuild the doc card's `Usage` band with the
|
|
26
|
+
canonical builder (`.throughline/references/doc-card-builder.md` —
|
|
27
|
+
verify its returned summary and stamp `surfaces.docCard.{src,render,renderer}`
|
|
28
|
+
from it), and (if the repo/code side exists) render MDX/JSDoc and run
|
|
29
|
+
`docs:digest` per the `storybook-chromatic-builder` render step.
|
|
30
|
+
3. **Reconcile drift.** Before trusting `docs:check`, confirm the repo's copy of
|
|
31
|
+
the doc scripts is current: compare `DOC_CARD_RENDERER_VERSION` in the repo's
|
|
32
|
+
`scripts/lib/doc-card-plan.mjs` against the same constant in
|
|
33
|
+
`.throughline/scripts/lib/doc-card-plan.mjs`. If the repo file is
|
|
34
|
+
missing, or its version is lower, `docs:check` is reading stale rules and its
|
|
35
|
+
"no drift" is meaningless — say so plainly, and offer to refresh the repo's
|
|
36
|
+
doc scripts from the plugin copy. Refresh the whole set and re-check the npm
|
|
37
|
+
registrations, both per **Documentation scripts — install as a set** in
|
|
38
|
+
`.throughline/scripts/README.md` — a refreshed file whose script was
|
|
39
|
+
never registered is the same failure in a new place. Run `docs:check` (with the
|
|
40
|
+
refreshed scripts, if any). For each drifted surface, offer a per-item
|
|
41
|
+
choice — **re-render** (canonical wins) or **pull-back**
|
|
42
|
+
(fold the surface edit into the record) — and land the result as a reviewable
|
|
43
|
+
change. On a brownfield component's first pass, adopt existing content
|
|
44
|
+
(`provenance: imported`) rather than overwriting it.
|
|
45
|
+
`docs:check` may also report `layout-upgrade-available` (informational, never
|
|
46
|
+
failing): the card's layout predates the current builder. Offer to re-render
|
|
47
|
+
the `Usage` band now — rebuild happens on this touch, never unprompted.
|
|
48
|
+
4. **Close the flow.** Hand back in the four-beat guide voice from
|
|
49
|
+
`.throughline/references/guide-voice.md`: the outcome, what you set
|
|
50
|
+
aside and why, one recommended next step, and at most one light alternative.
|
|
51
|
+
Read existing state to name what is actually outstanding rather than guessing —
|
|
52
|
+
a component at `status: "draft"` with no code surface in `meta[name].doc.surfaces`
|
|
53
|
+
means the code side is deferred. Do not close with a grid of co-equal options.
|
|
22
54
|
|
|
23
55
|
See `.throughline/references/component-doc-schema.md` for the record schema,
|
|
24
56
|
fingerprint contract, and projection mapping. If a component was never built in
|
|
@@ -27,15 +27,16 @@ system). Wire it to consume `packages/tokens` output so stories render with the
|
|
|
27
27
|
real design tokens (import the generated CSS/theme). Checkpoint: confirm
|
|
28
28
|
Storybook runs and shows the token-themed canvas.
|
|
29
29
|
|
|
30
|
-
Install the documentation scripts alongside the token scripts
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
- `"docs:check": "node scripts/docs-check.mjs"`
|
|
30
|
+
Install the documentation scripts alongside the token scripts: copy the five
|
|
31
|
+
files and register the three npm scripts listed under **Documentation scripts —
|
|
32
|
+
install as a set** in `.throughline/scripts/README.md`. That table is
|
|
33
|
+
the single source of truth for what a consuming repo gets; do not restate the
|
|
34
|
+
list here.
|
|
36
35
|
|
|
37
36
|
These are the documentation analog of `tokens:validate`; see
|
|
38
|
-
`.throughline/scripts/README.md`.
|
|
37
|
+
`.throughline/scripts/README.md`. This copy is setup, not a forever-fork:
|
|
38
|
+
`/document-component` re-checks these files' freshness on every run and refreshes
|
|
39
|
+
them from the plugin when it has moved on.
|
|
39
40
|
|
|
40
41
|
**pnpm build-script allowlist (first-run gotcha).** On pnpm workspaces, the
|
|
41
42
|
`@storybook/react-vite` install pulls `esbuild`, whose postinstall is blocked by
|
|
@@ -159,6 +160,43 @@ Configure Chromatic to snapshot everything (do **not** set `onlyChanged`), and
|
|
|
159
160
|
verify a token-only PR re-snapshots all stories — they should flip orange against
|
|
160
161
|
the green baseline.
|
|
161
162
|
|
|
163
|
+
### Usage & cost guardrails
|
|
164
|
+
|
|
165
|
+
The full-snapshot default above is the right call for catching regressions, and it
|
|
166
|
+
is also the **maximum-usage** choice: every story, every run. Chromatic bills per
|
|
167
|
+
snapshot, so name this cost shape to the user when you set Chromatic up, and put the
|
|
168
|
+
guardrails in *before* the first big token PR, not after the bill.
|
|
169
|
+
|
|
170
|
+
What Chromatic actually offers (re-verify the live numbers at
|
|
171
|
+
`chromatic.com/pricing` — they drift):
|
|
172
|
+
|
|
173
|
+
- **Free plan (~5,000 snapshots/month):** testing **auto-pauses** when the ceiling
|
|
174
|
+
is hit. No surprise bill, but visual-regression coverage silently *stops* until
|
|
175
|
+
the monthly reset or an upgrade. For a full-suite design system that ceiling
|
|
176
|
+
arrives fast — treat a *paused* build as a red flag, not a passing one.
|
|
177
|
+
- **Paid plans: no hard spending cap.** Overage snapshots auto-bill at month-end.
|
|
178
|
+
The only native guardrail is **usage alerts** — an email when consumption crosses
|
|
179
|
+
a threshold you set (e.g. 90%).
|
|
180
|
+
|
|
181
|
+
The math, so the user sizes the plan honestly: **snapshots ≈ stories × modes ×
|
|
182
|
+
builds.** One `/sync-figma-tokens` PR re-snapshots the *entire* suite × every mode
|
|
183
|
+
in a single build — e.g. 40 components × 2 modes = 80 snapshots per build, and a
|
|
184
|
+
handful of token PRs plus daily `main` builds clears a free tier in a week.
|
|
185
|
+
|
|
186
|
+
So the guardrails, all of them user-controlled (Chromatic will not cap you):
|
|
187
|
+
|
|
188
|
+
1. **Set usage alerts** at ~80% on a paid plan so the bill cannot sneak up. On the
|
|
189
|
+
free plan, make sure the user knows testing *pauses* at the ceiling.
|
|
190
|
+
2. **Scope the CI trigger.** Run Chromatic on **pull requests and `main` only** —
|
|
191
|
+
never on every branch push — path-filter out docs-only changes, and keep it to
|
|
192
|
+
one Chromatic build per commit (no duplicate runs).
|
|
193
|
+
3. **Size the plan to the math** before the first token PR. A large story count is
|
|
194
|
+
also the *only* reason to revisit TurboSnap (see above), and even then treat
|
|
195
|
+
every token change as a full run.
|
|
196
|
+
|
|
197
|
+
Do not silently pick a plan or leave the trigger wide open. Name the tradeoff and
|
|
198
|
+
let the user choose with the numbers in front of them.
|
|
199
|
+
|
|
162
200
|
## Step 5 — Code Connect (plan-gated, skip gracefully)
|
|
163
201
|
|
|
164
202
|
Code Connect ties Figma components to their code counterparts so Figma's dev
|
|
@@ -234,8 +272,10 @@ the `figma_execute` scripting gotchas — `getNodeByIdAsync` and an explicit
|
|
|
234
272
|
re-render the affected surfaces so `docs:check` stays green.
|
|
235
273
|
- If Figma is connected (per `figma.mechanism`), open the component's doc card and
|
|
236
274
|
update the `Status Label` text to `stable`, re-bind the `Status` chip fill to
|
|
237
|
-
the **success** semantic color variable (mode-aware, not a hardcoded hex),
|
|
238
|
-
|
|
275
|
+
the **success** semantic color variable (mode-aware, not a hardcoded hex), then
|
|
276
|
+
re-run the canonical doc-card builder against the same card to refresh the
|
|
277
|
+
header date from the `record.updatedAt` already set above (it locates the date
|
|
278
|
+
node under either header shape) — then screenshot to confirm the chip
|
|
239
279
|
recolored and the date changed.
|
|
240
280
|
- If Figma isn't connected, still update the manifest and tell the user the card
|
|
241
281
|
will reconcile next Figma session (or offer to reconnect and fix it now).
|
|
@@ -296,6 +336,9 @@ that may not exist.
|
|
|
296
336
|
- Never rely on TurboSnap (`onlyChanged: true`) for a token-driven design system
|
|
297
337
|
— its incremental model keeps missing global token changes. Default to full
|
|
298
338
|
snapshots (every story, every run); revisit only at large story counts.
|
|
339
|
+
- Never leave Chromatic's cost shape unspoken or the CI trigger wide open — there
|
|
340
|
+
is no hard spend cap on paid plans, so set usage alerts, run it on PRs + `main`
|
|
341
|
+
only, and size the plan to stories × modes × builds before the first token PR.
|
|
299
342
|
- Never use the sequential model for story-gen — parallelize via subagents.
|
|
300
343
|
- Never capture the Chromatic baseline *after* a code retrofit — baseline before, so
|
|
301
344
|
intended drift-fixes are distinguishable from regressions.
|
|
@@ -65,6 +65,8 @@ Copy these from `.throughline/scripts/` into the user's repo **verbatim**
|
|
|
65
65
|
(they are zero-dependency and version with the user's repo so their CI can run them):
|
|
66
66
|
|
|
67
67
|
- `lib/crosswalk.mjs` → `packages/tokens/scripts/lib/crosswalk.mjs`
|
|
68
|
+
- `lib/dtcg.mjs` → `packages/tokens/scripts/lib/dtcg.mjs` (required by
|
|
69
|
+
`validate-crosswalk.mjs` — copying the validator without it breaks the gate at import)
|
|
68
70
|
- `validate-crosswalk.mjs` → `packages/tokens/scripts/validate-crosswalk.mjs`
|
|
69
71
|
- `build-reverse-index.mjs` → `packages/tokens/scripts/build-reverse-index.mjs`
|
|
70
72
|
- `guard-token-removal.mjs` → `packages/tokens/scripts/guard-token-removal.mjs`
|
|
@@ -44,8 +44,8 @@ Ask which platform(s) the user is building for. Read
|
|
|
44
44
|
- **Curated (Tier 1):** `shadcn`, `tailwind`, `mui`, `vanilla-css`, `ios-swift`.
|
|
45
45
|
Vetted presets — high confidence.
|
|
46
46
|
- **Generated (Tier 2):** any other framework (Ant Design, Chakra, HeroUI,
|
|
47
|
-
Android/Kotlin, Flutter, etc.). The skill generates an adapter and
|
|
48
|
-
against a real component before trusting it.
|
|
47
|
+
Android/Kotlin, Flutter, etc.). The skill generates an adapter and
|
|
48
|
+
verifies it against a real component before trusting it.
|
|
49
49
|
|
|
50
50
|
**Always tell the user which tier they're on.** If they name a curated one, say
|
|
51
51
|
it'll be solid. If they name anything else, be honest: "That's not one I have a
|
|
@@ -139,11 +139,53 @@ register the platform, transform group, format, and `outputReferences`
|
|
|
139
139
|
flattens). Web adapters emit `:root`/`.dark` (or `[data-theme]`); the shadcn
|
|
140
140
|
adapter also emits a Tailwind preset.
|
|
141
141
|
|
|
142
|
+
**Native targets import the shipped configuration; they do not transcribe it.**
|
|
143
|
+
Copy `.throughline/scripts/lib/sd-native.mjs` into
|
|
144
|
+
`packages/tokens/scripts/lib/` (see Step 4) and call it. The stock `ios-swift`
|
|
145
|
+
and `compose` transform groups emit every `px`-authored dimension at ×16 its
|
|
146
|
+
value — valid, compiling, silently wrong — and mishandle `color-mix()` and
|
|
147
|
+
dual-node DTCG the same way. Never build a native platform from a stock
|
|
148
|
+
`transformGroup`.
|
|
149
|
+
|
|
150
|
+
```js
|
|
151
|
+
import StyleDictionary from 'style-dictionary';
|
|
152
|
+
import { registerNativeTransforms, nativePlatform, nativeSources }
|
|
153
|
+
from './scripts/lib/sd-native.mjs';
|
|
154
|
+
|
|
155
|
+
registerNativeTransforms(StyleDictionary);
|
|
156
|
+
|
|
157
|
+
for (const mode of MODES) { // e.g. ['light', 'dark']
|
|
158
|
+
const sd = new StyleDictionary({
|
|
159
|
+
source: nativeSources(sourcesFor(mode)), // guards against a mode collapse
|
|
160
|
+
preprocessors: ['dtcg/resolve-dual-node'],
|
|
161
|
+
platforms: {
|
|
162
|
+
ios: nativePlatform({ platform: 'ios-swift', buildPath: `ios/${mode}/` }),
|
|
163
|
+
// android also requires packageName:
|
|
164
|
+
// android: nativePlatform({ platform: 'android-kotlin',
|
|
165
|
+
// buildPath: `android/${mode}/`, packageName: 'com.example.tokens' }),
|
|
166
|
+
},
|
|
167
|
+
});
|
|
168
|
+
await sd.buildAllPlatforms();
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
**One build per mode combination, and never a glob.** Style Dictionary dedupes
|
|
173
|
+
by dot-path, so a single build over the whole token directory collapses light
|
|
174
|
+
and dark into whichever file sorted last, silently dropping a mode. Passing each
|
|
175
|
+
mode's sources through `nativeSources` turns that into a thrown error naming the
|
|
176
|
+
colliding paths. The `dtcg/resolve-dual-node` preprocessor throws too, on its
|
|
177
|
+
own collision: a dual node's hoisted child renamed to a camel-joined name that
|
|
178
|
+
an existing sibling or an earlier hoist in the same pass already has. Then run
|
|
179
|
+
`tokens:validate-output` against each generated file with that same source
|
|
180
|
+
list. See `.throughline/references/native-adapter-config.md`.
|
|
181
|
+
|
|
142
182
|
**Execution model — subagent dispatch with model routing.** Generating each
|
|
143
183
|
platform's output is independent and verifiable. If your host supports subagent
|
|
144
184
|
dispatch, dispatch **one `code-executor` per adapter** — each produces its
|
|
145
|
-
platform's files and verifies them (the config builds, the expected
|
|
146
|
-
appear, references resolve for
|
|
185
|
+
platform's files and verifies them (for web: the config builds, the expected
|
|
186
|
+
files appear, references resolve; for native: `tokens:validate-output` passes —
|
|
187
|
+
"the config builds" is not verification, it is the condition under which all
|
|
188
|
+
four known native failure modes ship silently) — then a **`reviewer`**
|
|
147
189
|
to check each before combining. Choose each subagent's model from its role tier
|
|
148
190
|
per `.throughline/references/agent-routing.md` (`code-executor` → fast,
|
|
149
191
|
`reviewer` → balanced), and only dispatch once each adapter's spec is complete
|
|
@@ -159,6 +201,24 @@ as **build artifacts** — regenerated every sync, never hand-edited. Wire
|
|
|
159
201
|
`packages/tokens/package.json` to export them so the UI package, Storybook, and
|
|
160
202
|
any future app consume them.
|
|
161
203
|
|
|
204
|
+
**Install the native token toolkit — all four files, as a set.** Copy
|
|
205
|
+
`.throughline/scripts/validate-token-output.mjs` into
|
|
206
|
+
`packages/tokens/scripts/`, and
|
|
207
|
+
`.throughline/scripts/lib/dtcg.mjs`,
|
|
208
|
+
`.throughline/scripts/lib/native-literal.mjs`, and
|
|
209
|
+
`.throughline/scripts/lib/sd-native.mjs` into
|
|
210
|
+
`packages/tokens/scripts/lib/`. `sd-native.mjs` and the validator both import
|
|
211
|
+
`dtcg.mjs` and `native-literal.mjs`, so copying any of them without the others
|
|
212
|
+
breaks at import. Then register the gate so it stays live on every future sync:
|
|
213
|
+
|
|
214
|
+
```json
|
|
215
|
+
"tokens:validate-output": "node scripts/validate-token-output.mjs --min-match 1"
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
Invoke it once per native output file, passing the same `--source` list that
|
|
219
|
+
file's build used. `--min-match 1` is what makes it a gate: the flag defaults to
|
|
220
|
+
`0.5`, so without it a 60% match rate exits `0`.
|
|
221
|
+
|
|
162
222
|
## Step 4.5 — Icon code sync (install check + custom SVGR)
|
|
163
223
|
|
|
164
224
|
Icons reach code differently from tokens, so handle them here if the system has
|
|
@@ -8,17 +8,49 @@ Ask which component to document (e.g. "Button"), then:
|
|
|
8
8
|
the `component-builder` rule's *Author the documentation record* step —
|
|
9
9
|
ingest any existing docs first (brownfield), then infer → enrich (from
|
|
10
10
|
`.throughline/references/component-doc-archetypes.md`) → specialize →
|
|
11
|
-
interview.
|
|
12
|
-
|
|
11
|
+
interview. Authored prose follows
|
|
12
|
+
`.throughline/references/doc-writing-standard.md`. Set `updatedAt` to
|
|
13
|
+
today's date (ISO, `YYYY-MM-DD`) whenever the record is written or rewritten —
|
|
14
|
+
it is a projected field and the doc card's header renders it. Once the record is
|
|
15
|
+
written, run `node .throughline/scripts/docs-lint.mjs
|
|
16
|
+
design-system/docs/components/<Name>.doc.json` and fix its warnings. Do not
|
|
17
|
+
raise a separate confirmation for a warning on an `imported`/`user` block:
|
|
18
|
+
draft the rewrite and carry it into the approval gate below, shown as
|
|
19
|
+
before/after and labelled with the block's provenance, so one approval covers
|
|
20
|
+
the whole record. The user approves the drafted record before anything is
|
|
21
|
+
projected (Figma description, doc card, manifest). Blocks the user did not
|
|
22
|
+
clear keep their existing text; blocks the user did clear are stamped
|
|
23
|
+
`imported+user` so a later run neither re-asks nor rewrites them.
|
|
13
24
|
2. **Project it.** Write `design-system/docs/components/<Name>.doc.json`, set the
|
|
14
|
-
Figma component `description`,
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
25
|
+
Figma component `description`, rebuild the doc card's `Usage` band with the
|
|
26
|
+
canonical builder (`.throughline/references/doc-card-builder.md` —
|
|
27
|
+
verify its returned summary and stamp `surfaces.docCard.{src,render,renderer}`
|
|
28
|
+
from it), and (if the repo/code side exists) render MDX/JSDoc and run
|
|
29
|
+
`docs:digest` per the `storybook-chromatic-builder` render step.
|
|
30
|
+
3. **Reconcile drift.** Before trusting `docs:check`, confirm the repo's copy of
|
|
31
|
+
the doc scripts is current: compare `DOC_CARD_RENDERER_VERSION` in the repo's
|
|
32
|
+
`scripts/lib/doc-card-plan.mjs` against the same constant in
|
|
33
|
+
`.throughline/scripts/lib/doc-card-plan.mjs`. If the repo file is
|
|
34
|
+
missing, or its version is lower, `docs:check` is reading stale rules and its
|
|
35
|
+
"no drift" is meaningless — say so plainly, and offer to refresh the repo's
|
|
36
|
+
doc scripts from the plugin copy. Refresh the whole set and re-check the npm
|
|
37
|
+
registrations, both per **Documentation scripts — install as a set** in
|
|
38
|
+
`.throughline/scripts/README.md` — a refreshed file whose script was
|
|
39
|
+
never registered is the same failure in a new place. Run `docs:check` (with the
|
|
40
|
+
refreshed scripts, if any). For each drifted surface, offer a per-item
|
|
41
|
+
choice — **re-render** (canonical wins) or **pull-back**
|
|
42
|
+
(fold the surface edit into the record) — and land the result as a reviewable
|
|
43
|
+
change. On a brownfield component's first pass, adopt existing content
|
|
44
|
+
(`provenance: imported`) rather than overwriting it.
|
|
45
|
+
`docs:check` may also report `layout-upgrade-available` (informational, never
|
|
46
|
+
failing): the card's layout predates the current builder. Offer to re-render
|
|
47
|
+
the `Usage` band now — rebuild happens on this touch, never unprompted.
|
|
48
|
+
4. **Close the flow.** Hand back in the four-beat guide voice from
|
|
49
|
+
`.throughline/references/guide-voice.md`: the outcome, what you set
|
|
50
|
+
aside and why, one recommended next step, and at most one light alternative.
|
|
51
|
+
Read existing state to name what is actually outstanding rather than guessing —
|
|
52
|
+
a component at `status: "draft"` with no code surface in `meta[name].doc.surfaces`
|
|
53
|
+
means the code side is deferred. Do not close with a grid of co-equal options.
|
|
22
54
|
|
|
23
55
|
See `.throughline/references/component-doc-schema.md` for the record schema,
|
|
24
56
|
fingerprint contract, and projection mapping. If a component was never built in
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: "Build
|
|
2
|
+
description: "Build Figma components — buttons, inputs, cards, badges, chips, modals, and more — with variant matrices (types, sizes, states) and icon/component/content slots bound to the design system's tokens and styles. Use this when the user wants to create components, build a component library, make buttons/inputs/cards/etc. in Figma, or set up the foundational UI kit. Also trigger after tokens and icons exist, when the user is ready to build actual UI components."
|
|
3
3
|
alwaysApply: false
|
|
4
4
|
---
|
|
5
5
|
# Component builder
|
|
@@ -240,7 +240,9 @@ Read `.throughline/references/component-doc-schema.md` for the exact JSON
|
|
|
240
240
|
schema, the fingerprint algorithm, and the projection contract.
|
|
241
241
|
|
|
242
242
|
**Run the generation pipeline (each layer only fills what it legitimately knows;
|
|
243
|
-
stamp `provenance` per block):**
|
|
243
|
+
stamp `provenance` per block):** all authored prose follows
|
|
244
|
+
`.throughline/references/doc-writing-standard.md` — its plain
|
|
245
|
+
reference register, not this skill's guide voice.
|
|
244
246
|
|
|
245
247
|
0. **Ingest existing docs — brownfield only, runs first.** If docs already exist
|
|
246
248
|
for this component (code JSDoc/MDX/README, or a populated Figma component
|
|
@@ -259,32 +261,74 @@ stamp `provenance` per block):**
|
|
|
259
261
|
accessibility idiom to the target framework (the same field you read for variant
|
|
260
262
|
vocabulary). Provenance `framework`.
|
|
261
263
|
4. **Interview for the non-inferable.** Ask the user for brand/product-specific
|
|
262
|
-
do's & don'ts and intent. Provenance `user`.
|
|
263
|
-
|
|
264
|
-
|
|
264
|
+
do's & don'ts and intent. Provenance `user`. Write the draft to
|
|
265
|
+
`design-system/docs/components/<Name>.doc.json`, run
|
|
266
|
+
`node .throughline/scripts/docs-lint.mjs design-system/docs/components/<Name>.doc.json`,
|
|
267
|
+
and fix the warnings it raises. Do not raise a separate confirmation for
|
|
268
|
+
a warning on an `imported`/`user` block: draft the rewrite and carry it
|
|
269
|
+
into the approval gate below, shown as before/after and labelled with the
|
|
270
|
+
block's provenance. **Show the whole drafted record and get explicit
|
|
271
|
+
approval before projecting it anywhere** (Figma description, doc card,
|
|
272
|
+
manifest) — one approval covers the whole record. Blocks the user did not
|
|
273
|
+
clear keep their existing text; blocks the user did clear are stamped
|
|
274
|
+
`imported+user` so a later run neither re-asks nor rewrites them.
|
|
265
275
|
|
|
266
276
|
**Write the record and project it:**
|
|
267
277
|
|
|
268
278
|
- Write `design-system/docs/components/<Name>.doc.json` (JSON; required fields
|
|
269
279
|
`name`, `summary`, `description`).
|
|
270
280
|
- **Figma component description.** Set the component's native `description` field
|
|
271
|
-
(via `figma_set_description`)
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
281
|
+
(via `figma_set_description`) from this exact template — this is the surface
|
|
282
|
+
Dev Mode and Code Connect read, and it must be reproducible byte-for-byte by
|
|
283
|
+
any agent from the same record:
|
|
284
|
+
|
|
285
|
+
```
|
|
286
|
+
<summary>
|
|
287
|
+
|
|
288
|
+
**When to use**
|
|
289
|
+
- <whenToUse[n]>
|
|
290
|
+
|
|
291
|
+
**When not to use**
|
|
292
|
+
- <whenNotToUse[n]>
|
|
293
|
+
|
|
294
|
+
**Do**
|
|
295
|
+
- <dos[n]>
|
|
296
|
+
|
|
297
|
+
**Don't**
|
|
298
|
+
- <donts[n]>
|
|
299
|
+
|
|
300
|
+
**Accessibility**
|
|
301
|
+
- <accessibility.keyboard[n]>
|
|
302
|
+
- <accessibility.notes[n]>
|
|
303
|
+
|
|
304
|
+
<!-- tl:doc <fp> -->
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
Rules: every line is a record string **verbatim** — no re-wording, no added
|
|
308
|
+
connectives, no sentences that appear nowhere in the record. A block whose
|
|
309
|
+
source array is empty is omitted along with its bold label. The **Accessibility**
|
|
310
|
+
label is omitted only when both `accessibility.keyboard` and `accessibility.notes`
|
|
311
|
+
are empty; when one is empty its bullets are simply absent and the label stays.
|
|
312
|
+
Sections are separated by exactly one blank line, and the fingerprint marker is
|
|
313
|
+
always last.
|
|
314
|
+
- **Doc card body.** Render the card's `Usage` band with the canonical builder
|
|
315
|
+
snippet in `.throughline/references/doc-card-builder.md` (via
|
|
316
|
+
`figma_execute` with an explicit `timeout`, one card per call): fill the
|
|
317
|
+
RECORD/CANONICAL_FP slots, resolve the nine required semantic variables and
|
|
318
|
+
the `Body/Default` text style per that file's call contract, run it, and
|
|
319
|
+
verify the returned summary (`rowsRendered`, `blocksCreated`, `cardWidth`) —
|
|
320
|
+
not a screenshot. The builder creates the `Doc Fingerprint` node itself and
|
|
321
|
+
is the only thing that may build the usage body — never hand-assemble it.
|
|
280
322
|
- Compute `<fp>` as the canonical fingerprint defined in the schema reference
|
|
281
323
|
(sha256 of the projected record without `provenance`, first 16 hex chars).
|
|
282
324
|
|
|
283
325
|
**Update the manifest (fields this skill owns):** set
|
|
284
326
|
`components.meta[<Name>].doc` to `{ path, fingerprint: <fp>, surfaces: {
|
|
285
327
|
figmaDescription: { src: <fp>, render: <hash of the description text> }, docCard: {
|
|
286
|
-
src: <fp>, render: <
|
|
287
|
-
|
|
328
|
+
src: <fp>, render: <summary.renderHash>, renderer: <summary.rendererVersion> } } }`
|
|
329
|
+
— the docCard entry is stamped from the builder's returned summary, never by
|
|
330
|
+
re-reading the card. The code surfaces (`storybookMdx`) are added later by
|
|
331
|
+
`storybook-chromatic-builder`.
|
|
288
332
|
|
|
289
333
|
Run the standard doc-card visual-validation + post-build audit
|
|
290
334
|
(`.throughline/references/figma-component-standards.md`) after enriching
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: "Take a single new component from Figma to fully-built-and-storied code, end to end — build it in Figma, sync any new tokens it introduced, then build its code component and stories.
|
|
2
|
+
description: "Take a single new component from Figma to fully-built-and-storied code, end to end — build it in Figma, sync any new tokens it introduced, then build its code component and stories. Orchestrates component-builder, token-sync-layer, and storybook-chromatic-builder with a human confirmation between each stage. Use this when the user wants to add a new component to an existing design system, ship a component end-to-end, or run the full new-component flow. Also trigger on \"/new-component\" or when someone wants one component built all the way through to code."
|
|
3
3
|
alwaysApply: false
|
|
4
4
|
---
|
|
5
5
|
# Component pipeline (orchestrator)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: "Measure a pre-existing design system before retrofitting it onto tokens
|
|
2
|
+
description: "Measure a pre-existing design system before retrofitting it onto tokens, so the retrofit is right-sized. This is a PROCESS skill and the brownfield front door. Use this when retrofitting a design system onto a mature codebase and an already-populated Figma file, when the user wants to audit an existing system, size a retrofit, count existing tokens/variables/bindings, or figure out how much work a migration is. Also trigger when figma-environment-setup detects a brownfield situation (existing repo or populated Figma file), before any building."
|
|
3
3
|
alwaysApply: false
|
|
4
4
|
---
|
|
5
5
|
# Design-system audit (brownfield front door)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: "Set up the local working folder and connect Cursor to Figma so the design-system skills can read and write variables, styles, and components.
|
|
2
|
+
description: "Set up the local working folder and connect Cursor to Figma so the design-system skills can read and write variables, styles, and components. Run this BEFORE brainstorming and before any other design-system skill. Invoke it immediately when the user wants to start, set up, or begin building a design system — phrases like 'let's setup my design system', 'let's get started', 'connect Figma', or 'build my design system' should all trigger this skill first, ahead of brainstorming. Also trigger when the user wants to fix a broken Figma connection, or mentions the Figma Console MCP, the desktop bridge plugin, or a Figma access token."
|
|
3
3
|
alwaysApply: false
|
|
4
4
|
---
|
|
5
5
|
# Figma environment setup
|