super-ux 0.18.0 → 0.23.2
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 +213 -0
- package/README.md +195 -130
- package/bin/super-ux.js +15 -3
- package/cursor/rules/super-ux.mdc +16 -5
- package/cursor/rules/ux-audit.mdc +9 -2
- package/cursor/rules/ux-flows.mdc +20 -3
- package/cursor/rules/ux-foundation.mdc +7 -0
- package/cursor/rules/ux-scenarios.mdc +9 -4
- package/package.json +6 -2
- package/plugins/super-ux/scripts/ux_lint.py +231 -0
- package/templates/README.md +4 -2
- package/templates/claude-rule.md +9 -4
- package/templates/flows.md +2 -0
- package/templates/screens.md +5 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,218 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.23.2 — 2026-07-28
|
|
4
|
+
|
|
5
|
+
Open-source hygiene pass — the repo is public, so the files a first-time
|
|
6
|
+
contributor looks for now exist.
|
|
7
|
+
|
|
8
|
+
### Added
|
|
9
|
+
- `SECURITY.md` — what the skill and its installer actually run (two `claude`
|
|
10
|
+
calls, explicit argv, no network from the linter), what they write, and private
|
|
11
|
+
reporting.
|
|
12
|
+
- `CODE_OF_CONDUCT.md` and a pull-request template that asks for the command
|
|
13
|
+
output rather than a "tests pass" claim.
|
|
14
|
+
- README now points at the security policy and the code of conduct alongside
|
|
15
|
+
contributing.
|
|
16
|
+
|
|
17
|
+
## 0.23.1 — 2026-07-28
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
- Consistent American spelling across every agent-facing file (`labour` →
|
|
21
|
+
`labor`, `honour` → `honor`, `neighbouring` → `neighboring`) — the docs
|
|
22
|
+
were mixing both, which reads as sloppy in a repo whose whole pitch is that
|
|
23
|
+
small inconsistencies compound.
|
|
24
|
+
- Reflowed three paragraphs left ragged by the previous pass's mechanical
|
|
25
|
+
edits (`figma-integration.md` intro, the `ux-flows` build gate), and the
|
|
26
|
+
build gate now names the style pack alongside the chain and the Figma
|
|
27
|
+
mockups.
|
|
28
|
+
|
|
29
|
+
## 0.23.0 — 2026-07-28
|
|
30
|
+
|
|
31
|
+
Production pass over the public repo: every file read again, the remaining
|
|
32
|
+
contradictions fixed, and the front door rewritten for people who have never
|
|
33
|
+
seen this project.
|
|
34
|
+
|
|
35
|
+
### Fixed
|
|
36
|
+
- **The hard rule described a three-layer chain.** The most-copied text in the
|
|
37
|
+
project — the rule installed into every `CLAUDE.md`, the always-on Cursor
|
|
38
|
+
rule, the README, `/ux-rule`, the `ux-flows` build gate — said
|
|
39
|
+
"foundation → flows → scenarios" while `screens.md` has been a first-class
|
|
40
|
+
layer with its own same-change rule since 0.16.0. All five copies now say
|
|
41
|
+
foundation → flows → **screens** → scenarios.
|
|
42
|
+
- **`ux-foundation` didn't know about a section it owns.** The contract gives
|
|
43
|
+
`foundation.md` a Design tooling block (Figma on/off + file URL), but
|
|
44
|
+
neither the skill nor its Cursor rule ever mentioned it, so the field was
|
|
45
|
+
only ever filled by whoever happened to read the template. Both now cover it
|
|
46
|
+
— and state that everything else visual (design system, style pack, frame
|
|
47
|
+
links) belongs to `screens.md`.
|
|
48
|
+
- The README's mermaid diagram used `\n` for line breaks, which GitHub renders
|
|
49
|
+
literally; it is `<br/>` now — and the diagram shows the current chain
|
|
50
|
+
(foundation → flows → screens → scenarios → build → audit → plan) instead of
|
|
51
|
+
the pre-flows one.
|
|
52
|
+
- `/ux`'s own description advertised "foundation/scenarios/audits"; menu item 3
|
|
53
|
+
said "design user flows" without mentioning that it also registers screens.
|
|
54
|
+
Inspect now also reports unexecuted plans in `docs/ux/plans/`.
|
|
55
|
+
- `ux-flows` Design had visual identity, wireframes, and Figma crammed into one
|
|
56
|
+
numbered step; identity is now its own step, before anything gets drawn.
|
|
57
|
+
|
|
58
|
+
### Added
|
|
59
|
+
- **[CONTRIBUTING.md](CONTRIBUTING.md)** — repo layout (including *why* the
|
|
60
|
+
contracts are duplicated per skill), the edit → sync → validate loop, the
|
|
61
|
+
conventions, how to test a change from a packed tarball rather than the
|
|
62
|
+
working tree, and the release checklist.
|
|
63
|
+
- Issue templates for bug reports and ideas, both asking for the thing that
|
|
64
|
+
actually resolves a report: the file that says otherwise, and the check that
|
|
65
|
+
would fail.
|
|
66
|
+
- Validator check: the plugin description in `marketplace.json` must equal the
|
|
67
|
+
one in `plugin.json` — the ecosystem requires both copies, so the duplication
|
|
68
|
+
gets a check instead of trust.
|
|
69
|
+
- `package.json` gains a `bugs` URL; `.gitignore` covers `npm pack` tarballs.
|
|
70
|
+
|
|
71
|
+
### Changed
|
|
72
|
+
- **README restructured for a first-time reader**: what goes wrong and what
|
|
73
|
+
super-ux does about it, the chain diagram, what you get, quick start per
|
|
74
|
+
channel, the hard rule, the typical cycle, companions, then the internals
|
|
75
|
+
(skills, commands, and a second table for the contracts). Value first,
|
|
76
|
+
reference last.
|
|
77
|
+
- Manifest descriptions rewritten to describe the current system — the whole
|
|
78
|
+
chain, the four skills, the linter, and the style pack — instead of the
|
|
79
|
+
0.17-era feature list.
|
|
80
|
+
- The historical `docs/superpowers/` spec and plan carry a banner marking them
|
|
81
|
+
as v0.1.0 provenance, with pointers to the live contract; they described two
|
|
82
|
+
skills and four commands and are not maintained.
|
|
83
|
+
|
|
84
|
+
## 0.22.0 — 2026-07-28
|
|
85
|
+
|
|
86
|
+
### Added
|
|
87
|
+
- **The visual layer has an owner: the `sheleg-design` companion.** super-ux
|
|
88
|
+
decided what every screen must contain and which craft floors it had to
|
|
89
|
+
clear, then left the actual look to be invented frame by frame — the visual
|
|
90
|
+
half of the drift this system exists to prevent. New reference
|
|
91
|
+
[`visual-identity.md`](plugins/super-ux/skills/references/visual-identity.md)
|
|
92
|
+
makes one **style pack** the identity for the whole product: picked with the
|
|
93
|
+
sheleg-design skill (`workbench` for product UI, dashboards and tools;
|
|
94
|
+
`instrument-console`; `editorial-luxury`; or a new pack authored on its
|
|
95
|
+
contract), recorded once, obeyed everywhere. A cinematic scroll-driven
|
|
96
|
+
landing also takes that skill's motion methodology.
|
|
97
|
+
- **`Style pack` field** in `screens.md` → Design system (contract + template).
|
|
98
|
+
One owner per fact: the pack is named there and referenced from everywhere
|
|
99
|
+
else, with its token file location beside it.
|
|
100
|
+
- **Wired into every design entry point** — `ux-flows` Design (before a frame
|
|
101
|
+
is drawn, not after), `/ux` step 0 beside the Figma question, `/ux-flows`,
|
|
102
|
+
the Figma design loop (pack tokens become the Figma variable collections),
|
|
103
|
+
the Cursor `ux-flows` rule, the hard rule in `templates/claude-rule.md` and
|
|
104
|
+
`/ux-rule`, and the seeded `docs/ux/README.md`.
|
|
105
|
+
- **Audited like any other record.** When a `Style pack` is recorded, the deep
|
|
106
|
+
audit's practice pass checks the built UI honors it — tokens referenced
|
|
107
|
+
instead of raw values, the pack's bans respected, dark mode from its twin;
|
|
108
|
+
a screen ignoring the recorded pack is `drifted`. No pack and an improvised
|
|
109
|
+
visual layer → the companion is suggested once, as an opportunity finding.
|
|
110
|
+
- Validator guard: the hard rule embedded in `/ux-rule` must be byte-identical
|
|
111
|
+
to `templates/claude-rule.md`. They had already drifted apart in wording —
|
|
112
|
+
two copies of a rule is the exact failure the plugin preaches against.
|
|
113
|
+
|
|
114
|
+
### Changed
|
|
115
|
+
- Recommendation, not dependency, in both directions: one offer with its
|
|
116
|
+
one-time install, then the user's answer stands and the chain continues on
|
|
117
|
+
platform defaults. A project that already has a design system records that
|
|
118
|
+
instead — two identities are worse than any one.
|
|
119
|
+
- Conflict rule stated where both sides live (`practice-selection.md`,
|
|
120
|
+
`ux-design-principles.md`): the style pack owns identity and wins on look;
|
|
121
|
+
BP-079..090 are floors (contrast, tap targets, line length, spacing rhythm)
|
|
122
|
+
and win on safety. The conflict and its resolution go in the compliance
|
|
123
|
+
table.
|
|
124
|
+
- README gains a Companions table (sheleg-design at VISUALIZE/BUILD,
|
|
125
|
+
task-pipeline after a plan) and the hard rule gains its style-pack bullet.
|
|
126
|
+
|
|
127
|
+
## 0.21.0 — 2026-07-28
|
|
128
|
+
|
|
129
|
+
Full-repo consistency pass: every file read, every contradiction between the
|
|
130
|
+
contract, the skills, the Cursor rules, the templates, and the tooling fixed.
|
|
131
|
+
|
|
132
|
+
### Fixed
|
|
133
|
+
- **`npx super-ux --cursor` crashed for every npm user.** `package.json`
|
|
134
|
+
`files[]` never shipped `plugins/super-ux/scripts/ux_lint.py`, so the CLI
|
|
135
|
+
installed the rules and templates and then died with an ENOENT stack trace
|
|
136
|
+
while copying the linter (reproduced against a packed 0.20.0 tarball). The
|
|
137
|
+
script is now in `files[]`, and a missing linter degrades to a warning with
|
|
138
|
+
a download link instead of a crash.
|
|
139
|
+
- **The linter mis-read story priorities.** `ST-NNN` bodies were scanned with
|
|
140
|
+
a fixed 600-character window, so a neighboring story's `**Priority:**`
|
|
141
|
+
line leaked into the previous story and produced false "must/should story
|
|
142
|
+
has no scenario" warnings. The scan now stops at the next heading.
|
|
143
|
+
- **The UX-plan example rendered broken.** The `` ```markdown `` block in the
|
|
144
|
+
contract contained a nested three-backtick fence, which closed the outer
|
|
145
|
+
block early and inverted the rest of the section; it is a four-backtick
|
|
146
|
+
fence now.
|
|
147
|
+
- Duplicate `refs(flows, "SCR")` computation in the linter collapsed into one.
|
|
148
|
+
- `release.yml` referenced a `pipeline.example.json` path that does not exist
|
|
149
|
+
in this repo and installed `jsonschema` the stdlib-only validator never
|
|
150
|
+
used.
|
|
151
|
+
|
|
152
|
+
### Changed
|
|
153
|
+
- **One owner per fact:** `**Design system:**` is gone from `foundation.md` →
|
|
154
|
+
Design tooling (it contradicted `screens.md`, `figma-integration.md`, and
|
|
155
|
+
the templates). Foundation records the Figma on/off choice and the file
|
|
156
|
+
URL; `screens.md` → Design system records the library, tokens, components,
|
|
157
|
+
and assets. `figma-structure.md` and `system-map.md` say the same thing.
|
|
158
|
+
- Cursor rules resynced with ux-contract v4: `ux-flows` documented a stale
|
|
159
|
+
`Screens & states` table (it is `Screens traversed` + the `screens.md`
|
|
160
|
+
entry shape); `ux-scenarios` was missing the `Alt paths` field and the
|
|
161
|
+
monetization entries of the per-product checklist; `ux-audit` said "git SHA
|
|
162
|
+
of scenarios.md" (the contract says `docs/ux`) and never mentioned
|
|
163
|
+
flow/screen conformance or the `coverage` scope; `super-ux` told Cursor
|
|
164
|
+
users to run `/ux-lint`, a Claude-Code-only command.
|
|
165
|
+
- `/ux` reports every layer (it said "all three"); `/ux-init` is incremental —
|
|
166
|
+
existing layers are left untouched and only the missing ones initialized,
|
|
167
|
+
instead of talking about "both files" from a two-file era; README no longer
|
|
168
|
+
says the skills CLI installs "both skills".
|
|
169
|
+
- `docs/ux/plans/` is created by the installers, `/ux-rule`, and `/ux`
|
|
170
|
+
alongside `audits/` — the contract has required the directory since v4.
|
|
171
|
+
- `install.sh --help` described seeding one file; it seeds the whole skeleton
|
|
172
|
+
plus the linter. README's Development section documents the four-way
|
|
173
|
+
version sync and the `sync_references.py` step.
|
|
174
|
+
|
|
175
|
+
### Added
|
|
176
|
+
- Validator check: every asset `bin/super-ux.js` copies must be covered by
|
|
177
|
+
`package.json` `files[]`, parsed from the CLI source rather than a
|
|
178
|
+
hand-kept list — the packaging regression above cannot come back silently.
|
|
179
|
+
- `templates/flows.md` carries the contract's `Wireframe` field.
|
|
180
|
+
|
|
181
|
+
## 0.20.0 — 2026-07-28
|
|
182
|
+
|
|
183
|
+
### Changed
|
|
184
|
+
- Skill descriptions restructured English-first: every Russian trigger now sits
|
|
185
|
+
beside its English equivalent (`"user flow" / "юзер флоу"`) instead of forming
|
|
186
|
+
a Russian-only tail, and the `/ux` routing table follows the same pairing.
|
|
187
|
+
- README is English-only: the Russian section is gone, replaced by a plain
|
|
188
|
+
statement of what the skill gives you and an author/links block.
|
|
189
|
+
|
|
190
|
+
### Added
|
|
191
|
+
- Validator enforces the three description canon rules on every skill —
|
|
192
|
+
`Use when` opening, Russian trigger aliases present, front-matter under 1024
|
|
193
|
+
characters. Twelve new checks; all four skills pass.
|
|
194
|
+
|
|
195
|
+
## 0.19.0 — 2026-07-25
|
|
196
|
+
|
|
197
|
+
Review pass — the contracts were not reaching non-Claude agents.
|
|
198
|
+
|
|
199
|
+
- **FIX (distribution): shared contracts now ship with every skill.** The skills
|
|
200
|
+
CLI copies only a skill's OWN directory, so the sibling `skills/references/`
|
|
201
|
+
reached Claude Code plugins but arrived **dangling on Cursor / Codex / OpenCode /
|
|
202
|
+
OpenClaw / …** — `~/.agents/skills/ux-audit/` held nothing but `SKILL.md` while
|
|
203
|
+
its SKILL.md called `scenario-format.md` a contract to "never deviate" from.
|
|
204
|
+
Each skill now carries its own `references/` (the transitive closure of what it
|
|
205
|
+
links) and links them `references/…`. `skills/references/` stays the source of
|
|
206
|
+
truth; `test/sync_references.py` re-syncs; the validator fails on drift, on a
|
|
207
|
+
missing shipped contract, on any `../references/` link, and on dangling links
|
|
208
|
+
inside the copies.
|
|
209
|
+
- Cursor always-on rule gains the `screens.md` and linter bullets it was missing
|
|
210
|
+
(it was two canon versions behind the Claude rule).
|
|
211
|
+
- `ux-scenarios.mdc` contract stamp corrected `scenario-format v1` → `ux-contract v4`.
|
|
212
|
+
- `system-map.md` lists `/ux-init`; README fixes "both skills" → "all four",
|
|
213
|
+
"three agent-requested rules" → "four", and the release note now names
|
|
214
|
+
`package.json` in the version-sync set (the validator has always enforced it).
|
|
215
|
+
|
|
3
216
|
All notable changes to this project are documented in this file. The format
|
|
4
217
|
follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versions
|
|
5
218
|
follow [SemVer](https://semver.org/spec/v2.0.0.html).
|
package/README.md
CHANGED
|
@@ -4,74 +4,52 @@
|
|
|
4
4
|
[](https://github.com/ssheleg/super-ux/actions/workflows/validate.yml)
|
|
5
5
|
[](LICENSE)
|
|
6
6
|
|
|
7
|
-
Scenario-driven UI development for AI agents
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
the
|
|
7
|
+
**Scenario-driven UI development for AI agents** — Claude Code, Cursor, and
|
|
8
|
+
70+ other agents.
|
|
9
|
+
|
|
10
|
+
Coding agents build bad interfaces for one reason: they write UI without a
|
|
11
|
+
model of user behavior. Screens appear feature by feature; error states,
|
|
12
|
+
empty states, and cross-feature flows get invented ad hoc or skipped, and
|
|
13
|
+
three prompts later the agent quietly rewrites something you already
|
|
14
|
+
approved. super-ux fixes the process, not the symptom: a versioned design
|
|
15
|
+
chain in `docs/ux/` becomes the source of truth, written and approved
|
|
16
|
+
*before* UI exists, updated in the same change as any behavior change, and
|
|
17
|
+
used as the checklist for evidence-backed audits of the code.
|
|
17
18
|
|
|
18
19
|
```mermaid
|
|
19
20
|
flowchart LR
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
G --> H[Prioritized fix plan\nFreq × Severity × Solvability] --> D
|
|
21
|
+
F["Foundation<br/>personas · JTBD<br/>journeys · stories"] --> L["Flows<br/>task analysis<br/>+ branches"]
|
|
22
|
+
L --> S["Screens<br/>states · elements<br/>Figma frames"]
|
|
23
|
+
S --> C["Scenarios<br/>action → response<br/>alt + error paths"]
|
|
24
|
+
C --> B["Build UI<br/>only now"]
|
|
25
|
+
B --> A["Audit<br/>code vs the chain<br/>file:line evidence"]
|
|
26
|
+
A --> P["Fix plan<br/>Freq × Severity<br/>× Solvability"]
|
|
27
|
+
P --> B
|
|
28
|
+
B -.->|same change| C
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
per-product completeness checklists, the `draft → validated → implemented`
|
|
54
|
-
lifecycle, audit verdicts and severities.
|
|
55
|
-
|
|
56
|
-
## The hard rule
|
|
57
|
-
|
|
58
|
-
- `docs/ux/scenarios.md` is the source of truth for all user-facing
|
|
59
|
-
behavior; foundation (WHY) and flows (HOW) are the layers it traces to.
|
|
60
|
-
- Any change touching user-facing behavior or interface updates **in the
|
|
61
|
-
same change**: scenarios, affected flows, the affected screens in
|
|
62
|
-
`docs/ux/screens.md` (the UI map — states, elements, coverage), and (Figma
|
|
63
|
-
on) the Figma frames plus their links. Code that diverges from a screen's
|
|
64
|
-
record, or a stale Figma link, is drift the audit flags.
|
|
65
|
-
- Any new feature or project **starts** with the chain: which job, which
|
|
66
|
-
journey stage, which story — then flows and scenarios, validated and
|
|
67
|
-
approved.
|
|
68
|
-
- **Do not write interface code until the UX workflow is done first** — the
|
|
69
|
-
foundation → flows → scenarios chain designed and approved, and (when
|
|
70
|
-
Figma is enabled, the default) the UI mocked up in Figma with every screen
|
|
71
|
-
linked to its frame. Building UI before this is the mistake super-ux
|
|
72
|
-
exists to prevent.
|
|
73
|
-
|
|
74
|
-
## Install
|
|
31
|
+
Every layer traces to the one above it. New product? Build it forward. Existing
|
|
32
|
+
codebase? The same artifacts get filled in backwards from the code, tagged
|
|
33
|
+
`inferred` until you confirm them — the gap between "is" and "should" becomes
|
|
34
|
+
your improvement backlog.
|
|
35
|
+
|
|
36
|
+
## What you get
|
|
37
|
+
|
|
38
|
+
- **Context stops evaporating.** You describe who the product is for and what
|
|
39
|
+
job it does once; every later prompt inherits that instead of re-deriving it
|
|
40
|
+
from the diff.
|
|
41
|
+
- **Scenarios become acceptance criteria.** "Make it nicer" can no longer mean
|
|
42
|
+
"silently change the error handling" — a file says what the error handling
|
|
43
|
+
does, and the audit checks the code against it.
|
|
44
|
+
- **Drift gets caught, deterministically.** A linter fails on missing Figma
|
|
45
|
+
frames, broken traces, orphan screens, and index desync; audits report what
|
|
46
|
+
no longer matches with `file:line` evidence. That is the review pass you'd
|
|
47
|
+
otherwise never run.
|
|
48
|
+
- **Designer artifacts without being a designer.** Personas, jobs to be done,
|
|
49
|
+
journeys, flows, screen states, wireframes, Figma frames — produced in your
|
|
50
|
+
repo, in the vocabulary a design review actually uses.
|
|
51
|
+
|
|
52
|
+
## Quick start
|
|
75
53
|
|
|
76
54
|
### Claude Code
|
|
77
55
|
|
|
@@ -80,97 +58,184 @@ lifecycle, audit verdicts and severities.
|
|
|
80
58
|
/plugin install super-ux@super-ux
|
|
81
59
|
```
|
|
82
60
|
|
|
83
|
-
Then in your project
|
|
84
|
-
`docs/ux/`, builds the
|
|
85
|
-
|
|
61
|
+
Then in your project, run `/ux` and answer in plain words. First run installs
|
|
62
|
+
the hard rule, seeds `docs/ux/`, and builds the chain; every later run reports
|
|
63
|
+
status and recommends one next action. You never pick a skill or a layer —
|
|
64
|
+
routing is the agent's job.
|
|
86
65
|
|
|
87
|
-
###
|
|
66
|
+
### Cursor
|
|
88
67
|
|
|
89
68
|
```sh
|
|
90
|
-
npx
|
|
69
|
+
npx super-ux --cursor /path/to/your/project
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Copies the rules into `.cursor/rules/` (one always-on hard rule + four
|
|
73
|
+
agent-requested rules), seeds `docs/ux/`, and installs the linter. An existing
|
|
74
|
+
scenario base is never overwritten; re-run with `--force` after a release to
|
|
75
|
+
refresh rules and linter only.
|
|
76
|
+
|
|
77
|
+
### Any agent (70+, via the skills CLI)
|
|
78
|
+
|
|
79
|
+
```sh
|
|
80
|
+
npx skills add ssheleg/super-ux # all four skills, current project
|
|
91
81
|
npx skills add ssheleg/super-ux -g # user-global
|
|
92
82
|
npx skills add ssheleg/super-ux --skill ux-audit # one skill
|
|
93
83
|
```
|
|
94
84
|
|
|
95
85
|
[vercel-labs/skills](https://github.com/vercel-labs/skills) discovers the
|
|
96
86
|
skills through this repo's marketplace manifest and installs them for Claude
|
|
97
|
-
Code, Cursor, Codex, OpenCode and others.
|
|
98
|
-
|
|
99
|
-
|
|
87
|
+
Code, Cursor, Codex, OpenCode and others. This channel ships the skills only —
|
|
88
|
+
the `/ux` commands come with the plugin, the always-on hard rule with the
|
|
89
|
+
Cursor install.
|
|
100
90
|
|
|
101
|
-
### Interactive (pick
|
|
91
|
+
### Interactive (pick channels and agents)
|
|
102
92
|
|
|
103
93
|
```sh
|
|
104
94
|
npx super-ux
|
|
105
95
|
```
|
|
106
96
|
|
|
107
|
-
Multi-select menu (space
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
97
|
+
Multi-select menu (space toggles, `a` selects everything, enter installs):
|
|
98
|
+
skills for any of 70+ agents, Cursor rules into a project, and the Claude Code
|
|
99
|
+
plugin user-globally — any combination in one run. Also works straight from
|
|
100
|
+
GitHub: `npx github:ssheleg/super-ux --cursor <dir>`, or clone and run
|
|
101
|
+
`./install.sh --cursor <dir>`.
|
|
111
102
|
|
|
112
|
-
|
|
103
|
+
## The hard rule
|
|
104
|
+
|
|
105
|
+
Installed into your project's `CLAUDE.md` (and as the always-on Cursor rule):
|
|
106
|
+
|
|
107
|
+
- `docs/ux/scenarios.md` is the source of truth for all user-facing behavior;
|
|
108
|
+
foundation (WHY), flows (HOW), and screens (the UI map) are the layers it
|
|
109
|
+
traces to.
|
|
110
|
+
- Any change touching user-facing behavior or interface updates **in the same
|
|
111
|
+
change**: scenarios, affected flows, the affected screens in
|
|
112
|
+
`docs/ux/screens.md`, and — when Figma is on — the frames plus their links.
|
|
113
|
+
Code that diverges from a screen's record, or a stale Figma link, is drift
|
|
114
|
+
the audit flags.
|
|
115
|
+
- Any new feature or project **starts** with the chain: which job, which
|
|
116
|
+
journey stage, which story — then flows, screens, and scenarios, validated
|
|
117
|
+
against the existing base and approved.
|
|
118
|
+
- **Do not write interface code until that workflow is done** — chain designed
|
|
119
|
+
and approved, and (Figma on, the default) the UI mocked up with every screen
|
|
120
|
+
linked to its frame. Building UI before this is the mistake super-ux exists
|
|
121
|
+
to prevent.
|
|
122
|
+
- One **style pack** is the visual identity for the whole product, recorded in
|
|
123
|
+
`docs/ux/screens.md` → Design system. Inventing a palette, type pairing, or
|
|
124
|
+
motion per screen is drift too.
|
|
125
|
+
- Run `python3 docs/ux/lint.py` after any UX change and in CI — it must pass.
|
|
126
|
+
|
|
127
|
+
## Typical cycle
|
|
128
|
+
|
|
129
|
+
1. **`/ux`** — first run sets everything up: foundation first (greenfield:
|
|
130
|
+
an interview about personas, jobs, journeys; existing code:
|
|
131
|
+
reverse-engineering them), then flows, screens, and scenarios derived from
|
|
132
|
+
the stories with full traceability.
|
|
133
|
+
2. **Work normally.** Every user-facing change updates the chain in the same
|
|
134
|
+
change — the always-on rule catches it, `/ux-update` gives manual control.
|
|
135
|
+
New feature ideas get validated against the chain first: which job, which
|
|
136
|
+
journey stage, which story. An idea serving no job is challenged, not
|
|
137
|
+
silently built.
|
|
138
|
+
3. **`/ux-audit`** — batched verification of code against every scenario plus
|
|
139
|
+
its story's acceptance criteria. `deep` adds heuristic, practice, and chain
|
|
140
|
+
coverage passes; `coverage` audits the chain itself. Reports land in
|
|
141
|
+
`docs/ux/audits/YYYY-MM-DD.md`.
|
|
142
|
+
4. **Fix plan.** Findings become `docs/ux/plans/…`: the target interface per
|
|
143
|
+
screen plus a traced CREATE/MODIFY/DELETE table, prioritized by Frequency ×
|
|
144
|
+
Severity × Solvability — written to be executable without the conversation
|
|
145
|
+
that produced it. Build, then re-audit.
|
|
146
|
+
|
|
147
|
+
## Companions (recommended, never required)
|
|
148
|
+
|
|
149
|
+
super-ux owns structure and behavior, and deliberately stops at two edges.
|
|
150
|
+
Each companion is offered once with its one-time install; the chain works
|
|
151
|
+
fine without either.
|
|
152
|
+
|
|
153
|
+
| When | Companion | What it adds |
|
|
154
|
+
|---|---|---|
|
|
155
|
+
| At VISUALIZE / BUILD — a frame or a screen is about to be drawn | **[sheleg-design](https://github.com/ssheleg/sheleg-design-skill)** | The look: one locked style pack (palette, type, texture, motion tokens, bans) with ready token CSS — `workbench` for product UI, dashboards and tools; `instrument-console`; `editorial-luxury`; or a new pack on its contract. Plus the motion methodology for cinematic scroll-driven landings. The pack is recorded in `screens.md`; its tokens become the Figma variables *and* the code tokens. `npx sheleg-design-skill` |
|
|
156
|
+
| After an audit or an Improve pass produced a UX plan | **[task-pipeline](https://github.com/ssheleg/task-pipeline)** | Executes the plan end-to-end through gated stages: spec → plan → subagent build → tests → deploy → docs. `/task-pipeline docs/ux/plans/<file>` |
|
|
157
|
+
|
|
158
|
+
The boundary that keeps them from fighting: BP-079..090 are craft **floors**
|
|
159
|
+
(contrast, line length, tap targets, spacing rhythm) and always win on safety;
|
|
160
|
+
the style pack owns **identity** and wins on look. Both decisions land in the
|
|
161
|
+
compliance table. Full protocol:
|
|
162
|
+
[visual-identity.md](plugins/super-ux/skills/references/visual-identity.md).
|
|
163
|
+
|
|
164
|
+
## What's inside
|
|
165
|
+
|
|
166
|
+
Four skills, one entry point, and a set of contracts they all obey.
|
|
167
|
+
|
|
168
|
+
| Piece | Purpose |
|
|
169
|
+
|---|---|
|
|
170
|
+
| skill `ux-foundation` | The WHY layer (`docs/ux/foundation.md`): personas, jobs to be done with forces, customer journey maps, user stories with Given/When/Then acceptance criteria, the monetization model |
|
|
171
|
+
| skill `ux-flows` | The HOW layer + the UI map: `docs/ux/flows.md` (task analysis, mermaid flows referencing screens by ID) and `docs/ux/screens.md` — every screen and state with its Figma frame, wireframe, code coverage, scenarios and resources. Also heuristic evaluation and traced redesign proposals |
|
|
172
|
+
| skill `ux-scenarios` | `docs/ux/scenarios.md`: use-case scenarios (action → observable response, alt and error paths) covering every flow node and edge, `Traces:` to stories and flows, validated for conflicts, coverage and traceability |
|
|
173
|
+
| skill `ux-audit` | Batched audit with full context: code vs every scenario plus its story's acceptance criteria; verdicts PASS / PARTIAL / FAIL / BLOCKED with `file:line` evidence; depths `quick` / `standard` / `deep`; a `coverage` scope that audits the chain itself |
|
|
174
|
+
| `/ux` | **The one command**: sets up whatever is missing, reports status across every layer, then offers only the applicable actions with one marked recommended. Idempotent |
|
|
175
|
+
| `/ux-init` `/ux-foundation` `/ux-flows` `/ux-update` `/ux-audit` `/ux-rule` `/ux-lint` | Direct controls for when you know exactly what you want; `/ux-rule` installs the hard rule into `CLAUDE.md` |
|
|
176
|
+
| `docs/ux/lint.py` + `/ux-lint` | The deterministic half: missing Figma frames, unresolved SCR/story traces, orphans, built screens without coverage, index desync, ID gaps, broken links. Stdlib-only, exit 1 on problems — wire it into CI so drift can't merge |
|
|
177
|
+
| `cursor/rules/*.mdc` | The same methodology for Cursor: one always-on hard rule + four agent-requested rules |
|
|
178
|
+
| `templates/` | Seeds for `docs/ux/`: foundation, flows, screens, scenario base, the folder README, the audit-report skeleton, and the CLAUDE.md rule snippet |
|
|
179
|
+
|
|
180
|
+
The contracts every skill reads:
|
|
181
|
+
|
|
182
|
+
| Reference | Holds |
|
|
183
|
+
|---|---|
|
|
184
|
+
| [scenario-format.md](plugins/super-ux/skills/references/scenario-format.md) | **The contract (ux-contract v4).** File layout, every field name, stable IDs (`P` `JTBD` `JRN` `ST` `FLW` `SCR` `SCN`), completeness checklists, the `draft → validated → implemented` lifecycle, audit verdicts and severities, the UX-plan format |
|
|
185
|
+
| [system-map.md](plugins/super-ux/skills/references/system-map.md) | The whole system on one page — pipeline, files, skills, companions, and the four sync rules; every skill points here |
|
|
186
|
+
| [ux-design-principles.md](plugins/super-ux/skills/references/ux-design-principles.md) | How the agent thinks: the design pipeline (forward and backwards), task analysis, flow rules, heuristics PRN-01..16, the improvement procedure, anti-patterns |
|
|
187
|
+
| [best-practices.md](plugins/super-ux/skills/references/best-practices.md) | Living, tag-indexed catalog of 115 proven practices — subscription-app laws, mobile/web/voice guidance (Apple HIG 2025, M3 Expressive, NN/g, Baymard, WCAG 2.2), monetization economics (RevenueCat/PLG 2025 benchmarks, ASO, freemium boundaries, web2app), visual craft, Figma structure |
|
|
188
|
+
| [practice-selection.md](plugins/super-ux/skills/references/practice-selection.md) | The deterministic bridge: product profile → mandatory consideration sets → per-artifact checklists → a compliance table where every pulled practice gets a verdict. No silent skips, no cargo cult |
|
|
189
|
+
| [component-guidelines.md](plugins/super-ux/skills/references/component-guidelines.md) | Which control for which job (radios/select/switch, sheet/alert, modal/disclosure, combobox, nav bar/rail, FAB, dates, toasts) and the platform rules — Apple HIG, Material 3, W3C ARIA APG, GOV.UK |
|
|
190
|
+
| [visual-identity.md](plugins/super-ux/skills/references/visual-identity.md) | The visual layer and its owner: one style pack for the whole product, where it's recorded, how it meets Figma and code, and the division of labor with the craft floors |
|
|
191
|
+
| [figma-integration.md](plugins/super-ux/skills/references/figma-integration.md) · [figma-structure.md](plugins/super-ux/skills/references/figma-structure.md) | The optional Figma surface (on by default): when and how to mock up, and how to structure the file so frames named `SCR-NN/<Screen>/<state>` map 1:1 to `screens.md` — deterministic lookup, checkable drift |
|
|
192
|
+
|
|
193
|
+
## Keeping installs current
|
|
194
|
+
|
|
195
|
+
Global channels (run after a release, then restart the Claude Code session so
|
|
196
|
+
the plugin reloads):
|
|
113
197
|
|
|
114
198
|
```sh
|
|
115
|
-
|
|
199
|
+
claude plugin marketplace update super-ux && \
|
|
200
|
+
claude plugin update super-ux@super-ux && \
|
|
201
|
+
npx --yes skills update ux-audit ux-flows ux-foundation ux-scenarios --global --yes
|
|
116
202
|
```
|
|
117
203
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
three rules into `.cursor/rules/` and seeds `docs/ux/scenarios.md`. An
|
|
121
|
-
existing scenario base is never overwritten; re-run with `--force` to update
|
|
122
|
-
rules after a new release.
|
|
204
|
+
Cursor rules and the seeded `docs/ux/lint.py` are per-project (Cursor has no
|
|
205
|
+
global rules directory) — refresh each project you use:
|
|
123
206
|
|
|
124
|
-
|
|
207
|
+
```sh
|
|
208
|
+
npx super-ux@latest --cursor /path/to/your/project --force
|
|
209
|
+
```
|
|
125
210
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
очередь". The agent asks at most one clarifying question, picks the right
|
|
130
|
-
workflow itself, and only shows you human decisions (approve scenarios,
|
|
131
|
-
pick a plan). Everything below this line is internals for the agent.
|
|
211
|
+
`--force` replaces the rule files and the linter; your scenario base and the
|
|
212
|
+
rest of `docs/ux/` are never touched. Check the published version with
|
|
213
|
+
`npm view super-ux version`.
|
|
132
214
|
|
|
133
|
-
##
|
|
215
|
+
## Contributing
|
|
134
216
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
— the validator enforces the sync.
|
|
158
|
-
|
|
159
|
-
## По-русски (коротко)
|
|
160
|
-
|
|
161
|
-
Проблема: агенты генерируют плохие интерфейсы, потому что строят UI без
|
|
162
|
-
модели поведения пользователя. super-ux строит цепочку: **персоны → JTBD →
|
|
163
|
-
карта пути → user stories → UX-сценарии → аудиты → планы фиксов**.
|
|
164
|
-
Foundation (`docs/ux/foundation.md`) отвечает на «зачем», сценарии
|
|
165
|
-
(`docs/ux/scenarios.md`) — источник правды поведения, трассируются к
|
|
166
|
-
stories. Всё пишется и валидируется **до** интерфейса, обновляется тем же
|
|
167
|
-
изменением, что и поведение. Аудиты (`/ux-audit`) проверяют код против
|
|
168
|
-
сценариев вместе с acceptance criteria, вердикты PASS/PARTIAL/FAIL/BLOCKED
|
|
169
|
-
с доказательствами `file:line`; `/ux-audit coverage` ищет дыры в самой
|
|
170
|
-
цепочке. Установка: в
|
|
171
|
-
Claude Code — `/plugin marketplace add ssheleg/super-ux`, в Cursor —
|
|
172
|
-
`npx super-ux --cursor <проект>`. Дальше одна команда — `/ux`: сама ставит
|
|
173
|
-
правило и базу, а при повторных запусках показывает статус и следующий шаг.
|
|
217
|
+
Issues and pull requests are welcome — see [CONTRIBUTING.md](CONTRIBUTING.md)
|
|
218
|
+
for the repo layout, the validator, and the release checklist. Everyone taking
|
|
219
|
+
part is expected to follow the [Code of Conduct](CODE_OF_CONDUCT.md); to report a
|
|
220
|
+
vulnerability, see [SECURITY.md](SECURITY.md). In short:
|
|
221
|
+
`python3 test/validate.py` must pass (CI runs it on every push and PR), and
|
|
222
|
+
edits to `plugins/super-ux/skills/references/` need
|
|
223
|
+
`python3 test/sync_references.py` to refresh the per-skill copies.
|
|
224
|
+
|
|
225
|
+
## Author
|
|
226
|
+
|
|
227
|
+
Built by ssheleg — [sshlg.me](https://sshlg.me)
|
|
228
|
+
|
|
229
|
+
- X / Twitter — [@fuck_this_year](https://x.com/fuck_this_year)
|
|
230
|
+
- Telegram — [@sshlg](https://t.me/sshlg)
|
|
231
|
+
|
|
232
|
+
Part of the [ssheleg skill family](https://github.com/ssheleg/sshlg-skills):
|
|
233
|
+
`super-ux`, `task-pipeline`, `make-skill`, `sheleg-design`, `seo-aeo-audit`.
|
|
234
|
+
One command installs all five for every agent you use:
|
|
235
|
+
|
|
236
|
+
```bash
|
|
237
|
+
npx sshlg-skills install
|
|
238
|
+
```
|
|
174
239
|
|
|
175
240
|
## License
|
|
176
241
|
|
package/bin/super-ux.js
CHANGED
|
@@ -74,7 +74,9 @@ function installCursor(target, force) {
|
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
-
|
|
77
|
+
for (const dir of ['audits', 'plans']) {
|
|
78
|
+
fs.mkdirSync(path.join(target, 'docs', 'ux', dir), { recursive: true });
|
|
79
|
+
}
|
|
78
80
|
for (const tpl of ['scenarios', 'foundation', 'flows', 'screens', 'README']) {
|
|
79
81
|
const dst = path.join(target, 'docs', 'ux', `${tpl}.md`);
|
|
80
82
|
if (fs.existsSync(dst)) {
|
|
@@ -85,9 +87,19 @@ function installCursor(target, force) {
|
|
|
85
87
|
}
|
|
86
88
|
}
|
|
87
89
|
// The linter is code, not a template — refresh it to the shipped version.
|
|
90
|
+
// Shipped via package.json files[]; if that ever regresses, warn instead of
|
|
91
|
+
// dying on an ENOENT stack trace after the rules are already installed.
|
|
92
|
+
const lintSrc = path.join(ROOT, 'plugins', 'super-ux', 'scripts', 'ux_lint.py');
|
|
88
93
|
const lintDst = path.join(target, 'docs', 'ux', 'lint.py');
|
|
89
|
-
fs.
|
|
90
|
-
|
|
94
|
+
if (fs.existsSync(lintSrc)) {
|
|
95
|
+
fs.copyFileSync(lintSrc, lintDst);
|
|
96
|
+
console.log(`sync: ${lintDst}`);
|
|
97
|
+
} else {
|
|
98
|
+
console.error(
|
|
99
|
+
`warning: linter not found in this package (${lintSrc}); docs/ux/lint.py was not installed.\n` +
|
|
100
|
+
` Get it from https://github.com/${REPO}/blob/main/plugins/super-ux/scripts/ux_lint.py`
|
|
101
|
+
);
|
|
102
|
+
}
|
|
91
103
|
|
|
92
104
|
console.log(`done: ${installed} installed, ${skipped} skipped`);
|
|
93
105
|
}
|
|
@@ -8,6 +8,12 @@ alwaysApply: true
|
|
|
8
8
|
- `docs/ux/scenarios.md` is the source of truth for all user-facing behavior;
|
|
9
9
|
`docs/ux/foundation.md` (personas, JTBD, journeys, user stories) is the WHY
|
|
10
10
|
layer scenarios trace to.
|
|
11
|
+
- `docs/ux/screens.md` is the UI map: every screen + state with its wireframe
|
|
12
|
+
and (Figma on) its frame link. A screen that changes in code changes here in
|
|
13
|
+
the SAME change.
|
|
14
|
+
- Run the linter after any UX change and before calling work done:
|
|
15
|
+
`python3 docs/ux/lint.py`. It must pass — drift must not merge; wire it
|
|
16
|
+
into CI/pre-commit.
|
|
11
17
|
- Any change that touches user-facing behavior MUST update
|
|
12
18
|
`docs/ux/scenarios.md` in the same change (add/adjust scenarios, statuses,
|
|
13
19
|
coverage). New user-facing behavior with no scenario is a blocker, not a
|
|
@@ -17,10 +23,15 @@ alwaysApply: true
|
|
|
17
23
|
against the existing base (conflicts, overlaps, gaps), approved. An idea
|
|
18
24
|
serving no job is challenged, not silently accepted.
|
|
19
25
|
- Do NOT write interface code until the UX workflow is done first: the
|
|
20
|
-
foundation → flows → scenarios chain is designed and approved,
|
|
21
|
-
Figma is enabled (default) — the UI is mocked up in Figma with
|
|
22
|
-
screen linked to its frame. Building UI before this is the exact
|
|
23
|
-
super-ux exists to prevent.
|
|
26
|
+
foundation → flows → screens → scenarios chain is designed and approved,
|
|
27
|
+
and — when Figma is enabled (default) — the UI is mocked up in Figma with
|
|
28
|
+
every screen linked to its frame. Building UI before this is the exact
|
|
29
|
+
mistake super-ux exists to prevent.
|
|
30
|
+
- Visual identity is one locked style pack, recorded once in `screens.md` →
|
|
31
|
+
Design system and used by every frame and every built screen — picked with
|
|
32
|
+
the **sheleg-design** companion skill (`npx sheleg-design-skill`) when the
|
|
33
|
+
project has no design system of its own. Recommended, never forced; a
|
|
34
|
+
palette invented per screen is visual drift.
|
|
24
35
|
- Workflows: `ux-foundation` rule (WHY), `ux-flows` rule (flows + Figma
|
|
25
|
-
mockups), `ux-scenarios` rule (scenario base), `ux-audit` rule
|
|
36
|
+
mockups + style pack), `ux-scenarios` rule (scenario base), `ux-audit` rule
|
|
26
37
|
(evidence-backed audits).
|
|
@@ -15,8 +15,9 @@ verdict BLOCKED with the exact reason. Never guess, never a courtesy PASS.
|
|
|
15
15
|
|
|
16
16
|
## Loop
|
|
17
17
|
|
|
18
|
-
1. Read the base
|
|
19
|
-
|
|
18
|
+
1. Read the base (and foundation/flows/screens when they exist); scope =
|
|
19
|
+
all | feature:<name> | ID range | coverage; note the git SHA of `docs/ux`
|
|
20
|
+
for the report header; skip retired scenarios.
|
|
20
21
|
2. Batch by feature, ~5–8 scenarios per batch; list batches up front.
|
|
21
22
|
3. Per scenario check against the code: entry point reachable; every step
|
|
22
23
|
implemented; every listed UI element present and wired; every listed
|
|
@@ -26,6 +27,12 @@ verdict BLOCKED with the exact reason. Never guess, never a courtesy PASS.
|
|
|
26
27
|
`[AUD-YYYY-MM-DD-NN] (critical|major|minor) description -> suggested fix`.
|
|
27
28
|
4. Verdicts: PASS (complete), PARTIAL (flow exists, gaps), FAIL (missing or
|
|
28
29
|
broken), BLOCKED (cannot verify — say why).
|
|
30
|
+
When `flows.md`/`screens.md` exist, also check conformance: every flow
|
|
31
|
+
node reachable and every edge (error edges included) wired; every
|
|
32
|
+
registered screen's states rendered and its `Coverage` accurate — code
|
|
33
|
+
that diverges from a screen's record is a `drifted` finding. Scope
|
|
34
|
+
`coverage` audits the chain itself (orphan stories/flows/screens/
|
|
35
|
+
scenarios, journey stages without scenarios, personas unused).
|
|
29
36
|
5. Write the report batch by batch: header (scope, method, base SHA),
|
|
30
37
|
Summary (totals, top issues, prioritized next actions), per-batch
|
|
31
38
|
verdicts with evidence, findings-register table.
|
|
@@ -20,8 +20,14 @@ Fields: `Traces` (story/job IDs), `Goal` (observable end state), `Entry
|
|
|
20
20
|
points` (ALL of them), `Success exit`, `Task analysis` (numbered
|
|
21
21
|
user-visible micro-steps), mermaid `flowchart` (screens as
|
|
22
22
|
`Screen: <name>`, decisions as diamonds, `*_err` error nodes with labeled
|
|
23
|
-
recovery edges), `Screens
|
|
24
|
-
|
|
23
|
+
recovery edges), `Screens traversed` table (`| Screen | States used here |`
|
|
24
|
+
— SCR-IDs only; the full per-screen spec lives once in `screens.md`).
|
|
25
|
+
|
|
26
|
+
Each screen entry in `screens.md`: `Used by`, `Purpose`, `Elements` (mark
|
|
27
|
+
the ONE primary action), `States` table (`| State | Trigger | Figma frame |
|
|
28
|
+
Behavior |` — a row per loading/empty/error/success that applies),
|
|
29
|
+
`Wireframe`, `Coverage` (file:line), `Scenarios`, `Resources`, `Status`
|
|
30
|
+
(designed|built|drifted|retired).
|
|
25
31
|
|
|
26
32
|
## Design rules
|
|
27
33
|
|
|
@@ -33,9 +39,20 @@ loading/empty/error/success + key elements, one primary action).
|
|
|
33
39
|
- Wireframes optional (`docs/ux/wireframes/FLW-NN.md`, ASCII hierarchy +
|
|
34
40
|
primary action, not pixels); storyboard only when usage context drives
|
|
35
41
|
design.
|
|
42
|
+
- Visual identity BEFORE any frame: `screens.md` → Design system →
|
|
43
|
+
`Style pack`. Empty and no design system in the project → pick a pack with
|
|
44
|
+
the **sheleg-design** companion skill (`workbench` for product UI /
|
|
45
|
+
dashboards / tools, `instrument-console`, `editorial-luxury`, or a new
|
|
46
|
+
pack on its contract; cinematic scroll pages also take its motion
|
|
47
|
+
methodology) and record the pack + token file. Missing → offer the
|
|
48
|
+
one-time install once (`npx sheleg-design-skill`) and continue on platform
|
|
49
|
+
defaults; recommend, don't force. The pack owns palette/type/motion and
|
|
50
|
+
its bans; BP-079..090 stay the floors it must clear. Never invent a look
|
|
51
|
+
per screen.
|
|
36
52
|
- Figma mockups optional (default on): if the foundation's Design tooling
|
|
37
53
|
enables Figma and a Figma MCP is available, mirror each screen into a
|
|
38
|
-
frame
|
|
54
|
+
frame built on the pack's tokens (they become the Figma variable
|
|
55
|
+
collections) applying visual-craft practices (BP-079..090), and link every
|
|
39
56
|
screen row to its frame; ask the user once at the start of design.
|
|
40
57
|
- Backwards mode (existing product): reconstruct flows as they ARE from
|
|
41
58
|
code with file:line evidence, tag `inferred` until confirmed; gaps
|
|
@@ -42,6 +42,13 @@ deleted.
|
|
|
42
42
|
INVEST, observable criteria), coverage (persona→job→journey→story chain
|
|
43
43
|
complete; must/should stories have scenarios).
|
|
44
44
|
|
|
45
|
+
Two more sections this file owns, filled when they apply: **Monetization**
|
|
46
|
+
(model + value metric + free boundary + money moments + acquisition
|
|
47
|
+
coherence — each money moment becomes a first-class flow) and **Design
|
|
48
|
+
tooling** (the Figma on/off choice, default on, plus the project's Figma file
|
|
49
|
+
URL — asked once per project). Everything else about the visual layer, the
|
|
50
|
+
design system and the style pack, lives in `docs/ux/screens.md`.
|
|
51
|
+
|
|
45
52
|
Evidence beats opinion: mark unvalidated guesses as assumptions
|
|
46
53
|
(desirability/viability/feasibility/usability) and test risky ones before
|
|
47
54
|
building on them.
|
|
@@ -8,7 +8,7 @@ alwaysApply: false
|
|
|
8
8
|
`docs/ux/scenarios.md` describes everything the user can do, see, and hit —
|
|
9
9
|
every feature, button, state, error, result. Keep it true.
|
|
10
10
|
|
|
11
|
-
## File structure (
|
|
11
|
+
## File structure (ux-contract v4)
|
|
12
12
|
|
|
13
13
|
Title, then header comment, then: **Index** table
|
|
14
14
|
(`| ID | Title | Feature | Persona | Traces | Status | Last audit |`),
|
|
@@ -21,8 +21,10 @@ JRN-01/#2)`), enforce traceability — every must/should story covered by ≥1
|
|
|
21
21
|
scenario, every scenario serves ≥1 story or job.
|
|
22
22
|
|
|
23
23
|
Scenario entry fields (exact names): `Persona`, `Feature`, `Traces`, `Entry point`,
|
|
24
|
-
`Preconditions`, `Steps` (numbered, one user action each
|
|
25
|
-
|
|
24
|
+
`Preconditions`, `Steps` (numbered, one user action each, paired with the
|
|
25
|
+
observable system response), `Expected result` (observable), `Alt paths`
|
|
26
|
+
(meaningful non-error deviations — skip/dismiss/alternate route — omit only
|
|
27
|
+
when none exist), `UI elements` (every button/field/link/dialog/toast involved —
|
|
26
28
|
this is what audits check), `States covered` (loading|empty|error|success),
|
|
27
29
|
`Errors & recovery` (each failure: what the user sees, how they recover),
|
|
28
30
|
`Status` (draft|validated|implemented|retired), `Coverage` (file:line or
|
|
@@ -35,7 +37,10 @@ never deleted. Lifecycle: draft → validated (human approval) → implemented
|
|
|
35
37
|
Per-feature completeness: happy path, every error path, empty state, visible
|
|
36
38
|
loading, destructive-action confirmation, returning-user variant.
|
|
37
39
|
Per-product: first-run onboarding, every core flow, settings, multi-entity
|
|
38
|
-
flows (e.g. second project), account/data lifecycle
|
|
40
|
+
flows (e.g. second project), account/data lifecycle, and — when the product
|
|
41
|
+
earns money — the monetization flows: paywall (first-session placement),
|
|
42
|
+
trial start/end, upgrade-at-limit, cancel + winback, rating prompt after
|
|
43
|
+
success moments.
|
|
39
44
|
|
|
40
45
|
## Workflows
|
|
41
46
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "super-ux",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Scenario-driven UI development for AI agents (Claude Code +
|
|
3
|
+
"version": "0.23.2",
|
|
4
|
+
"description": "Scenario-driven UI development for AI agents (Claude Code, Cursor, 70+ agents): a versioned design chain in docs/ux/, a scenario-first hard rule, a deterministic drift linter, and evidence-backed UX audits. This package is the installer CLI.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"super-ux": "bin/super-ux.js"
|
|
7
7
|
},
|
|
@@ -9,12 +9,16 @@
|
|
|
9
9
|
"bin",
|
|
10
10
|
"cursor",
|
|
11
11
|
"templates",
|
|
12
|
+
"plugins/super-ux/scripts/ux_lint.py",
|
|
12
13
|
"README.md",
|
|
13
14
|
"LICENSE",
|
|
14
15
|
"CHANGELOG.md"
|
|
15
16
|
],
|
|
16
17
|
"repository": "github:ssheleg/super-ux",
|
|
17
18
|
"homepage": "https://github.com/ssheleg/super-ux",
|
|
19
|
+
"bugs": {
|
|
20
|
+
"url": "https://github.com/ssheleg/super-ux/issues"
|
|
21
|
+
},
|
|
18
22
|
"license": "MIT",
|
|
19
23
|
"author": "ssheleg",
|
|
20
24
|
"engines": {
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""super-ux linter — checks a target project's docs/ux/ for integrity and drift.
|
|
3
|
+
|
|
4
|
+
Deterministic enforcement of the ux-contract: run it after any UX change and
|
|
5
|
+
before calling the work done, and wire it into the project's CI/pre-commit.
|
|
6
|
+
It turns the prose rules (same-change, no lost Figma, no orphans, no drift)
|
|
7
|
+
into a check that fails.
|
|
8
|
+
|
|
9
|
+
Usage:
|
|
10
|
+
python3 docs/ux/lint.py # lint ./docs/ux
|
|
11
|
+
python3 docs/ux/lint.py <dir> # lint <dir> (a docs/ux directory or its parent)
|
|
12
|
+
python3 docs/ux/lint.py --strict # warnings also fail (exit 1)
|
|
13
|
+
|
|
14
|
+
Exit codes: 0 clean (warnings allowed unless --strict), 1 problems found,
|
|
15
|
+
2 no UX docs at all (run /ux first). Stdlib only; tolerant parsing — reports
|
|
16
|
+
what it can and never crashes on malformed markdown.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from __future__ import annotations
|
|
20
|
+
|
|
21
|
+
import re
|
|
22
|
+
import sys
|
|
23
|
+
from pathlib import Path
|
|
24
|
+
|
|
25
|
+
ERRORS: list[str] = []
|
|
26
|
+
WARNS: list[str] = []
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def err(msg: str) -> None:
|
|
30
|
+
ERRORS.append(msg)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def warn(msg: str) -> None:
|
|
34
|
+
WARNS.append(msg)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def read(path: Path) -> str:
|
|
38
|
+
try:
|
|
39
|
+
text = path.read_text(encoding="utf-8")
|
|
40
|
+
except OSError:
|
|
41
|
+
return ""
|
|
42
|
+
# Strip HTML comments so template examples (shipped commented-out) and
|
|
43
|
+
# notes are never parsed as real entries.
|
|
44
|
+
return re.sub(r"<!--.*?-->", "", text, flags=re.DOTALL)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def find_ux_dir(arg: str | None) -> Path | None:
|
|
48
|
+
base = Path(arg) if arg else Path.cwd()
|
|
49
|
+
for cand in (base, base / "docs" / "ux", base.parent if base.name else base):
|
|
50
|
+
if (cand / "scenarios.md").exists() or (cand / "foundation.md").exists():
|
|
51
|
+
return cand
|
|
52
|
+
return None
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def ids(text: str, prefix: str) -> list[str]:
|
|
56
|
+
"""All '### PREFIX-NN:' entry ids, in order."""
|
|
57
|
+
return re.findall(rf"^###\s+({prefix}-\d+):", text, re.MULTILINE)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def index_ids(text: str, prefix: str) -> set[str]:
|
|
61
|
+
"""Ids appearing in a leading '| PREFIX-NN |' index-table cell."""
|
|
62
|
+
return set(re.findall(rf"^\|\s*({prefix}-\d+)\s*\|", text, re.MULTILINE))
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def refs(text: str, prefix: str) -> set[str]:
|
|
66
|
+
"""Every PREFIX-NN token mentioned anywhere."""
|
|
67
|
+
return set(re.findall(rf"\b({prefix}-\d+)\b", text))
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def check_unique_and_gaps(entry_ids: list[str], label: str) -> None:
|
|
71
|
+
seen: dict[str, int] = {}
|
|
72
|
+
for i in entry_ids:
|
|
73
|
+
seen[i] = seen.get(i, 0) + 1
|
|
74
|
+
for i, n in seen.items():
|
|
75
|
+
if n > 1:
|
|
76
|
+
err(f"{label}: duplicate id {i} ({n} entries)")
|
|
77
|
+
nums = sorted(int(i.split("-")[1]) for i in seen)
|
|
78
|
+
if nums:
|
|
79
|
+
missing = [n for n in range(1, max(nums) + 1) if n not in nums]
|
|
80
|
+
if missing:
|
|
81
|
+
warn(f"{label}: id gaps (retired entries should stay): {missing}")
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def figma_enabled(foundation: str) -> bool | None:
|
|
85
|
+
"""True/False from foundation Design tooling; None if unstated (default-on)."""
|
|
86
|
+
m = re.search(r"\*\*Figma:\*\*\s*(enabled|disabled)", foundation, re.IGNORECASE)
|
|
87
|
+
if not m:
|
|
88
|
+
return None
|
|
89
|
+
return m.group(1).lower() == "enabled"
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def screen_blocks(text: str) -> dict[str, str]:
|
|
93
|
+
"""Map SCR-id -> its section body (from its header to the next ### / ##)."""
|
|
94
|
+
out: dict[str, str] = {}
|
|
95
|
+
parts = re.split(r"^###\s+(SCR-\d+):", text, flags=re.MULTILINE)
|
|
96
|
+
# parts = [pre, id1, body1, id2, body2, ...]
|
|
97
|
+
for i in range(1, len(parts), 2):
|
|
98
|
+
sid = parts[i]
|
|
99
|
+
body = parts[i + 1] if i + 1 < len(parts) else ""
|
|
100
|
+
body = re.split(r"^##\s", body, maxsplit=1, flags=re.MULTILINE)[0]
|
|
101
|
+
out[sid] = body
|
|
102
|
+
return out
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def check_links(ux: Path) -> None:
|
|
106
|
+
link_re = re.compile(r"\[[^\]]*\]\(([^)\s]+)\)")
|
|
107
|
+
for md in sorted(ux.rglob("*.md")):
|
|
108
|
+
text = read(md)
|
|
109
|
+
for target in link_re.findall(text):
|
|
110
|
+
if target.startswith(("http://", "https://", "#", "mailto:")):
|
|
111
|
+
continue
|
|
112
|
+
resolved = (md.parent / target.split("#", 1)[0]).resolve()
|
|
113
|
+
if not resolved.exists():
|
|
114
|
+
warn(f"{md.name}: broken link -> {target}")
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def main() -> int:
|
|
118
|
+
args = [a for a in sys.argv[1:] if not a.startswith("-")]
|
|
119
|
+
strict = "--strict" in sys.argv[1:]
|
|
120
|
+
ux = find_ux_dir(args[0] if args else None)
|
|
121
|
+
if ux is None:
|
|
122
|
+
print("no UX docs found (docs/ux/scenarios.md). Run /ux to set up.")
|
|
123
|
+
return 2
|
|
124
|
+
|
|
125
|
+
foundation = read(ux / "foundation.md")
|
|
126
|
+
flows = read(ux / "flows.md")
|
|
127
|
+
screens = read(ux / "screens.md")
|
|
128
|
+
scenarios = read(ux / "scenarios.md")
|
|
129
|
+
|
|
130
|
+
has_flows = bool(ids(flows, "FLW"))
|
|
131
|
+
has_screens = bool(ids(screens, "SCR"))
|
|
132
|
+
has_stories = bool(ids(foundation, "ST"))
|
|
133
|
+
|
|
134
|
+
# --- ID integrity ---
|
|
135
|
+
for text, pref, label in [
|
|
136
|
+
(scenarios, "SCN", "scenarios.md"),
|
|
137
|
+
(flows, "FLW", "flows.md"),
|
|
138
|
+
(screens, "SCR", "screens.md"),
|
|
139
|
+
(foundation, "ST", "foundation.md/stories"),
|
|
140
|
+
(foundation, "JTBD", "foundation.md/jobs"),
|
|
141
|
+
]:
|
|
142
|
+
entry_ids = ids(text, pref)
|
|
143
|
+
if entry_ids:
|
|
144
|
+
check_unique_and_gaps(entry_ids, label)
|
|
145
|
+
|
|
146
|
+
# --- Index <-> entries sync (scenarios, screens) ---
|
|
147
|
+
for text, pref, name in [(scenarios, "SCN", "scenarios.md"), (screens, "SCR", "screens.md")]:
|
|
148
|
+
entries = set(ids(text, pref))
|
|
149
|
+
if not entries:
|
|
150
|
+
continue
|
|
151
|
+
idx = index_ids(text, pref)
|
|
152
|
+
for missing in sorted(entries - idx):
|
|
153
|
+
warn(f"{name}: {missing} has no index row")
|
|
154
|
+
for ghost in sorted(idx - entries):
|
|
155
|
+
err(f"{name}: index lists {ghost} but no entry exists")
|
|
156
|
+
|
|
157
|
+
# --- Flows reference existing screens ---
|
|
158
|
+
if has_flows and has_screens:
|
|
159
|
+
screen_ids = set(ids(screens, "SCR"))
|
|
160
|
+
used = refs(flows, "SCR")
|
|
161
|
+
for miss in sorted(used - screen_ids):
|
|
162
|
+
err(f"flows.md references {miss} but screens.md has no such screen")
|
|
163
|
+
for orphan in sorted(screen_ids - used):
|
|
164
|
+
warn(f"screens.md: {orphan} is used by no flow (orphan)")
|
|
165
|
+
|
|
166
|
+
# --- Scenario traces resolve ---
|
|
167
|
+
if ids(scenarios, "SCN"):
|
|
168
|
+
story_ids = set(ids(foundation, "ST"))
|
|
169
|
+
flow_ids = set(ids(flows, "FLW"))
|
|
170
|
+
traced_st = refs(scenarios, "ST")
|
|
171
|
+
traced_flw = refs(scenarios, "FLW")
|
|
172
|
+
if has_stories:
|
|
173
|
+
for miss in sorted(traced_st - story_ids):
|
|
174
|
+
warn(f"scenarios.md: traces to {miss} which is not in foundation.md")
|
|
175
|
+
if has_flows:
|
|
176
|
+
for miss in sorted(traced_flw - flow_ids):
|
|
177
|
+
warn(f"scenarios.md: traces to {miss} which is not in flows.md")
|
|
178
|
+
|
|
179
|
+
# --- must/should stories have a scenario ---
|
|
180
|
+
if has_stories and ids(scenarios, "SCN"):
|
|
181
|
+
traced = refs(scenarios, "ST")
|
|
182
|
+
for m in re.finditer(r"^###\s+(ST-\d+):", foundation, re.MULTILINE):
|
|
183
|
+
sid = m.group(1)
|
|
184
|
+
# Only this story's own body: stop at the next heading, so a
|
|
185
|
+
# neighbor's Priority line is never read as this story's.
|
|
186
|
+
tail = re.split(r"^#{2,3}\s", foundation[m.end():], maxsplit=1, flags=re.MULTILINE)[0]
|
|
187
|
+
if re.search(r"\*\*Priority:\*\*\s*(must|should)", tail, re.IGNORECASE):
|
|
188
|
+
if sid not in traced:
|
|
189
|
+
warn(f"foundation.md: {sid} (must/should) has no scenario tracing to it")
|
|
190
|
+
|
|
191
|
+
# --- Screen-level: Figma frames, coverage, drift status ---
|
|
192
|
+
if has_screens:
|
|
193
|
+
fig = figma_enabled(foundation)
|
|
194
|
+
for sid, body in screen_blocks(screens).items():
|
|
195
|
+
status_m = re.search(r"\*\*Status:\*\*\s*(designed|built|drifted|retired)", body)
|
|
196
|
+
status = status_m.group(1) if status_m else None
|
|
197
|
+
if status == "retired":
|
|
198
|
+
continue
|
|
199
|
+
# every state row present in the States table
|
|
200
|
+
state_rows = re.findall(r"^\s*\|\s*(loading|empty|error|success)\s*\|(.*)\|\s*$",
|
|
201
|
+
body, re.MULTILINE | re.IGNORECASE)
|
|
202
|
+
if fig is not False: # enabled or default-on
|
|
203
|
+
for state, rest in state_rows:
|
|
204
|
+
cells = [c.strip() for c in rest.split("|")]
|
|
205
|
+
frame = cells[1] if len(cells) >= 2 else ""
|
|
206
|
+
if not frame or frame in ("-", "—", "<frame deep-link>", "<frame link>"):
|
|
207
|
+
err(f"screens.md: {sid} state '{state}' has no Figma frame link")
|
|
208
|
+
cov_m = re.search(r"\*\*Coverage:\*\*\s*(.+)", body)
|
|
209
|
+
cov = cov_m.group(1).strip() if cov_m else ""
|
|
210
|
+
if status == "built" and (not cov or cov.lower().startswith("none")):
|
|
211
|
+
warn(f"screens.md: {sid} is 'built' but has no Coverage")
|
|
212
|
+
|
|
213
|
+
check_links(ux)
|
|
214
|
+
|
|
215
|
+
# --- Report ---
|
|
216
|
+
for e in ERRORS:
|
|
217
|
+
print(f"ERROR: {e}")
|
|
218
|
+
for w in WARNS:
|
|
219
|
+
print(f"warn: {w}")
|
|
220
|
+
total = len(ERRORS) + len(WARNS)
|
|
221
|
+
if not total:
|
|
222
|
+
print(f"OK — docs/ux is consistent ({ux})")
|
|
223
|
+
return 0
|
|
224
|
+
print(f"\n{len(ERRORS)} error(s), {len(WARNS)} warning(s)")
|
|
225
|
+
if ERRORS or (strict and WARNS):
|
|
226
|
+
return 1
|
|
227
|
+
return 0
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
if __name__ == "__main__":
|
|
231
|
+
sys.exit(main())
|
package/templates/README.md
CHANGED
|
@@ -12,7 +12,7 @@ Personas · JTBD · Journeys · Stories → Flows → Screens → Scenario
|
|
|
12
12
|
|
|
13
13
|
| File | Holds |
|
|
14
14
|
|------|-------|
|
|
15
|
-
| `foundation.md` | WHO & WHY: personas, jobs-to-be-done, journeys, user stories, monetization, Figma on/off |
|
|
15
|
+
| `foundation.md` | WHO & WHY: personas, jobs-to-be-done, journeys, user stories, monetization, Figma on/off + file URL |
|
|
16
16
|
| `flows.md` | HOW: user-flow diagrams (screens, branches, error paths), referencing screens by `SCR-ID` |
|
|
17
17
|
| `screens.md` | THE UI MAP: every screen and state with its Figma frame link, wireframe, code coverage, scenarios, resources |
|
|
18
18
|
| `scenarios.md` | WHAT EXACTLY: use-case scenarios — the source of truth for behavior |
|
|
@@ -29,7 +29,9 @@ Personas · JTBD · Journeys · Stories → Flows → Screens → Scenario
|
|
|
29
29
|
`scenarios.md`, affected flows, the affected screens in `screens.md`,
|
|
30
30
|
and (Figma on) the Figma frame plus its link — together, not later.
|
|
31
31
|
3. **No drift.** Code that diverges from a screen's record, or a stale Figma
|
|
32
|
-
link, is a bug to fix.
|
|
32
|
+
link, is a bug to fix. The same goes for the look: one style pack is
|
|
33
|
+
recorded in `screens.md` → Design system (pick it with the
|
|
34
|
+
**sheleg-design** skill) and every screen obeys it.
|
|
33
35
|
4. **Lint it.** Run `python3 docs/ux/lint.py` after changes and in CI.
|
|
34
36
|
|
|
35
37
|
Maintained with the super-ux plugin. In Claude Code, run `/ux`.
|
package/templates/claude-rule.md
CHANGED
|
@@ -14,10 +14,15 @@
|
|
|
14
14
|
serve, which journey stage, which story — then flows and scenarios,
|
|
15
15
|
validated against the existing base, approved.
|
|
16
16
|
- **Do NOT write interface code until the UX workflow is done first:** the
|
|
17
|
-
foundation → flows → scenarios chain is designed and approved,
|
|
18
|
-
Figma is enabled (default) — the UI is mocked up in Figma with
|
|
19
|
-
screen linked to its frame. Building UI before this is the exact
|
|
20
|
-
super-ux exists to prevent.
|
|
17
|
+
foundation → flows → screens → scenarios chain is designed and approved,
|
|
18
|
+
and — when Figma is enabled (default) — the UI is mocked up in Figma with
|
|
19
|
+
every screen linked to its frame. Building UI before this is the exact
|
|
20
|
+
mistake super-ux exists to prevent.
|
|
21
|
+
- Visual identity is ONE locked style pack, recorded in `docs/ux/screens.md`
|
|
22
|
+
→ Design system and obeyed by every Figma frame and every built screen —
|
|
23
|
+
picked with the **sheleg-design** companion skill when the project has no
|
|
24
|
+
design system of its own (recommended, not required). Inventing a palette,
|
|
25
|
+
type pairing, or motion per screen is visual drift.
|
|
21
26
|
- After any UX change and before calling the work done, run the linter
|
|
22
27
|
`python3 docs/ux/lint.py` — it must pass (errors are drift/broken
|
|
23
28
|
structure; wire it into CI/pre-commit).
|
package/templates/flows.md
CHANGED
package/templates/screens.md
CHANGED
|
@@ -13,6 +13,11 @@ whose code diverges from its record here is a "drifted" finding. -->
|
|
|
13
13
|
|
|
14
14
|
## Design system
|
|
15
15
|
|
|
16
|
+
<!-- Style pack = the locked visual identity every frame and built screen obeys.
|
|
17
|
+
Pick it with the sheleg-design companion skill (workbench for product UI /
|
|
18
|
+
dashboards / tools, instrument-console, editorial-luxury, or a new pack on its
|
|
19
|
+
contract) before drawing anything; record its token file below. -->
|
|
20
|
+
- **Style pack:** <pack name, or "none — platform defaults">
|
|
16
21
|
- **Figma library:** <url/name, or "none — platform defaults">
|
|
17
22
|
- **Tokens in code:** <where color/type/spacing tokens live, e.g. src/theme/tokens.ts>
|
|
18
23
|
- **Component source:** <shared UI components dir, e.g. src/components/>
|