start-vibing 4.2.0 → 4.3.1
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 +288 -6
- package/template/.claude/agents/sd-fix.md +101 -2
- package/template/.claude/agents/sd-research.md +119 -3
- package/template/.claude/skills/mobile-app-patterns/SKILL.md +237 -0
- package/template/.claude/skills/super-design/.schema-version +1 -0
- package/template/.claude/skills/super-design/SKILL.md +34 -10
- package/template/.claude/skills/super-design/references/audit-methodology.md +118 -0
- package/template/.claude/skills/super-design/references/component-flow-discovery.md +258 -0
- package/template/.claude/skills/super-design/references/design-intelligence-rubric.md +457 -0
- package/template/.claude/skills/super-design/references/design-skills-catalog.md +133 -0
- package/template/.claude/skills/super-design/scripts/detect-changes.sh +113 -18
- package/template/.claude/skills/super-design/scripts/discover-routes.sh +7 -0
- package/template/.claude/skills/super-design/scripts/extract-tokens.mjs +19 -2
- package/template/.claude/skills/super-design/scripts/hash-pages.sh +6 -0
- package/template/.claude/skills/super-design/scripts/setup-git-notes.sh +21 -0
- package/template/.claude/skills/super-design/scripts/validate-state.sh +34 -2
- package/template/.claude/skills/super-design/scripts/write-state.sh +26 -0
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mobile-app-patterns
|
|
3
|
+
description: >
|
|
4
|
+
Best-in-class mobile UI/UX patterns inspired by Duolingo, Linear, Arc, Raycast,
|
|
5
|
+
Notion Mobile, Superhuman. MUST BE USED when designing, auditing, or fixing
|
|
6
|
+
any mobile viewport (≤768px) — especially dashboards, lists, forms, modals,
|
|
7
|
+
nav. Replaces "responsive-web-on-a-phone" thinking with genuine mobile-native
|
|
8
|
+
patterns. Referenced by sd-audit (design-intelligence rubric), sd-fix
|
|
9
|
+
(M-template fixes), and sd-research (component extraction from competitors).
|
|
10
|
+
version: 1.0.0
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# mobile-app-patterns
|
|
14
|
+
|
|
15
|
+
## Philosophy
|
|
16
|
+
|
|
17
|
+
A mobile screen is **not** a shrunken desktop. It is a **thumb-reach device** used in 2–10 second sessions with one hand, often while walking/waiting/scrolling. Every pattern here is derived from apps people actually keep on their home screen.
|
|
18
|
+
|
|
19
|
+
## Reference apps (study these before designing)
|
|
20
|
+
|
|
21
|
+
| App | Why | Patterns to extract |
|
|
22
|
+
|---|---|---|
|
|
23
|
+
| **Duolingo** | Highest D7 retention in learning category | Compact metric rows, streak flames, XP hero, bottom nav with tab bubbles, full-screen lesson flow, celebration animations |
|
|
24
|
+
| **Linear Mobile** | Fastest feedback SaaS on mobile | Minimal chrome, swipe-to-action on list rows, bottom sheet for create, command-K style quick switcher |
|
|
25
|
+
| **Arc Mobile / Search** | Search-first nav | No bottom tabs — single tap to search/command, gesture stack for back |
|
|
26
|
+
| **Raycast iOS** | Power-user density | Compact list rows with inline metadata, command palette, no decorative chrome |
|
|
27
|
+
| **Notion Mobile** | Heavy content on small screen | Block-based editor, swipe to nest/unnest, floating action button for quick capture |
|
|
28
|
+
| **Superhuman** | Speed as the aesthetic | No loading states visible — optimistic everything, keyboard shortcuts respected on iPad, split-swipe archive/snooze |
|
|
29
|
+
| **Cash App** | Financial density without tables | Big number hero, compact transaction rows (avatar + name + amount + relative time), bottom-sheet send/receive |
|
|
30
|
+
| **Spotify** | Media density | Horizontal scroll rails (not cards in column), sticky now-playing bar, bottom tab nav |
|
|
31
|
+
|
|
32
|
+
## Core mobile patterns
|
|
33
|
+
|
|
34
|
+
### 1. Lists over cards (CRITICAL)
|
|
35
|
+
|
|
36
|
+
**Rule:** On mobile dashboards, `role=listitem` rows beat `role=region` cards for metrics, entities, and history. Cards waste 40–60% of viewport height on padding+radius+shadow for a single data point.
|
|
37
|
+
|
|
38
|
+
```tsx
|
|
39
|
+
// ANTI-PATTERN (what the beats-market admin dashboard did wrong)
|
|
40
|
+
<div className="flex flex-col gap-3">
|
|
41
|
+
<Card><CardHeader>Total Users</CardHeader><CardContent>16</CardContent></Card>
|
|
42
|
+
<Card><CardHeader>Producers</CardHeader><CardContent>5</CardContent></Card>
|
|
43
|
+
<Card><CardHeader>Orders</CardHeader><CardContent>18</CardContent></Card>
|
|
44
|
+
{/* 10+ cards = endless scroll, no density */}
|
|
45
|
+
</div>
|
|
46
|
+
|
|
47
|
+
// GOOD (Duolingo/Linear/Cash App style)
|
|
48
|
+
<ul className="divide-y divide-border">
|
|
49
|
+
{metrics.map(m => (
|
|
50
|
+
<li key={m.id} className="flex items-center justify-between py-3 px-4">
|
|
51
|
+
<div className="flex items-center gap-3">
|
|
52
|
+
<Icon name={m.icon} className="size-5 text-muted-foreground" />
|
|
53
|
+
<span className="text-sm text-muted-foreground">{m.label}</span>
|
|
54
|
+
</div>
|
|
55
|
+
<span className="text-base font-semibold tabular-nums">{m.value}</span>
|
|
56
|
+
</li>
|
|
57
|
+
))}
|
|
58
|
+
</ul>
|
|
59
|
+
|
|
60
|
+
// EVEN BETTER for a hero metric on mobile (Cash App style)
|
|
61
|
+
<section className="px-4 pt-6 pb-4">
|
|
62
|
+
<p className="text-sm text-muted-foreground">Total revenue</p>
|
|
63
|
+
<h1 className="text-4xl font-bold tabular-nums">R$1.389</h1>
|
|
64
|
+
<p className="text-xs text-muted-foreground mt-1">+12% vs last month</p>
|
|
65
|
+
</section>
|
|
66
|
+
<ul className="divide-y">{/* supporting metrics as compact rows */}</ul>
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
**Density target:** A mobile viewport (390×844) should fit **at least 6–8 metrics above the fold**, not 2–3.
|
|
70
|
+
|
|
71
|
+
### 2. Hero + compact list (dashboard pattern)
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
┌─────────────────────────┐
|
|
75
|
+
│ ☰ Dashboard 👤 │ Header (56px fixed)
|
|
76
|
+
├─────────────────────────┤
|
|
77
|
+
│ │
|
|
78
|
+
│ Total Revenue │ HERO: 1 big number
|
|
79
|
+
│ R$ 1,389.00 │ that matters most
|
|
80
|
+
│ +12% this month ↗ │
|
|
81
|
+
│ │
|
|
82
|
+
├─────────────────────────┤
|
|
83
|
+
│ 👥 Users 16 │ Compact metric rows
|
|
84
|
+
│ 🎵 Producers 5 │ (44px each)
|
|
85
|
+
│ 📦 Active Packs 18 │
|
|
86
|
+
│ 🛒 Orders 18 │
|
|
87
|
+
│ 🔄 Refunds 0 │
|
|
88
|
+
│ 📊 Refund Rate 0.0% │
|
|
89
|
+
│ 🛡️ DMCA Claims 0 │
|
|
90
|
+
│ 💬 Open Tickets 1 │
|
|
91
|
+
├─────────────────────────┤
|
|
92
|
+
│ [Home][Metrics][Orders] │ Bottom tab nav (56px)
|
|
93
|
+
└─────────────────────────┘
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### 3. Bottom nav (NOT hamburger) for top-level nav
|
|
97
|
+
|
|
98
|
+
- 3–5 tabs max. More → move to secondary screen via "More" tab.
|
|
99
|
+
- Each tab = a destination, not an action.
|
|
100
|
+
- Fixed position, 56–64px tall, with safe-area inset.
|
|
101
|
+
- Active state: fill icon + label always visible (not hidden).
|
|
102
|
+
|
|
103
|
+
```tsx
|
|
104
|
+
<nav className="fixed inset-x-0 bottom-0 z-40 border-t bg-background pb-[env(safe-area-inset-bottom)]">
|
|
105
|
+
<ul className="flex h-14">
|
|
106
|
+
{tabs.map(t => (
|
|
107
|
+
<li key={t.id} className="flex-1">
|
|
108
|
+
<Link
|
|
109
|
+
href={t.href}
|
|
110
|
+
aria-current={active === t.id ? 'page' : undefined}
|
|
111
|
+
className="flex h-full flex-col items-center justify-center gap-1 text-xs"
|
|
112
|
+
>
|
|
113
|
+
<t.Icon className={cn('size-5', active === t.id ? 'fill-current' : '')} />
|
|
114
|
+
<span className={active === t.id ? 'font-semibold' : 'text-muted-foreground'}>{t.label}</span>
|
|
115
|
+
</Link>
|
|
116
|
+
</li>
|
|
117
|
+
))}
|
|
118
|
+
</ul>
|
|
119
|
+
</nav>
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### 4. Bottom sheets (NOT centered modals) for actions
|
|
123
|
+
|
|
124
|
+
- Centered dialog on mobile = thumb cannot reach top-right close button.
|
|
125
|
+
- Bottom sheet slides up from the bottom, close via drag-down or button at top.
|
|
126
|
+
- Use `<dialog>` or Vaul/Radix + `vaul-drawer` libs.
|
|
127
|
+
|
|
128
|
+
### 5. Full-screen flows (NOT multi-step modals)
|
|
129
|
+
|
|
130
|
+
Onboarding, lesson completion, checkout, create-entity — all should be **full-screen pages** that replace the current view, with a close/back in the top-left, not modal overlays.
|
|
131
|
+
|
|
132
|
+
Duolingo lesson = full-screen. Cash App send = full-screen. Linear create-issue = bottom sheet → expand to full. Never a centered modal trying to cram a form.
|
|
133
|
+
|
|
134
|
+
### 6. Swipe actions on list rows
|
|
135
|
+
|
|
136
|
+
Archive / Delete / Snooze / Complete = left or right swipe on the row. Exposes discoverability via slight peek on first render.
|
|
137
|
+
|
|
138
|
+
Lib: `react-swipeable-list` / custom pointer-events handler. Always provide a long-press or trailing `[…]` button as a11y fallback.
|
|
139
|
+
|
|
140
|
+
### 7. Pull-to-refresh on scrollable lists
|
|
141
|
+
|
|
142
|
+
Native iOS/Android pattern. Every list that fetches server data should implement it. Lib: `react-pull-to-refresh` or Framer Motion gestures.
|
|
143
|
+
|
|
144
|
+
### 8. Typography scale for mobile
|
|
145
|
+
|
|
146
|
+
- Body: **16px** (never smaller — iOS triggers zoom on focus for <16px inputs)
|
|
147
|
+
- Meta / captions: 14px minimum, 13px absolute floor for tabular dense lists
|
|
148
|
+
- Headings: 20/24/32/40 — large hero numbers allowed (44–56px)
|
|
149
|
+
- Line-height: 1.4 body, 1.2 headings, 1.5 long-form reading
|
|
150
|
+
|
|
151
|
+
### 9. Touch targets
|
|
152
|
+
|
|
153
|
+
- **44×44 px minimum** (Apple HIG) or 48dp (Material) — NOT the WCAG 24px floor
|
|
154
|
+
- 8px gap between adjacent targets
|
|
155
|
+
- Full-width list rows: the whole row is the target, not just the text
|
|
156
|
+
|
|
157
|
+
### 10. Data tables → convert on mobile
|
|
158
|
+
|
|
159
|
+
Tables with >3 columns CANNOT fit at 375px. Transform:
|
|
160
|
+
|
|
161
|
+
| Original desktop | Mobile replacement |
|
|
162
|
+
|---|---|
|
|
163
|
+
| Users table (name, email, role, status, date, actions) | List of rows with avatar + primary text + compact metadata stack + trailing `[⋯]` menu |
|
|
164
|
+
| Orders table (id, buyer, items, total, payment, refund, downloads, actions) | Card per order: buyer + total prominent, metadata as chips, CTA row at bottom |
|
|
165
|
+
| Data grid | Virtualized list OR horizontal scroll with sticky first column (only if truly needed) |
|
|
166
|
+
|
|
167
|
+
## Mobile anti-patterns (auto-flag in audits)
|
|
168
|
+
|
|
169
|
+
| Anti-pattern | Why bad | Fix |
|
|
170
|
+
|---|---|---|
|
|
171
|
+
| Cards in `flex-col` for metrics | Wastes 40–60% vertical space | Compact list rows with divider |
|
|
172
|
+
| Desktop table <768px | Unreadable microtext or horizontal scroll hell | Card-per-row OR list with primary+meta |
|
|
173
|
+
| Hamburger menu as only nav | Hides primary destinations behind 1+ tap | Bottom tab bar (3–5 tabs) |
|
|
174
|
+
| Centered modal with close in top-right | Unreachable by thumb | Bottom sheet with drag handle |
|
|
175
|
+
| Input `font-size < 16px` | iOS Safari zooms in on focus | Use 16px or `font-size: max(16px, 1rem)` |
|
|
176
|
+
| Fixed header + fixed footer > 25% height | Leaves <75% for content | Collapse header on scroll (framer shrink) |
|
|
177
|
+
| Multi-column layout <600px | Nothing fits | Single column or horizontal rail |
|
|
178
|
+
| Hover-only affordances | Touch has no hover | Gate `@media (hover: hover)` + tap equivalent |
|
|
179
|
+
| Tiny close buttons (<24×24) | Missed taps | 44×44 hit area even if icon is smaller |
|
|
180
|
+
| Toast in top-right | Thumb can't dismiss | Bottom-center toast with swipe-down |
|
|
181
|
+
| 100vh anywhere | iOS Safari URL bar breaks it | `100svh` / `100dvh` with `-webkit-fill-available` fallback |
|
|
182
|
+
| Pull-to-refresh inside inner scroll | Conflicts with browser pull | `overscroll-behavior: contain` |
|
|
183
|
+
|
|
184
|
+
## Competitor reference for mobile patterns by domain
|
|
185
|
+
|
|
186
|
+
| Your app type | Study these on mobile |
|
|
187
|
+
|---|---|
|
|
188
|
+
| Admin / SaaS dashboard | Linear, Height, Plane, Vercel dashboard |
|
|
189
|
+
| Marketplace (buyer) | Instagram Shop, Depop, Vinted, Mercari |
|
|
190
|
+
| Marketplace (seller) | Shopify Mobile, Etsy Seller, Depop |
|
|
191
|
+
| E-commerce checkout | Shop App, Amazon, Stripe Checkout (in a WebView) |
|
|
192
|
+
| Social / community | Discord, Slack, Twitter (X), BlueSky |
|
|
193
|
+
| Learning / habit | Duolingo, Brilliant, Finch, Streaks |
|
|
194
|
+
| Finance / fintech | Cash App, Revolut, Mercury, Ramp |
|
|
195
|
+
| Productivity | Notion, Linear, Raycast, Things 3 |
|
|
196
|
+
| Media | Spotify, Apple Music, YouTube |
|
|
197
|
+
|
|
198
|
+
## How to use this skill
|
|
199
|
+
|
|
200
|
+
- **sd-audit** references these anti-patterns as M-category findings (M1–M12).
|
|
201
|
+
- **sd-fix** applies M-templates with code snippets directly from this skill.
|
|
202
|
+
- **sd-research** studies competitors' mobile viewports against this pattern library, not just home pages.
|
|
203
|
+
- **frontend-design** plugin cross-references this skill when generating mobile UI.
|
|
204
|
+
|
|
205
|
+
## Mandatory mobile audit checklist (≤375px viewport)
|
|
206
|
+
|
|
207
|
+
```
|
|
208
|
+
□ Primary nav is bottom tabs (3-5), not hamburger-only
|
|
209
|
+
□ Dashboards use hero + compact list, not card stack
|
|
210
|
+
□ Tables transformed to card-per-row or compact list
|
|
211
|
+
□ No input has font-size < 16px
|
|
212
|
+
□ Every interactive target ≥ 44×44 px
|
|
213
|
+
□ Modals are bottom sheets or full-screen, not centered
|
|
214
|
+
□ No hover-only state; every hover has a tap equivalent
|
|
215
|
+
□ Loading states exist for async flows
|
|
216
|
+
□ Empty states exist for zero-data cases
|
|
217
|
+
□ Error states exist for server failures
|
|
218
|
+
□ Safe-area insets respected (iOS notch, home indicator)
|
|
219
|
+
□ Text uses 100svh / 100dvh (not 100vh) for full-height
|
|
220
|
+
□ Scroll containers use overscroll-behavior: contain
|
|
221
|
+
□ Pull-to-refresh implemented on primary list views
|
|
222
|
+
□ Swipe actions discoverable (peek on first render)
|
|
223
|
+
□ Back gesture (iOS) works via browser history
|
|
224
|
+
□ Keyboard does not overlap input (visualViewport API)
|
|
225
|
+
□ Touch targets 8px+ apart
|
|
226
|
+
□ Long-press fallback for swipe actions
|
|
227
|
+
□ Bottom sheet CTAs sticky above safe area
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
## References
|
|
231
|
+
|
|
232
|
+
- Linear Method — https://linear.app/method
|
|
233
|
+
- Vercel Design Engineering — https://vercel.com/blog/design-engineering-at-vercel
|
|
234
|
+
- iOS HIG Touch Targets — https://developer.apple.com/design/human-interface-guidelines/layout
|
|
235
|
+
- Material 3 Bottom App Bar — https://m3.material.io/components/bottom-app-bar/overview
|
|
236
|
+
- NN/g Mobile UX — https://www.nngroup.com/topic/mobile-and-tablet-design/
|
|
237
|
+
- Baymard Mobile Checkout — https://baymard.com/checkout-usability
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
1.0.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.1
|
|
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
|
|
|
@@ -68,9 +86,14 @@ Pass findings via files under `.super-design/sessions/<id>/`, not chat.
|
|
|
68
86
|
|
|
69
87
|
### Step 4: Write state + history
|
|
70
88
|
|
|
71
|
-
- Atomic write `.audit-state.json`
|
|
89
|
+
- Atomic write `.audit-state.json` via `scripts/write-state.sh` (takes JSON
|
|
90
|
+
on stdin, writes `.tmp`, validates with `jq`, then renames). Do NOT write
|
|
91
|
+
the state file directly.
|
|
72
92
|
- Append session to `audit-history.md`.
|
|
73
93
|
- `git notes --ref=super-design add -f -m <json> HEAD`.
|
|
94
|
+
- First-time notes setup (run once per clone, also in `setup-git-notes.sh`
|
|
95
|
+
if you extract it): `git config --add remote.origin.fetch '+refs/notes/super-design/*:refs/notes/super-design/*'`
|
|
96
|
+
— without this, notes don't round-trip across clones (artifact §7).
|
|
74
97
|
|
|
75
98
|
### Step 5: Return summary (≤5 sentences)
|
|
76
99
|
|
|
@@ -85,6 +108,7 @@ Do NOT paste overview into chat.
|
|
|
85
108
|
- `--fix` — run sd-fix after audit
|
|
86
109
|
- `--dry-run` — artifacts without committing state
|
|
87
110
|
- `--ci` — non-interactive, create PR, exit non-zero on blockers
|
|
111
|
+
- `--update-baselines` — Re-hash pages and tokens without re-auditing (use after accepted cosmetic drift)
|
|
88
112
|
|
|
89
113
|
## References (Read on demand)
|
|
90
114
|
|
|
@@ -187,6 +187,66 @@ The 2026 WebAIM Million report (released ~30 March 2026, https://webaim.org/proj
|
|
|
187
187
|
|
|
188
188
|
**What automation CANNOT catch** (the manual 40–70%): keyboard trap detection beyond trivial cases; screen-reader announcement quality; meaningful alt text (tools detect missing, not quality); logical focus order when CSS reorders; error message clarity; appropriate heading structure (presence vs meaning); context-appropriate link text; video caption accuracy/sync; color meaning (1.4.1); reading order under CSS transforms; reflow at 320px (no tool); text-spacing override; focus-indicator quality (2.4.11 / 2.4.13); `prefers-reduced-motion` honoring; target size / spacing (partial); autocomplete correctness; captcha alternatives; content-on-hover persistence (1.4.13); page title descriptiveness; consistent navigation/identification (3.2.3 / 3.2.4).
|
|
189
189
|
|
|
190
|
+
### 2.5 Tool triangulation for automated a11y (MANDATORY)
|
|
191
|
+
|
|
192
|
+
axe-core alone catches only ~57% of WCAG issues by volume (Deque's own
|
|
193
|
+
coverage study) and ~40% by Success Criterion count. Running a single
|
|
194
|
+
engine guarantees blind spots. sd-audit MUST run axe **plus** at least two
|
|
195
|
+
more engines and dedupe the merged results by `{rule, selector}`.
|
|
196
|
+
|
|
197
|
+
**Engines to run in parallel (don't serialize — they're cheap):**
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
# 1. axe-core — inject via Playwright MCP (already done in sd-audit Step 2,
|
|
201
|
+
# with `experimental: true` so WCAG 2.2 rules fire).
|
|
202
|
+
|
|
203
|
+
# 2. Pa11y — runs both htmlcs and axe runners for broader coverage
|
|
204
|
+
pa11y "$URL" \
|
|
205
|
+
--standard WCAG2AA \
|
|
206
|
+
--runner axe \
|
|
207
|
+
--runner htmlcs \
|
|
208
|
+
--reporter json \
|
|
209
|
+
> "$SESSION_DIR/a11y/pa11y_<slug>_<vp>.json"
|
|
210
|
+
|
|
211
|
+
# 3. WAVE API — WebAIM's detector, overlay-oriented, strong on contrast and ARIA
|
|
212
|
+
curl -s "https://wave.webaim.org/api/request?key=$WAVE_KEY&url=$(printf %s "$URL" | jq -sRr @uri)&reporttype=4" \
|
|
213
|
+
> "$SESSION_DIR/a11y/wave_<slug>_<vp>.json"
|
|
214
|
+
|
|
215
|
+
# 4. IBM Equal Access Accessibility Checker — ACT-rule aligned, ~140 rules
|
|
216
|
+
achecker "$URL" \
|
|
217
|
+
--reportLevel violation,potentialviolation \
|
|
218
|
+
--outputFormat json \
|
|
219
|
+
--outputFolder "$SESSION_DIR/a11y/achecker_<slug>_<vp>/"
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
**Dedup and severity normalization:**
|
|
223
|
+
|
|
224
|
+
```js
|
|
225
|
+
// Pseudocode — run in sd-audit Step 3a after parsing all engine outputs.
|
|
226
|
+
const key = (f) => `${f.rule}::${f.selector}`;
|
|
227
|
+
const bucket = new Map();
|
|
228
|
+
for (const engine of ['axe', 'pa11y', 'wave', 'achecker']) {
|
|
229
|
+
for (const f of findings[engine]) {
|
|
230
|
+
const k = key(f);
|
|
231
|
+
if (!bucket.has(k)) bucket.set(k, { ...f, engines: [] });
|
|
232
|
+
bucket.get(k).engines.push(engine);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
// Confidence ladder:
|
|
236
|
+
// engines.length === 1 → single-source, keep but tag "unverified"
|
|
237
|
+
// engines.length >= 2 → triangulated, high confidence
|
|
238
|
+
// engines.length >= 3 → near-certain, promote severity +1 step
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
**Why each engine is non-redundant:**
|
|
242
|
+
- **axe-core** — strongest on `4.1.2`, `1.4.3`, `1.1.1`, `1.3.1` subsets; experimental flag gates 2.2.
|
|
243
|
+
- **Pa11y** — htmlcs runner catches rule shapes axe doesn't ship; dual-runner mode is unique.
|
|
244
|
+
- **WAVE** — contrast slider tool + in-context overlay; different heuristics for ARIA landmarks; never marks a page "passed" (useful bias — never false-clean).
|
|
245
|
+
- **IBM Equal Access** — ACT-Rules aligned (different normative base than axe); baseline-file regression; severity categories (`violation / potentialviolation / recommendation / manual`) map onto Nielsen 0–4.
|
|
246
|
+
|
|
247
|
+
Record per-finding `source_engines: [...]` so sd-synthesis can promote
|
|
248
|
+
triangulated issues and down-weight single-engine noise.
|
|
249
|
+
|
|
190
250
|
### 2.4 Regulatory context
|
|
191
251
|
|
|
192
252
|
**European Accessibility Act** (Directive (EU) 2019/882) enforceable **28 June 2025** for new products/services; 28 June 2030 deadline for pre-existing. References **EN 301 549** (currently WCAG 2.1 AA baseline; being updated to 2.2). Extraterritorial.
|
|
@@ -201,6 +261,64 @@ The 2026 WebAIM Million report (released ~30 March 2026, https://webaim.org/proj
|
|
|
201
261
|
|
|
202
262
|
Baymard (Copenhagen, founded ~2009) is used by 71% of Fortune 500 e-commerce companies. Research: 54 rounds of benchmarking, 327 top-grossing US/EU sites, 275,000+ manually assigned UX performance scores, 200,000+ research hours. Methodology page: https://baymard.com/research/methodology. Headline finding: the average large e-commerce site can gain **+35.26% conversion** through better checkout design — **$260B** in recoverable US+EU orders.
|
|
203
263
|
|
|
264
|
+
### 3.0 Baymard sub-rule enumeration (finding code prefixes)
|
|
265
|
+
|
|
266
|
+
The single blanket "Baymard" verdict is too coarse for a structured audit.
|
|
267
|
+
Baymard organises findings by **surface** (checkout, PDP, search, etc.) and
|
|
268
|
+
each surface has a bounded, enumerable set of sub-rules. Every Baymard
|
|
269
|
+
finding raised by sd-audit MUST use one of the prefixes below so
|
|
270
|
+
sd-synthesis can group them and so the fix-playbook can route to the right
|
|
271
|
+
U-template. Rules that do not yet have an official Baymard number are
|
|
272
|
+
prefixed by count only (e.g. `baymard-cc-01` … `baymard-cc-14`) with the
|
|
273
|
+
source section cited.
|
|
274
|
+
|
|
275
|
+
| Surface | Prefix | Count | Source (methodology §) |
|
|
276
|
+
|---|---|---|---|
|
|
277
|
+
| Credit card form | `baymard-cc-<NN>` | 14 rules | §3.3 + https://baymard.com/checkout-usability/credit-card-patterns |
|
|
278
|
+
| Address form | `baymard-addr-<NN>` | 8 rules | §3.4 + https://baymard.com/blog/address-line-2 + https://baymard.com/blog/automatic-address-lookup |
|
|
279
|
+
| Search | `baymard-search-<NN>` | 12 rules | §3.6 + https://baymard.com/ecommerce-design-examples/34-autocomplete-suggestions |
|
|
280
|
+
| Filter | `baymard-filter-<NN>` | 10 rules | §3.6 + https://baymard.com/blog/promoting-product-filters + https://baymard.com/blog/have-filters-for-list-item-info |
|
|
281
|
+
| Breadcrumbs | `baymard-bread-<NN>` | 6 rules | §3.7 + https://baymard.com/blog/ecommerce-breadcrumbs |
|
|
282
|
+
| PDP / Product Detail | `baymard-pdp-<NN>` | 18 rules | §3.8 + https://baymard.com/research/product-page |
|
|
283
|
+
|
|
284
|
+
**`baymard-cc-*` — Credit card form (14 rules, §3.3):**
|
|
285
|
+
1. `baymard-cc-01` auto-format spaces per card brand (4-4-4-4 / 4-6-5 AMEX / 4-4-4-4-3 19-digit)
|
|
286
|
+
2. `baymard-cc-02` auto-detect card type via IIN ranges (adapt length limit, CVV help, spacing)
|
|
287
|
+
3. `baymard-cc-03` expiration as single MM/YY field with auto-inserted slash (NOT YYYY, NOT two dropdowns)
|
|
288
|
+
4. `baymard-cc-04` CVV field with adaptive help image (3-digit back for Visa/MC, 4-digit front for AMEX)
|
|
289
|
+
5. `baymard-cc-05` autocomplete tokens present: `cc-number`, `cc-name`, `cc-exp`, `cc-exp-month`, `cc-exp-year`, `cc-csc`
|
|
290
|
+
6. `baymard-cc-06` `inputmode="numeric"` (never `type="number"`) on card number, expiration, CVV
|
|
291
|
+
7. `baymard-cc-07` never clear CC number/CVV on validation error (preserve entered data)
|
|
292
|
+
8. `baymard-cc-08` stored-card edit uses "fake editing" (delete + re-add) per PCI; clear messaging
|
|
293
|
+
9. `baymard-cc-09` inline validation with 5%-abandonment guardrail (no vague "Card declined" without reason)
|
|
294
|
+
10. `baymard-cc-10` fallback entry path when wallet (Apple Pay / Google Pay) fails
|
|
295
|
+
11. `baymard-cc-11` accept pasted numbers; strip spaces/dashes server+client
|
|
296
|
+
12. `baymard-cc-12` surface accepted card brands near the input (logo strip) before submit
|
|
297
|
+
13. `baymard-cc-13` billing-address reuse: "Billing same as shipping" default-checked with editable prefill
|
|
298
|
+
14. `baymard-cc-14` error messages identify which field failed + how to fix (not "Payment failed")
|
|
299
|
+
|
|
300
|
+
> Source: §3.3 bullets + https://baymard.com/checkout-usability/credit-card-patterns. Rules 10–14 derived from §3.3 narrative; number them in this table and supersede with Baymard's official IDs when available.
|
|
301
|
+
|
|
302
|
+
**`baymard-addr-*` — Address form (8 rules, §3.4):**
|
|
303
|
+
1. `baymard-addr-01` country selector FIRST (drives all subsequent field formats/validation)
|
|
304
|
+
2. `baymard-addr-02` single "Address Line 1" + optional "Address Line 2" labeled "Apt, Suite — optional" (never omit Line 2)
|
|
305
|
+
3. `baymard-addr-03` automatic address autocomplete preferred (9% manual-entry typo rate without it)
|
|
306
|
+
4. `baymard-addr-04` postal-code autodetect of city/state (28% mobile sites fail)
|
|
307
|
+
5. `baymard-addr-05` US state as dropdown (not free text); UK optional county; hide for countries without subdivisions
|
|
308
|
+
6. `baymard-addr-06` autocomplete tokens: `street-address`, `address-line1`, `address-line2`, `address-level1/2`, `postal-code`, `country`
|
|
309
|
+
7. `baymard-addr-07` "Billing same as shipping" default-checked with editable prefilled fields (also WCAG 3.3.7 Redundant Entry)
|
|
310
|
+
8. `baymard-addr-08` name inputs accept Unicode, hyphens, apostrophes, single-name users, >20 chars
|
|
311
|
+
|
|
312
|
+
> Source: §3.4.
|
|
313
|
+
|
|
314
|
+
**`baymard-search-*` — Search (12 rules, §3.6):** placeholders for 12 rules covering autocomplete presence, scope suggestions in autocomplete, search-within-current-category, autodirect on category match, query-term pluralization tolerance, typo tolerance, "no results" with recovery options, recent-searches memory, sort-vs-filter separation, faceted-search state in URL, submit-without-suggestion-selection, voice search on mobile. Rules `baymard-search-01` … `baymard-search-12`. Source: §3.6 bullets + https://baymard.com/ecommerce-design-examples/34-autocomplete-suggestions. Enumerate the exact wording when next Baymard PDF is purchased.
|
|
315
|
+
|
|
316
|
+
**`baymard-filter-*` — Filter (10 rules, §3.6):** placeholders `baymard-filter-01` … `baymard-filter-10` covering: promote top filters above the product grid; truncate long value lists >10 with styled "More" link; category-specific filters (megapixels, temperature rating); filters for every attribute displayed in list items; expand/collapse icons right-aligned; applied-filter pills visible and individually removable; "clear all" affordance; range sliders with keyboard + numeric input; multi-select affordance obvious; result count live-updated via `aria-live`. Source: §3.6 bullets + https://baymard.com/blog/promoting-product-filters + https://baymard.com/blog/have-filters-for-list-item-info.
|
|
317
|
+
|
|
318
|
+
**`baymard-bread-*` — Breadcrumbs (6 rules, §3.7):** placeholders `baymard-bread-01` … `baymard-bread-06` covering: present on all non-home pages; implement BOTH hierarchy-based AND history-based (68% of top 50 sub-par, 45% only hierarchy, 23% none); present on mobile (65% mobile fail); no "hidden in more" collapse on desktop without reveal; last crumb non-clickable; structured-data markup (`BreadcrumbList`). Source: §3.7 + https://baymard.com/blog/ecommerce-breadcrumbs.
|
|
319
|
+
|
|
320
|
+
**`baymard-pdp-*` — PDP / Product Detail (18 rules, §3.8):** placeholders `baymard-pdp-01` … `baymard-pdp-18` covering: single dominant Add-to-Cart (no 3–6 competing colorful buttons); shipping cost/ETA visible on PDP (64% of users look for it); total visible before checkout (24% abandon otherwise); accordion over horizontal tabs (67% of accordion users mis-implement; 28% use worst-performing tabs); UGC visuals present (67% lack them); minimum 3–5 images + zoom + variant-driven imagery; swatches not dropdowns for variants; out-of-stock variants visible-but-disabled (not removed); star ratings above the fold (up to +18% conversion with verified badges); stock urgency without dark patterns; delivery-date estimator; returns policy on PDP; size guide inline (not in a separate page); Q&A / reviews with filtering; cross-sell without shoving below CTA; "notify me" flow for OOS; price history for discount honesty; country/currency switcher persisted. Source: §3.8 + https://baymard.com/research/product-page.
|
|
321
|
+
|
|
204
322
|
### 3.1 Cart abandonment
|
|
205
323
|
**70.19% average abandonment** across 49 studies 2006–2023, range 55–84.27% (https://baymard.com/lists/cart-abandonment-rate). By device: mobile 77.06%, tablet 66.39%, desktop 70.01%. **Reasons** (excluding 43% "just browsing"): extra costs 48%; forced account creation 24%; slow delivery 19%; distrust with CC 18–19%; too long/complicated 17–18%; couldn't see total up front 16%; errors/crashes 13%; returns policy 12%; declined CC 9%; limited payment methods 7%.
|
|
206
324
|
|