start-vibing 4.2.0 → 4.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/template/.claude/agents/sd-audit.md +167 -4
- package/template/.claude/agents/sd-fix.md +90 -2
- package/template/.claude/agents/sd-research.md +70 -1
- package/template/.claude/skills/mobile-app-patterns/SKILL.md +237 -0
- package/template/.claude/skills/super-design/SKILL.md +27 -9
- package/template/.claude/skills/super-design/references/component-flow-discovery.md +258 -0
- package/template/.claude/skills/super-design/references/design-intelligence-rubric.md +376 -0
- package/template/.claude/skills/super-design/references/design-skills-catalog.md +102 -0
|
@@ -8,7 +8,7 @@ description: >
|
|
|
8
8
|
UX audit (WCAG 2.2 AA, Nielsen heuristics, Baymard, CWV), and synthesized
|
|
9
9
|
overview. Re-audits only what changed since last run. On explicit user request,
|
|
10
10
|
applies surgical fixes with full rollback.
|
|
11
|
-
version: 0.
|
|
11
|
+
version: 0.6.0
|
|
12
12
|
---
|
|
13
13
|
|
|
14
14
|
# super-design
|
|
@@ -18,16 +18,34 @@ version: 0.5.0
|
|
|
18
18
|
Four-phase pipeline with 6 specialist agents:
|
|
19
19
|
|
|
20
20
|
1. **Market research** (sd-research) — auto-detects niche from repo, finds 5–10
|
|
21
|
-
competitors, extracts design language
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
competitors, extracts design language AND component vocabulary (buttons,
|
|
22
|
+
nav, cards, modals, forms, tokens — per competitor × mobile+desktop),
|
|
23
|
+
produces market-analysis.md + component-comparison.md.
|
|
24
|
+
2. **UI/UX audit** (sd-audit) — drives browser via Playwright MCP directly.
|
|
25
|
+
Five layers:
|
|
26
|
+
- Route discovery + static snap (Nielsen + WCAG 2.2 AA + Baymard + CWV)
|
|
27
|
+
- **Step 2.5 component/modal/flow discovery** (Phase A inventory, B modal
|
|
28
|
+
enumeration, C flow exercising, D state matrix, E form coverage) — this
|
|
29
|
+
is where modal contents, empty/loading/error states, and flow errors
|
|
30
|
+
get real evidence instead of "checklist hypothetical".
|
|
31
|
+
- **Step 3g design-intelligence scoring** (17-category rubric → DIS 0–100)
|
|
32
|
+
catches implicit best practices checklists miss (cards-in-flex-col,
|
|
33
|
+
low density, weak CTA hierarchy, vibecode smell).
|
|
34
|
+
- **Step 3h mobile-native audit** (21-item Duolingo/Linear/Arc/Cash-App
|
|
35
|
+
checklist) — replaces "responsive-web-on-a-phone" thinking.
|
|
36
|
+
- C16 ≤ 4 → design-skill advisory finding citing typeui-* selection matrix.
|
|
37
|
+
Produces findings.json + design-intelligence.json with SHOT+QUOTE+SEL+VAL.
|
|
38
|
+
3. **Synthesis** (sd-synthesis) — unifies research + audit + design-intelligence
|
|
39
|
+
into overview.md (per-page DIS table + executive summary).
|
|
26
40
|
4. **Fix** (sd-fix + two-stage verify) — optional. Applies safe fixes with
|
|
27
41
|
technical gates (types/lint/tests) AND semantic verification ("does this
|
|
28
|
-
fix actually resolve the finding, or just mask it?").
|
|
29
|
-
|
|
30
|
-
|
|
42
|
+
fix actually resolve the finding, or just mask it?"). Template families:
|
|
43
|
+
A1-A15 a11y · V1-V8 design · U1-U10 ux · P1-P10 perf · **M1-M15 mobile**
|
|
44
|
+
(cards-in-flex-col → compact list, table-on-mobile → card-per-row,
|
|
45
|
+
centered-modal → bottom-sheet, etc.) · **DSC-1 design-skill advisory**
|
|
46
|
+
(proposes typeui-* direction, never auto-applies — HIGH risk). After each
|
|
47
|
+
successful fix, re-drives Playwright to capture an after-screenshot (full
|
|
48
|
+
page + element crop) and emits `docs/super-design/sessions/<id>/fix-report.md`:
|
|
31
49
|
a self-contained visual diff with before/after images, file diffs,
|
|
32
50
|
verification status, and commit SHA per finding.
|
|
33
51
|
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
# Component, Modal & Flow Discovery Playbook
|
|
2
|
+
|
|
3
|
+
> How sd-audit systematically exercises EVERY interactive element before
|
|
4
|
+
> running heuristics. Without this, the audit only sees static page snaps
|
|
5
|
+
> and misses modal contents, flow state, hover/focus/active variants, and
|
|
6
|
+
> loading/empty/error states.
|
|
7
|
+
>
|
|
8
|
+
> This playbook runs as **Step 2.5** in sd-audit, after route discovery
|
|
9
|
+
> and before per-viewport heuristic passes.
|
|
10
|
+
|
|
11
|
+
## Why this matters
|
|
12
|
+
|
|
13
|
+
Static screenshots of pages show ~30% of what users interact with. The other 70%
|
|
14
|
+
lives inside modals, drawers, dropdowns, command palettes, error flows, empty
|
|
15
|
+
states, loading states, hover menus, focus rings. A page can score 95/100 on
|
|
16
|
+
Lighthouse and be unusable because its "Create" modal is broken — and the
|
|
17
|
+
auditor never opened it.
|
|
18
|
+
|
|
19
|
+
## Discovery phases
|
|
20
|
+
|
|
21
|
+
### Phase A — Interactive inventory (per page × viewport)
|
|
22
|
+
|
|
23
|
+
After navigating and dismissing banners:
|
|
24
|
+
|
|
25
|
+
```js
|
|
26
|
+
// browser_evaluate
|
|
27
|
+
(() => {
|
|
28
|
+
const roots = [
|
|
29
|
+
'[role="button"]',
|
|
30
|
+
'button',
|
|
31
|
+
'a[href]',
|
|
32
|
+
'[role="link"]',
|
|
33
|
+
'[role="menuitem"]',
|
|
34
|
+
'[role="tab"]',
|
|
35
|
+
'[role="switch"]',
|
|
36
|
+
'[role="checkbox"]',
|
|
37
|
+
'[role="radio"]',
|
|
38
|
+
'[aria-haspopup]',
|
|
39
|
+
'[aria-expanded]',
|
|
40
|
+
'[data-trigger]',
|
|
41
|
+
'[data-state]',
|
|
42
|
+
'input',
|
|
43
|
+
'select',
|
|
44
|
+
'textarea',
|
|
45
|
+
'summary',
|
|
46
|
+
];
|
|
47
|
+
const items = [];
|
|
48
|
+
roots.forEach(sel => {
|
|
49
|
+
document.querySelectorAll(sel).forEach(el => {
|
|
50
|
+
if (!el.offsetParent && getComputedStyle(el).position !== 'fixed') return;
|
|
51
|
+
const r = el.getBoundingClientRect();
|
|
52
|
+
if (r.width === 0 || r.height === 0) return;
|
|
53
|
+
items.push({
|
|
54
|
+
selector: sel,
|
|
55
|
+
tag: el.tagName,
|
|
56
|
+
role: el.getAttribute('role'),
|
|
57
|
+
name: el.getAttribute('aria-label') || el.textContent?.trim().slice(0, 60) || '',
|
|
58
|
+
type: el.getAttribute('type'),
|
|
59
|
+
haspopup: el.getAttribute('aria-haspopup'),
|
|
60
|
+
expanded: el.getAttribute('aria-expanded'),
|
|
61
|
+
disabled: el.disabled || el.getAttribute('aria-disabled') === 'true',
|
|
62
|
+
rect: { x: r.x, y: r.y, w: r.width, h: r.height },
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
return items;
|
|
67
|
+
})()
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Save to `.super-design/sessions/<id>/interactive/<slug>_<vp>.json`.
|
|
71
|
+
|
|
72
|
+
Classify each:
|
|
73
|
+
- **navigation** — links, tabs, back buttons
|
|
74
|
+
- **action** — primary CTAs, submit, delete, save
|
|
75
|
+
- **trigger** — opens modal/drawer/dropdown (`aria-haspopup`, `data-trigger`)
|
|
76
|
+
- **input** — form fields
|
|
77
|
+
- **state-toggle** — switches, checkboxes, expanders
|
|
78
|
+
|
|
79
|
+
### Phase B — Modal & overlay discovery
|
|
80
|
+
|
|
81
|
+
For each trigger from Phase A:
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
1. Pre-click snapshot (already have from Phase 1)
|
|
85
|
+
2. browser_click({ ref }) # click the trigger
|
|
86
|
+
3. browser_wait_for(text="<expected modal content>") or 500ms
|
|
87
|
+
4. browser_snapshot → save as snapshots/<slug>_<vp>_<triggerName>_open.yaml
|
|
88
|
+
5. browser_take_screenshot fullPage + element-scoped → screens/components/
|
|
89
|
+
6. browser_console_messages(level="error") → record
|
|
90
|
+
7. Inside open modal, run Phase A again (nested inventory)
|
|
91
|
+
8. Look for [role="dialog"] or [data-state="open"] to confirm it opened
|
|
92
|
+
9. Exercise modal internals:
|
|
93
|
+
- Tab through to find focus trap
|
|
94
|
+
- Press Escape to confirm dismiss
|
|
95
|
+
- Resize to mobile — check if it becomes bottom-sheet
|
|
96
|
+
10. Close modal (button or Escape)
|
|
97
|
+
11. Re-snapshot → confirm background restored, focus returned to trigger
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
**Modals a junior agent misses:**
|
|
101
|
+
- Confirmation dialogs (delete confirm, logout confirm)
|
|
102
|
+
- Date pickers (calendar popover)
|
|
103
|
+
- Color pickers
|
|
104
|
+
- Combobox dropdowns (autocomplete search)
|
|
105
|
+
- Popover menus (dropdown with options)
|
|
106
|
+
- Sheet / drawer (slide-in from right or bottom)
|
|
107
|
+
- Command palette (Cmd+K)
|
|
108
|
+
- Tooltips (hover-triggered on desktop)
|
|
109
|
+
- Toast notifications (programmatic — trigger an action that causes one)
|
|
110
|
+
- Error modals (submit invalid form)
|
|
111
|
+
- Share sheets
|
|
112
|
+
- File upload dialogs (click input[type=file])
|
|
113
|
+
|
|
114
|
+
### Phase C — Flow exercising
|
|
115
|
+
|
|
116
|
+
A **flow** is a multi-step user journey. Every app has 3–10 critical flows.
|
|
117
|
+
sd-audit must auto-discover and exercise them.
|
|
118
|
+
|
|
119
|
+
**Auto-discover flows from routes + component names:**
|
|
120
|
+
|
|
121
|
+
| Route / name hint | Flow |
|
|
122
|
+
|---|---|
|
|
123
|
+
| `/login`, `/signin`, `/auth` | Login flow (happy + wrong password + locked account) |
|
|
124
|
+
| `/register`, `/signup` | Registration flow |
|
|
125
|
+
| `/forgot`, `/reset` | Password reset flow |
|
|
126
|
+
| `/onboarding`, `/welcome` | First-run flow |
|
|
127
|
+
| `/checkout`, `/cart` | Checkout flow (incl. errors: declined card, validation) |
|
|
128
|
+
| `/dashboard`, `/home` (authed) | Post-auth landing → primary CTA flow |
|
|
129
|
+
| List route (`/users`, `/orders`) | CRUD — create, edit, view, delete, filter, search, paginate |
|
|
130
|
+
| Detail route (`/users/:id`) | Edit flow, delete flow, related actions |
|
|
131
|
+
| `/settings`, `/profile` | Profile edit, preference toggles, account delete |
|
|
132
|
+
| `/support`, `/help`, `/chat` | Messaging flow |
|
|
133
|
+
|
|
134
|
+
**Per flow:**
|
|
135
|
+
|
|
136
|
+
```
|
|
137
|
+
1. Plan steps (list of expected screens + actions)
|
|
138
|
+
2. Execute step-by-step:
|
|
139
|
+
- Navigate / click to advance
|
|
140
|
+
- Per step: snapshot + screenshot + console
|
|
141
|
+
- Test error path (invalid input, network error via DevTools)
|
|
142
|
+
- Test back button preserves state
|
|
143
|
+
3. Capture final success state (confirmation page, toast, redirect)
|
|
144
|
+
4. If flow depends on creating test data, use burner account
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Save per-flow artifacts under `.super-design/sessions/<id>/flows/<flow_name>/step_NN_<action>.png`.
|
|
148
|
+
|
|
149
|
+
### Phase D — State matrix per component
|
|
150
|
+
|
|
151
|
+
For each UI component class (Button, Input, Card, ListRow, Modal, NavItem…),
|
|
152
|
+
capture:
|
|
153
|
+
|
|
154
|
+
| State | How to trigger |
|
|
155
|
+
|---|---|
|
|
156
|
+
| default | Initial render |
|
|
157
|
+
| hover | `browser_hover` (desktop only, gate `@media hover`) |
|
|
158
|
+
| focus | Tab to element via `browser_press_key(Tab)` until focused |
|
|
159
|
+
| focus-visible | Same as focus (most systems collapse them now) |
|
|
160
|
+
| active | `browser_press_key` Enter/Space while focused |
|
|
161
|
+
| disabled | Find a disabled example (e.g., form before valid) |
|
|
162
|
+
| loading | Submit form → catch transient state; OR throttle network via DevTools |
|
|
163
|
+
| error | Invalid input + submit |
|
|
164
|
+
| empty | Navigate to route with no data (burner account OR delete all) |
|
|
165
|
+
| success | Complete a flow successfully |
|
|
166
|
+
| selected | Click tab / radio / checkbox that shows selected variant |
|
|
167
|
+
|
|
168
|
+
Save per component class:
|
|
169
|
+
```
|
|
170
|
+
.super-design/sessions/<id>/components/
|
|
171
|
+
Button/
|
|
172
|
+
default.png
|
|
173
|
+
hover.png
|
|
174
|
+
focus.png
|
|
175
|
+
active.png
|
|
176
|
+
disabled.png
|
|
177
|
+
loading.png
|
|
178
|
+
Input/...
|
|
179
|
+
Modal/...
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Output `.super-design/sessions/<id>/component-state-matrix.json`:
|
|
183
|
+
|
|
184
|
+
```json
|
|
185
|
+
{
|
|
186
|
+
"Button": {
|
|
187
|
+
"states_captured": ["default", "hover", "focus", "active", "disabled", "loading"],
|
|
188
|
+
"states_missing": ["error"],
|
|
189
|
+
"evidence": { "default": "components/Button/default.png", "..." }
|
|
190
|
+
},
|
|
191
|
+
"...": {}
|
|
192
|
+
}
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
**Missing states → finding.**
|
|
196
|
+
|
|
197
|
+
### Phase E — Form state coverage
|
|
198
|
+
|
|
199
|
+
Per form discovered, test:
|
|
200
|
+
1. Empty submit → validation messages
|
|
201
|
+
2. Each field invalid individually → per-field error
|
|
202
|
+
3. All valid → success state
|
|
203
|
+
4. Server error (simulate 500) → error recovery
|
|
204
|
+
5. Network offline → offline handling
|
|
205
|
+
6. Paste into password field → paste NOT blocked
|
|
206
|
+
7. Autocomplete tokens on login fields (`username`, `current-password`, `one-time-code`)
|
|
207
|
+
8. Tab order matches visual order
|
|
208
|
+
9. Submit via Enter key works
|
|
209
|
+
10. Mobile viewport — input zoom behavior (iOS Safari `font-size < 16px`?)
|
|
210
|
+
|
|
211
|
+
Save: `.super-design/sessions/<id>/forms/<formId>_<scenario>.png`
|
|
212
|
+
|
|
213
|
+
## Orchestration summary
|
|
214
|
+
|
|
215
|
+
sd-audit adds this between Step 2 and Step 3:
|
|
216
|
+
|
|
217
|
+
```
|
|
218
|
+
Step 2.5 — Discovery
|
|
219
|
+
For each (page, viewport):
|
|
220
|
+
A. Interactive inventory
|
|
221
|
+
B. Modal/overlay enumeration (click every trigger)
|
|
222
|
+
C. Flow exercising (login, CRUD, checkout if applicable)
|
|
223
|
+
D. Component state matrix
|
|
224
|
+
E. Form state coverage
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
This takes 3–5× longer than static-only audit but produces ~3× the findings,
|
|
228
|
+
each with real evidence of failure conditions (not just hypothetical WCAG
|
|
229
|
+
violations on static markup).
|
|
230
|
+
|
|
231
|
+
## Budget & skipping
|
|
232
|
+
|
|
233
|
+
For very large apps, scope Phase B/C/D to:
|
|
234
|
+
- Top 5 most-clicked triggers per page (ranked by proximity to primary CTA)
|
|
235
|
+
- Critical flows only (login + checkout + 1 CRUD)
|
|
236
|
+
- 3 component classes minimum (Button, Input, Modal) — rest deferred to full-mode audit
|
|
237
|
+
|
|
238
|
+
Record what was skipped in `.super-design/sessions/<id>/scope.json` so later
|
|
239
|
+
runs can close the gap.
|
|
240
|
+
|
|
241
|
+
## Error handling
|
|
242
|
+
|
|
243
|
+
- **Triggered modal doesn't appear within 2s** — record "trigger broken" finding, move on
|
|
244
|
+
- **Console error after click** — record verbatim, still capture whatever rendered
|
|
245
|
+
- **Focus not trapped** — record a11y violation
|
|
246
|
+
- **Modal close fails** — force navigate away, record "close broken" finding
|
|
247
|
+
|
|
248
|
+
Never let a broken trigger abort the full audit — isolate and continue.
|
|
249
|
+
|
|
250
|
+
## Hard rules
|
|
251
|
+
|
|
252
|
+
1. Every Phase A inventory item must be considered for exercising; skips recorded.
|
|
253
|
+
2. Every modal opened must be screenshotted OPEN + CLOSED.
|
|
254
|
+
3. Every flow must capture at least one error path, not just happy path.
|
|
255
|
+
4. Component state matrix must declare which states are MISSING (not just captured).
|
|
256
|
+
5. Form state coverage — 10 scenarios per form; partial completion records which.
|
|
257
|
+
6. Use ONE Playwright session; reuse across phases; `browser_close` only at end.
|
|
258
|
+
7. Sequential, not parallel. Never spawn parallel tabs.
|
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
# Design Intelligence Rubric
|
|
2
|
+
|
|
3
|
+
> The missing layer between WCAG/Nielsen checklists and "does this feel
|
|
4
|
+
> designed or vibecoded?" — used by sd-audit as Phase 3g.
|
|
5
|
+
|
|
6
|
+
## Why this exists
|
|
7
|
+
|
|
8
|
+
A UI can pass axe (zero WCAG violations), Nielsen (10/10 heuristics green),
|
|
9
|
+
Lighthouse (100 perf score) and still be visually horrible: card-stacked mobile
|
|
10
|
+
dashboards, microtext tables on phones, no visual hierarchy, shadcn defaults
|
|
11
|
+
slapped onto every surface with zero variant discipline, inline arbitrary
|
|
12
|
+
pixel values everywhere. This rubric codifies those **implicit** criteria.
|
|
13
|
+
|
|
14
|
+
Every category is scored **0–10** per page × viewport. Total score → a single
|
|
15
|
+
**design-intelligence score (DIS)** 0–100. Scores below 60 auto-flag MEDIUM
|
|
16
|
+
findings; below 40 auto-flag HIGH.
|
|
17
|
+
|
|
18
|
+
## Evidence requirement
|
|
19
|
+
|
|
20
|
+
Each category's score MUST cite ≥1 piece of evidence from the audit session:
|
|
21
|
+
- **SHOT** (screenshot path)
|
|
22
|
+
- **CSS** (computed style excerpt)
|
|
23
|
+
- **DOM** (snapshot quote)
|
|
24
|
+
- **CODE** (source file + line, via Grep, for vibecode detection)
|
|
25
|
+
|
|
26
|
+
A score without evidence is invalid. Auditor records `n/a` instead of guessing.
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Category 1 — Visual hierarchy (weight 1.0)
|
|
31
|
+
|
|
32
|
+
**Question:** On this view, what is the single primary goal? Is it the most
|
|
33
|
+
dominant element visually?
|
|
34
|
+
|
|
35
|
+
| Score | Criteria |
|
|
36
|
+
|---|---|
|
|
37
|
+
| 10 | One dominant element ≥ 2× larger or distinctly heavier than rest. Supporting info subordinate. Example: Cash App balance. |
|
|
38
|
+
| 7 | Primary clear but competing CTAs present. |
|
|
39
|
+
| 4 | Multiple equal-weight elements; user has to hunt. |
|
|
40
|
+
| 0 | Flat wall of cards/tables, no signal of where to look. |
|
|
41
|
+
|
|
42
|
+
**Detect:** `browser_evaluate` → collect computed `fontSize`, `fontWeight`, `lineHeight`, `color` of h1–h6, buttons, key metrics. Compute size-dominance ratio. Ratio > 2 → 10. Ratio < 1.3 → ≤4.
|
|
43
|
+
|
|
44
|
+
**Example fail (beats-market):** admin dashboard mobile — 10 equal-weight metric cards, no hero. Score: 2.
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Category 2 — Density calibration per viewport (weight 1.2)
|
|
49
|
+
|
|
50
|
+
**Question:** Does information density match the device context?
|
|
51
|
+
|
|
52
|
+
| Viewport | Expected primary entities visible above fold |
|
|
53
|
+
|---|---|
|
|
54
|
+
| Mobile 375×812 | 6–8 compact rows OR 1 hero + 4–5 rows |
|
|
55
|
+
| Tablet 768×1024 | 8–12 rows or 4 cards in 2×2 |
|
|
56
|
+
| Desktop 1440×900 | 12–20+ rows or data-dense tables |
|
|
57
|
+
|
|
58
|
+
**Score:**
|
|
59
|
+
- 10 if density within ±20% of target
|
|
60
|
+
- 5 if half or double target
|
|
61
|
+
- 0 if <25% of target (wasteful) or >3× (cramped illegible)
|
|
62
|
+
|
|
63
|
+
**Detect:** Count `role=listitem | region | article` elements with `getBoundingClientRect` intersecting viewport. Compare to viewport target.
|
|
64
|
+
|
|
65
|
+
**Example fail (beats-market):** admin dashboard mobile — 3 cards above fold (target 6–8). Score: 3. Orders mobile = 20 rows visible but microtext = also fail (see Category 7).
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Category 3 — Consistency: spacing scale (weight 0.8)
|
|
70
|
+
|
|
71
|
+
**Question:** Do paddings, margins, gaps come from a scale (4/8px or 0.25rem) or are they arbitrary magic numbers?
|
|
72
|
+
|
|
73
|
+
**Detect:**
|
|
74
|
+
- `browser_evaluate` → collect computed `padding`, `margin`, `gap` from ≥50 elements.
|
|
75
|
+
- Grep codebase for `p-\[\d+px\]`, `m-\[\d+px\]`, `gap-\[\d+px\]` (Tailwind arbitrary values).
|
|
76
|
+
- Count: on-scale vs off-scale.
|
|
77
|
+
|
|
78
|
+
| Score | Criteria |
|
|
79
|
+
|---|---|
|
|
80
|
+
| 10 | 95%+ values on a 4/8 scale; no arbitrary pixel values in code |
|
|
81
|
+
| 7 | 80–95% on-scale; a few arbitrary values in leaf components |
|
|
82
|
+
| 4 | 50–80% on-scale; arbitrary values common |
|
|
83
|
+
| 0 | Random pixel values everywhere; no visible scale |
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## Category 4 — Consistency: typography scale (weight 0.8)
|
|
88
|
+
|
|
89
|
+
Same method for font-size, font-weight, line-height. Look for `text-\[\d+px\]` and arbitrary font-size. Expected: 6–10 sizes total in a designed system; 30+ sizes = vibecoded.
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## Category 5 — Consistency: color palette (weight 0.8)
|
|
94
|
+
|
|
95
|
+
**Detect:**
|
|
96
|
+
- Collect computed `color`, `background-color`, `border-color` from ≥100 elements.
|
|
97
|
+
- Unique colors count. <15 = disciplined. 30+ = vibecoded.
|
|
98
|
+
- Grep for `#[0-9a-f]{6}`, `rgb\(`, Tailwind arbitrary colors.
|
|
99
|
+
|
|
100
|
+
| Score | Criteria |
|
|
101
|
+
|---|---|
|
|
102
|
+
| 10 | ≤12 distinct colors, all from tokens |
|
|
103
|
+
| 7 | 12–20 colors, mostly tokens |
|
|
104
|
+
| 4 | 20–30 colors |
|
|
105
|
+
| 0 | 30+ colors, raw hex/rgb inline |
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## Category 6 — Whitespace & breathing room (weight 0.7)
|
|
110
|
+
|
|
111
|
+
**Question:** Does content have room to breathe, or is it crammed?
|
|
112
|
+
|
|
113
|
+
**Detect:** Compute average `padding-inline + margin-inline` per content block. Compare to container width. Measure content-to-chrome ratio.
|
|
114
|
+
|
|
115
|
+
| Score | Criteria |
|
|
116
|
+
|---|---|
|
|
117
|
+
| 10 | Content 60–75% of width, 25–40% whitespace |
|
|
118
|
+
| 7 | Content 75–85% |
|
|
119
|
+
| 4 | Content 85–95% OR <50% (too sparse) |
|
|
120
|
+
| 0 | Content touching edges, no breathing |
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## Category 7 — Text legibility (weight 1.2)
|
|
125
|
+
|
|
126
|
+
**Detect:** `browser_evaluate` → collect `fontSize` computed px. Find minimum across visible text.
|
|
127
|
+
|
|
128
|
+
| Viewport | Min body | Min meta | Min input |
|
|
129
|
+
|---|---|---|---|
|
|
130
|
+
| Mobile | 16px | 13px | 16px (iOS zoom floor) |
|
|
131
|
+
| Desktop | 14px | 12px | 14px |
|
|
132
|
+
|
|
133
|
+
| Score | Criteria |
|
|
134
|
+
|---|---|
|
|
135
|
+
| 10 | All text meets mins |
|
|
136
|
+
| 5 | One or two elements below by ≤1px |
|
|
137
|
+
| 0 | Widespread microtext (tables, chips, meta) below min |
|
|
138
|
+
|
|
139
|
+
**Example fail (beats-market):** orders mobile — table cells computed at ~8px. Score: 0.
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## Category 8 — CTA hierarchy (weight 1.0)
|
|
144
|
+
|
|
145
|
+
**Question:** Is there ONE primary CTA per view?
|
|
146
|
+
|
|
147
|
+
**Detect:** Count buttons with `variant=default | primary | filled` OR bg-primary class. >1 above fold = competing.
|
|
148
|
+
|
|
149
|
+
| Score | Criteria |
|
|
150
|
+
|---|---|
|
|
151
|
+
| 10 | Single primary CTA, rest secondary/ghost |
|
|
152
|
+
| 7 | Single primary + 1 competing |
|
|
153
|
+
| 4 | 2–3 competing primaries |
|
|
154
|
+
| 0 | Every button styled primary |
|
|
155
|
+
|
|
156
|
+
Reference: Baymard PDP — 51% of e-commerce pages fail due to competing CTAs.
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## Category 9 — State coverage (weight 1.1)
|
|
161
|
+
|
|
162
|
+
Per page, does the UI handle: default / loading / empty / error / success?
|
|
163
|
+
|
|
164
|
+
**Detect per scenario:**
|
|
165
|
+
- Loading: Grep source for `isLoading`, `pending`, `Skeleton`, `aria-busy`.
|
|
166
|
+
- Empty: Grep for `isEmpty`, `EmptyState`, zero-result ternaries.
|
|
167
|
+
- Error: Grep for `role="alert"`, error boundaries, `onError`.
|
|
168
|
+
|
|
169
|
+
| Score | Criteria |
|
|
170
|
+
|---|---|
|
|
171
|
+
| 10 | 5/5 states rendered or demonstrably coded |
|
|
172
|
+
| 8 | 4/5 (usually missing success toast) |
|
|
173
|
+
| 5 | 3/5 (missing empty + error) |
|
|
174
|
+
| 0 | Only default; fetch returns broken UI on failure |
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## Category 10 — Touch targets (mobile only, weight 1.0)
|
|
179
|
+
|
|
180
|
+
**Detect:** `browser_evaluate` → get `getBoundingClientRect` of every clickable. Count targets < 44×44 px.
|
|
181
|
+
|
|
182
|
+
| Score | Criteria |
|
|
183
|
+
|---|---|
|
|
184
|
+
| 10 | 100% targets ≥ 44×44 OR 24×24 with 8px+ gap |
|
|
185
|
+
| 7 | 80–99% compliant |
|
|
186
|
+
| 4 | 50–80% compliant (common: icon-only buttons) |
|
|
187
|
+
| 0 | Widespread <24px targets |
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## Category 11 — Motion & feedback (weight 0.6)
|
|
192
|
+
|
|
193
|
+
**Question:** Do interactions give feedback? Are animations tasteful and respect `prefers-reduced-motion`?
|
|
194
|
+
|
|
195
|
+
**Detect:**
|
|
196
|
+
- `browser_evaluate` with `matchMedia('(prefers-reduced-motion: reduce)')` + check for `transition` / `animation` on interactive elements.
|
|
197
|
+
- Missing hover/focus feedback on buttons = major fail.
|
|
198
|
+
- >3s animations = excessive.
|
|
199
|
+
|
|
200
|
+
| Score | Criteria |
|
|
201
|
+
|---|---|
|
|
202
|
+
| 10 | Hover/focus/active feedback everywhere; animations ≤300ms; reduced-motion respected |
|
|
203
|
+
| 7 | Most interactions feedback; reduced-motion partial |
|
|
204
|
+
| 4 | Some interactions static; reduced-motion ignored |
|
|
205
|
+
| 0 | No hover/focus feedback at all OR autoplay video + parallax with no disable |
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
## Category 12 — Nav pattern matches platform (weight 1.0)
|
|
210
|
+
|
|
211
|
+
| Viewport | Expected nav |
|
|
212
|
+
|---|---|
|
|
213
|
+
| Mobile (≤768) | Bottom tab bar (3–5), full-screen menus, gesture back |
|
|
214
|
+
| Tablet | Hybrid (collapsible sidebar or top tabs) |
|
|
215
|
+
| Desktop | Persistent sidebar or top navbar with search |
|
|
216
|
+
|
|
217
|
+
**Detect:** On mobile viewport, check for `<nav>` in fixed bottom position. On desktop, fixed left sidebar OR top header with nav.
|
|
218
|
+
|
|
219
|
+
| Score | Criteria |
|
|
220
|
+
|---|---|
|
|
221
|
+
| 10 | Nav matches platform convention |
|
|
222
|
+
| 5 | Hybrid but functional (e.g., bottom FAB + hamburger) |
|
|
223
|
+
| 0 | Hamburger-only on mobile OR bottom tabs on desktop |
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
## Category 13 — Table-on-mobile detection (weight 1.2, mobile only)
|
|
228
|
+
|
|
229
|
+
**Detect:** At ≤768px, find `<table>` with >3 visible columns OR `display: table` containers with horizontal scroll AND text < 13px.
|
|
230
|
+
|
|
231
|
+
| Score | Criteria |
|
|
232
|
+
|---|---|
|
|
233
|
+
| 10 | No table or table transformed to card-per-row |
|
|
234
|
+
| 5 | Table present but scrolls clean with sticky first col |
|
|
235
|
+
| 0 | Squashed desktop table with microtext |
|
|
236
|
+
|
|
237
|
+
**Example fail (beats-market):** admin orders mobile — 8-col desktop table rendered at 375px with ~8px text. Score: 0.
|
|
238
|
+
|
|
239
|
+
---
|
|
240
|
+
|
|
241
|
+
## Category 14 — Modal/sheet appropriateness (weight 0.8)
|
|
242
|
+
|
|
243
|
+
| Viewport | Expected modal pattern |
|
|
244
|
+
|---|---|
|
|
245
|
+
| Mobile | Bottom sheet (slide-up) or full-screen with close top-left |
|
|
246
|
+
| Tablet | Centered dialog OR bottom sheet |
|
|
247
|
+
| Desktop | Centered dialog |
|
|
248
|
+
|
|
249
|
+
**Detect:** Open every `role=dialog` trigger. Measure position + dimensions. On mobile, centered dialog with close in top-right = fail.
|
|
250
|
+
|
|
251
|
+
| Score | Criteria |
|
|
252
|
+
|---|---|
|
|
253
|
+
| 10 | Correct per viewport |
|
|
254
|
+
| 5 | Centered on mobile but within reach |
|
|
255
|
+
| 0 | Unreachable thumb-zone close, wrong pattern for device |
|
|
256
|
+
|
|
257
|
+
---
|
|
258
|
+
|
|
259
|
+
## Category 15 — Color semantics (weight 0.6)
|
|
260
|
+
|
|
261
|
+
**Detect:** Collect colors used on: error messages, success states, warnings, info. Red = error? Green = success? Or decorative-only?
|
|
262
|
+
|
|
263
|
+
| Score | Criteria |
|
|
264
|
+
|---|---|
|
|
265
|
+
| 10 | Semantic colors distinct and consistent across app |
|
|
266
|
+
| 5 | Used but inconsistent (red elsewhere as brand) |
|
|
267
|
+
| 0 | No semantic color system |
|
|
268
|
+
|
|
269
|
+
---
|
|
270
|
+
|
|
271
|
+
## Category 16 — Design-system coherence (weight 1.1)
|
|
272
|
+
|
|
273
|
+
**The meta-category.** Does the app LOOK like it was designed by one team with one vision? Or does it look like a collection of shadcn defaults?
|
|
274
|
+
|
|
275
|
+
**Detect (aesthetic signal):**
|
|
276
|
+
- Does at least one of: custom color palette, custom font pairing, custom spacing rhythm, custom radius language, custom motion language, custom illustration/icon set EXIST?
|
|
277
|
+
- Grep package.json for ≥1 of: `typeui.sh`, `framer-motion`, custom fonts beyond system, Lottie, MagicUI, Aceternity, custom token file.
|
|
278
|
+
|
|
279
|
+
| Score | Criteria |
|
|
280
|
+
|---|---|
|
|
281
|
+
| 10 | Strong identity — you could recognize this app from a cropped screenshot |
|
|
282
|
+
| 7 | Some identity (brand color + maybe custom font) |
|
|
283
|
+
| 4 | shadcn defaults + 1 accent color |
|
|
284
|
+
| 0 | Pure shadcn defaults, zero customization, looks like `npx shadcn-ui@latest init` |
|
|
285
|
+
|
|
286
|
+
**When score ≤4:** recommend a typeui.sh aesthetic skill OR a frontend-design
|
|
287
|
+
session. See `design-skills-catalog.md`.
|
|
288
|
+
|
|
289
|
+
---
|
|
290
|
+
|
|
291
|
+
## Category 17 — Vibecode detection (weight 1.0)
|
|
292
|
+
|
|
293
|
+
**Question:** Does the code follow patterns (components, variants, tokens)
|
|
294
|
+
or is it hand-assembled divs with inline styles?
|
|
295
|
+
|
|
296
|
+
**Detect (source grep):**
|
|
297
|
+
- Count `<div className="..."` without surrounding component → raw-div score
|
|
298
|
+
- Count inline `style={{` → inline-style count
|
|
299
|
+
- Count `@media` queries inline vs breakpoint tokens
|
|
300
|
+
- Count arbitrary Tailwind values (`\[\d+px\]`, `\[#[0-9a-f]+\]`)
|
|
301
|
+
- Check if shadcn components are wrapped into domain components (MetricRow, OrderCard) or used raw per page
|
|
302
|
+
- Check if types are co-located in `types/` vs inline `any`
|
|
303
|
+
|
|
304
|
+
| Score | Criteria |
|
|
305
|
+
|---|---|
|
|
306
|
+
| 10 | Domain components, design tokens, typed props, variants via CVA |
|
|
307
|
+
| 7 | Some composition, some raw shadcn usage |
|
|
308
|
+
| 4 | Mostly raw primitives, inconsistent composition |
|
|
309
|
+
| 0 | Flat page files with 500+ lines of inline JSX; zero reuse |
|
|
310
|
+
|
|
311
|
+
---
|
|
312
|
+
|
|
313
|
+
## Scoring formula
|
|
314
|
+
|
|
315
|
+
```
|
|
316
|
+
DIS = Σ(score_i × weight_i) / Σ(weight_i) × 10
|
|
317
|
+
|
|
318
|
+
weight_sum = 14.8
|
|
319
|
+
max_raw = 148.0 → normalized to 100
|
|
320
|
+
|
|
321
|
+
Example (beats-market admin dashboard mobile):
|
|
322
|
+
C1 hierarchy: 2 × 1.0 = 2.0
|
|
323
|
+
C2 density: 3 × 1.2 = 3.6
|
|
324
|
+
C3 spacing: 7 × 0.8 = 5.6
|
|
325
|
+
C4 type: 6 × 0.8 = 4.8
|
|
326
|
+
C5 color: 7 × 0.8 = 5.6
|
|
327
|
+
C6 whitespace:4 × 0.7 = 2.8
|
|
328
|
+
C7 legibility:8 × 1.2 = 9.6
|
|
329
|
+
C8 CTA: 6 × 1.0 = 6.0
|
|
330
|
+
C9 states: 4 × 1.1 = 4.4
|
|
331
|
+
C10 touch: 6 × 1.0 = 6.0
|
|
332
|
+
C11 motion: 5 × 0.6 = 3.0
|
|
333
|
+
C12 nav: 4 × 1.0 = 4.0
|
|
334
|
+
C13 table: 10 × 1.2 = 12.0 (no table on dashboard)
|
|
335
|
+
C14 modal: 6 × 0.8 = 4.8
|
|
336
|
+
C15 color-sem:6 × 0.6 = 3.6
|
|
337
|
+
C16 coherence:3 × 1.1 = 3.3
|
|
338
|
+
C17 vibecode: 4 × 1.0 = 4.0
|
|
339
|
+
raw = 85.1 → DIS = 57.5 → MEDIUM severity
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
## Output format
|
|
343
|
+
|
|
344
|
+
Write `.super-design/sessions/<id>/design-intelligence.json`:
|
|
345
|
+
|
|
346
|
+
```json
|
|
347
|
+
{
|
|
348
|
+
"pages": [
|
|
349
|
+
{
|
|
350
|
+
"page_url": "/admin",
|
|
351
|
+
"viewport": "375x812",
|
|
352
|
+
"categories": {
|
|
353
|
+
"visual_hierarchy": { "score": 2, "evidence": ["screens/admin_mobile.png", "styles/admin_mobile.json"], "notes": "10 equal-weight metric cards, no hero" },
|
|
354
|
+
"density": { "score": 3, "evidence": ["screens/admin_mobile.png"], "notes": "Only 3 metrics above fold; target 6-8" }
|
|
355
|
+
},
|
|
356
|
+
"dis": 57.5,
|
|
357
|
+
"severity": "MEDIUM",
|
|
358
|
+
"top_findings": ["F-0042", "F-0043", "F-0049"]
|
|
359
|
+
}
|
|
360
|
+
],
|
|
361
|
+
"overall_dis": 54.2,
|
|
362
|
+
"overall_severity": "MEDIUM",
|
|
363
|
+
"weakest_categories": ["visual_hierarchy", "density", "design_system_coherence"]
|
|
364
|
+
}
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
Each category score ≤ 4 SHOULD spawn a finding with `template_id` from the M-family (M1–M15) in `fix-agent-playbook.md`.
|
|
368
|
+
|
|
369
|
+
## Cross-references
|
|
370
|
+
|
|
371
|
+
- Mobile-specific categories (C2, C7, C10, C12, C13, C14) reference
|
|
372
|
+
`.claude/skills/mobile-app-patterns/SKILL.md` for fix patterns.
|
|
373
|
+
- Design-system coherence (C16) references `design-skills-catalog.md` for
|
|
374
|
+
typeui.sh skill suggestions.
|
|
375
|
+
- Vibecode (C17) references `fix-agent-playbook.md` V-templates (spacing,
|
|
376
|
+
type, color tokens).
|