@ctxr/skill-frontend-excellence 0.1.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/CHANGELOG.md +37 -0
- package/LICENSE +21 -0
- package/README.md +114 -0
- package/SKILL.md +227 -0
- package/package.json +63 -0
- package/references/accessibility.md +396 -0
- package/references/audit-workflow.md +390 -0
- package/references/components.md +247 -0
- package/references/data-viz.md +457 -0
- package/references/defects.md +152 -0
- package/references/design.md +513 -0
- package/references/forms.md +485 -0
- package/references/lighthouse.md +242 -0
- package/references/motion.md +642 -0
- package/references/performance.md +416 -0
- package/references/pre-launch.md +342 -0
- package/references/responsive.md +519 -0
- package/references/seo.md +422 -0
- package/references/ui-ux.md +565 -0
- package/scripts/check-no-dashes.mjs +90 -0
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
# Pre-Launch Checklist
|
|
2
|
+
|
|
3
|
+
The final verification gate before any public-visible page or interface is declared complete. Run every item on every change. Treat any failure as a blocking defect.
|
|
4
|
+
|
|
5
|
+
## How to Use This Checklist
|
|
6
|
+
|
|
7
|
+
1. Print or pin in your editor.
|
|
8
|
+
2. Walk top to bottom on every page that changed.
|
|
9
|
+
3. For shared components, walk every page that consumes them.
|
|
10
|
+
4. Don't skip items because "they passed last time"; regressions hide in unchanged areas.
|
|
11
|
+
5. If a page genuinely doesn't apply (e.g., no forms), mark "n/a"; don't silently skip.
|
|
12
|
+
|
|
13
|
+
## 1. Lighthouse (Production Build)
|
|
14
|
+
|
|
15
|
+
Run against the production build, not the dev server. Run mobile and desktop separately. Run at least 3 times; take the median.
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
<framework-build>
|
|
19
|
+
<framework-start-prod-server> -p 3001 &
|
|
20
|
+
export CHROME_PATH="$(find ~/Library/Caches/ms-playwright -name 'Google Chrome for Testing' -type f 2>/dev/null | head -1)"
|
|
21
|
+
|
|
22
|
+
# Mobile
|
|
23
|
+
npx lighthouse "http://localhost:3001/<path>" \
|
|
24
|
+
--output=json --output-path=/tmp/lh-mob.json \
|
|
25
|
+
--chrome-flags="--headless=new --no-sandbox --disable-gpu" \
|
|
26
|
+
--only-categories=performance,accessibility,best-practices,seo --quiet
|
|
27
|
+
|
|
28
|
+
# Desktop
|
|
29
|
+
npx lighthouse "http://localhost:3001/<path>" \
|
|
30
|
+
--output=json --output-path=/tmp/lh-desk.json \
|
|
31
|
+
--preset=desktop \
|
|
32
|
+
--chrome-flags="--headless=new --no-sandbox --disable-gpu" \
|
|
33
|
+
--only-categories=performance,accessibility,best-practices,seo --quiet
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
| Score | Mobile | Desktop |
|
|
37
|
+
|-------|--------|---------|
|
|
38
|
+
| Performance | >= 95 | >= 99 |
|
|
39
|
+
| Accessibility | 100 | 100 |
|
|
40
|
+
| Best Practices | 100 | 100 |
|
|
41
|
+
| SEO | 100 (or n/a for noindex pages) | 100 (or n/a for noindex pages) |
|
|
42
|
+
|
|
43
|
+
Verify each category. If any score drops below the bar, identify the failing audit and fix per [lighthouse.md](lighthouse.md).
|
|
44
|
+
|
|
45
|
+
## 2. Core Web Vitals (Lab)
|
|
46
|
+
|
|
47
|
+
From the same Lighthouse run, verify each metric:
|
|
48
|
+
|
|
49
|
+
- [ ] LCP < 2.5s mobile, < 2.0s desktop
|
|
50
|
+
- [ ] CLS < 0.1 mobile, < 0.05 desktop
|
|
51
|
+
- [ ] TBT < 200ms mobile, < 100ms desktop
|
|
52
|
+
- [ ] FCP < 1.8s mobile, < 1.0s desktop
|
|
53
|
+
- [ ] TTFB < 800ms mobile, < 600ms desktop
|
|
54
|
+
|
|
55
|
+
INP is not in lab Lighthouse; verify in the field via `web-vitals` JS instrumentation.
|
|
56
|
+
|
|
57
|
+
## 3. Asset Budgets
|
|
58
|
+
|
|
59
|
+
- [ ] Initial JS payload (gzipped) < budget (default 90 KB mobile / 130 KB desktop)
|
|
60
|
+
- [ ] Initial CSS payload (gzipped) < budget (default 25 KB mobile / 35 KB desktop)
|
|
61
|
+
- [ ] Above-the-fold image budget met
|
|
62
|
+
- [ ] <= 2 font families, <= 4 weights total
|
|
63
|
+
- [ ] Third-party scripts within count and main-thread time budget
|
|
64
|
+
|
|
65
|
+
If your tooling supports `bundlesize`, `size-limit`, or a custom CI check, run it. Treat budget violations as blocking.
|
|
66
|
+
|
|
67
|
+
## 4. Accessibility
|
|
68
|
+
|
|
69
|
+
### Automated
|
|
70
|
+
|
|
71
|
+
- [ ] Lighthouse Accessibility = 100
|
|
72
|
+
- [ ] axe DevTools (or `@axe-core/playwright`) shows zero violations
|
|
73
|
+
- [ ] HTML validates (no broken markup)
|
|
74
|
+
|
|
75
|
+
### Manual
|
|
76
|
+
|
|
77
|
+
- [ ] Tab through the entire page in document order
|
|
78
|
+
- [ ] Every interactive element shows a visible focus ring with 3:1 contrast against surface and resting state
|
|
79
|
+
- [ ] Esc closes any open modal, popover, dropdown
|
|
80
|
+
- [ ] Forms: labels visible, required marked, error inline + announced, focus moves to first invalid
|
|
81
|
+
- [ ] Modals: focus moves in on open, trapped while open, restored to trigger on close
|
|
82
|
+
- [ ] Screen reader pass on the primary user flow (VoiceOver or NVDA)
|
|
83
|
+
- [ ] Reading order matches visual order
|
|
84
|
+
- [ ] Headings: one H1, sequential, no skipped levels
|
|
85
|
+
- [ ] Images: every meaningful image has descriptive alt; decorative images have alt=""
|
|
86
|
+
- [ ] Links: descriptive text (not "click here")
|
|
87
|
+
- [ ] Skip-to-content link present and working
|
|
88
|
+
|
|
89
|
+
### Visual accessibility
|
|
90
|
+
|
|
91
|
+
- [ ] Body text contrast >= 4.5:1 in both light and dark mode (verified independently, not by inversion)
|
|
92
|
+
- [ ] Large text and meaningful UI graphics >= 3:1
|
|
93
|
+
- [ ] Color is never the only signal (status, error, success paired with icon or text)
|
|
94
|
+
- [ ] Page usable at 200% browser zoom with no horizontal scroll
|
|
95
|
+
- [ ] Page usable at largest system text size
|
|
96
|
+
|
|
97
|
+
## 5. Responsive
|
|
98
|
+
|
|
99
|
+
Test at every breakpoint and orientation.
|
|
100
|
+
|
|
101
|
+
- [ ] 320px (smallest supported phone)
|
|
102
|
+
- [ ] 375px (typical phone)
|
|
103
|
+
- [ ] 768px (tablet portrait)
|
|
104
|
+
- [ ] 1024px (tablet landscape, small laptop)
|
|
105
|
+
- [ ] 1280px (desktop)
|
|
106
|
+
- [ ] 1920px (large desktop)
|
|
107
|
+
- [ ] Phone landscape (short height)
|
|
108
|
+
- [ ] Tablet landscape
|
|
109
|
+
|
|
110
|
+
Per breakpoint:
|
|
111
|
+
|
|
112
|
+
- [ ] No horizontal scroll
|
|
113
|
+
- [ ] No clipped content
|
|
114
|
+
- [ ] Layout is intentional, not just fluid
|
|
115
|
+
- [ ] Touch targets >= 44x44 with 8px gaps (mobile/tablet)
|
|
116
|
+
- [ ] Body text >= 16px on mobile (avoids iOS auto-zoom)
|
|
117
|
+
- [ ] Tables either fit, scroll horizontally, or transform to cards
|
|
118
|
+
- [ ] Sidebar / nav transforms appropriately
|
|
119
|
+
- [ ] Modals fit smallest viewport
|
|
120
|
+
- [ ] Safe areas respected (notch, dynamic island, gesture bar)
|
|
121
|
+
- [ ] `100dvh` (not `100vh`) for full-height mobile sections
|
|
122
|
+
|
|
123
|
+
## 6. Theme
|
|
124
|
+
|
|
125
|
+
- [ ] Light mode designed and tested independently
|
|
126
|
+
- [ ] Dark mode designed and tested independently (not just inverted)
|
|
127
|
+
- [ ] All semantic tokens work in both modes
|
|
128
|
+
- [ ] Borders and dividers visible in both modes
|
|
129
|
+
- [ ] Focus rings visible in both modes
|
|
130
|
+
- [ ] Imagery looks correct in both modes (may need separate dark variants)
|
|
131
|
+
- [ ] Theme toggle (if present) works without flicker
|
|
132
|
+
- [ ] Default theme respects `prefers-color-scheme`
|
|
133
|
+
- [ ] User-selected theme persists across navigation
|
|
134
|
+
|
|
135
|
+
## 7. Motion
|
|
136
|
+
|
|
137
|
+
- [ ] All animations use `transform` and/or `opacity` (no `width`, `height`, `top`, `left`, `margin`)
|
|
138
|
+
- [ ] Durations 100-500ms (no animations longer than 500ms in routine UI)
|
|
139
|
+
- [ ] Exit faster than entrance (60-70%)
|
|
140
|
+
- [ ] `prefers-reduced-motion: reduce` removes or shortens non-essential animation
|
|
141
|
+
- [ ] Loading: skeleton at 300ms+, spinner before, progress for determinate
|
|
142
|
+
- [ ] Spinner / skeleton has accessible name or `aria-busy`
|
|
143
|
+
- [ ] Animations don't block input
|
|
144
|
+
- [ ] Animations don't cause layout shift (CLS)
|
|
145
|
+
- [ ] Continuous animations pause when off-screen and tab is inactive
|
|
146
|
+
|
|
147
|
+
## 8. Visual Quality
|
|
148
|
+
|
|
149
|
+
### Typography
|
|
150
|
+
|
|
151
|
+
- [ ] Maximum 2 font families, 4 weights total
|
|
152
|
+
- [ ] Distinctive choices (not just Inter on white)
|
|
153
|
+
- [ ] Type scale is consistent (multiplicative, not random)
|
|
154
|
+
- [ ] Body text 16px+ on mobile
|
|
155
|
+
- [ ] Line height 1.5-1.75 for body
|
|
156
|
+
- [ ] Line length 60-75 characters for prose
|
|
157
|
+
- [ ] Tabular figures for numeric columns
|
|
158
|
+
|
|
159
|
+
### Color
|
|
160
|
+
|
|
161
|
+
- [ ] Semantic tokens used (no raw hex in components)
|
|
162
|
+
- [ ] Dominant + 1-2 accents (not evenly distributed)
|
|
163
|
+
- [ ] Brand color contrasts properly in both modes
|
|
164
|
+
- [ ] Neutral scale used consistently for surfaces and text
|
|
165
|
+
|
|
166
|
+
### Spacing
|
|
167
|
+
|
|
168
|
+
- [ ] Spacing scale chosen (4-pt or 8-pt)
|
|
169
|
+
- [ ] No random spacing values
|
|
170
|
+
- [ ] Visual rhythm consistent
|
|
171
|
+
|
|
172
|
+
### Iconography
|
|
173
|
+
|
|
174
|
+
- [ ] One icon set throughout
|
|
175
|
+
- [ ] Consistent stroke width
|
|
176
|
+
- [ ] Consistent sizes per hierarchy level
|
|
177
|
+
- [ ] No emoji as structural icons (only as accents where intentional)
|
|
178
|
+
- [ ] SVG only (no PNG icons)
|
|
179
|
+
|
|
180
|
+
### Composition
|
|
181
|
+
|
|
182
|
+
- [ ] At least one section breaks the safe centered three-card layout (where appropriate to the brand)
|
|
183
|
+
- [ ] Visual hierarchy: scan the page; the most important element is the largest/boldest
|
|
184
|
+
- [ ] Whitespace intentional; not just residual
|
|
185
|
+
- [ ] One primary CTA per screen
|
|
186
|
+
|
|
187
|
+
## 9. SEO (public-visible pages)
|
|
188
|
+
|
|
189
|
+
- [ ] Unique `<title>` 50-60 chars
|
|
190
|
+
- [ ] Unique `<meta name="description">` 140-160 chars
|
|
191
|
+
- [ ] One `<h1>` matching primary intent
|
|
192
|
+
- [ ] Sequential headings, no skipped levels
|
|
193
|
+
- [ ] Self-referencing `<link rel="canonical">`
|
|
194
|
+
- [ ] `<meta name="robots" content="index, follow">` (or `noindex` if not indexable)
|
|
195
|
+
- [ ] Open Graph tags (og:title, og:description, og:image 1200x630, og:url, og:type)
|
|
196
|
+
- [ ] Twitter card tags
|
|
197
|
+
- [ ] `<html lang="...">`
|
|
198
|
+
- [ ] Structured data validated via Rich Results Test (where applicable)
|
|
199
|
+
- [ ] Image alt text on every meaningful image
|
|
200
|
+
- [ ] Internal links use descriptive anchor text (not "click here")
|
|
201
|
+
- [ ] Page reachable from home in <= 3 clicks
|
|
202
|
+
- [ ] Listed in sitemap.xml (if indexable)
|
|
203
|
+
- [ ] HTTPS, no mixed content
|
|
204
|
+
- [ ] No render-blocking content critical to indexing
|
|
205
|
+
|
|
206
|
+
## 10. State Coverage
|
|
207
|
+
|
|
208
|
+
Every screen and component has intentional designs for:
|
|
209
|
+
|
|
210
|
+
- [ ] Empty (with message and action, not blank)
|
|
211
|
+
- [ ] Loading (skeleton matching layout, or spinner)
|
|
212
|
+
- [ ] Success (brief feedback)
|
|
213
|
+
- [ ] Error (cause + fix + recovery action)
|
|
214
|
+
- [ ] Disabled (visually distinct, programmatically disabled)
|
|
215
|
+
- [ ] Initial / first-run (where applicable)
|
|
216
|
+
- [ ] Offline (network-dependent actions disabled, message shown)
|
|
217
|
+
- [ ] Limit reached (where applicable)
|
|
218
|
+
|
|
219
|
+
## 11. Forms (if forms changed)
|
|
220
|
+
|
|
221
|
+
- [ ] Every input has a visible, programmatic label
|
|
222
|
+
- [ ] Right `type` and `inputmode` for the data
|
|
223
|
+
- [ ] `autocomplete` per WHATWG spec (especially for username/password/address/payment)
|
|
224
|
+
- [ ] Required fields marked visually + `aria-required`
|
|
225
|
+
- [ ] Validation on blur (not on every keystroke)
|
|
226
|
+
- [ ] Errors inline, near the field, with cause + fix
|
|
227
|
+
- [ ] Errors announced via `role="alert"` or `aria-live`
|
|
228
|
+
- [ ] On submit error, focus moves to first invalid field
|
|
229
|
+
- [ ] Submit button has loading state, disabled during submission, specific verb-noun label
|
|
230
|
+
- [ ] Helper text for complex fields
|
|
231
|
+
- [ ] Long forms autosave; "Saved" indicator visible
|
|
232
|
+
- [ ] Multi-step forms show progress and allow back navigation
|
|
233
|
+
- [ ] Destructive actions confirm or provide undo
|
|
234
|
+
- [ ] Tested with password manager / autofill
|
|
235
|
+
|
|
236
|
+
## 12. Charts and Tables (if data viz changed)
|
|
237
|
+
|
|
238
|
+
- [ ] Right chart for the data
|
|
239
|
+
- [ ] Axes labeled with units
|
|
240
|
+
- [ ] Colorblind-safe palette
|
|
241
|
+
- [ ] Color paired with shape/pattern/label
|
|
242
|
+
- [ ] Tooltip works on hover AND tap
|
|
243
|
+
- [ ] Text alternative (summary or accessible data table)
|
|
244
|
+
- [ ] Interactive elements keyboard-accessible
|
|
245
|
+
- [ ] Touch targets >= 44x44
|
|
246
|
+
- [ ] Responsive: simplifies on small screens
|
|
247
|
+
- [ ] Loading skeleton matches layout
|
|
248
|
+
- [ ] Empty state with message and action
|
|
249
|
+
- [ ] Error state with retry
|
|
250
|
+
- [ ] Numbers locale-formatted
|
|
251
|
+
- [ ] Tables: sorting, sticky header, mobile-adaptive
|
|
252
|
+
|
|
253
|
+
## 13. Cross-Browser
|
|
254
|
+
|
|
255
|
+
Test on at least:
|
|
256
|
+
|
|
257
|
+
- [ ] Latest Chrome (Chromium engine, what most users have)
|
|
258
|
+
- [ ] Latest Safari (WebKit, all iOS users + many macOS users)
|
|
259
|
+
- [ ] Latest Firefox (Gecko, smaller share but valuable diversity)
|
|
260
|
+
|
|
261
|
+
For supported older browsers (per browserslist), spot-check key flows.
|
|
262
|
+
|
|
263
|
+
For Safari:
|
|
264
|
+
|
|
265
|
+
- `:has()` (now widely supported, but verify on older iOS)
|
|
266
|
+
- `<dialog>` (added in Safari 15.4)
|
|
267
|
+
- `view-transition` API (Safari 18+)
|
|
268
|
+
- Container queries (Safari 16+)
|
|
269
|
+
- Backdrop filter (use prefixed `-webkit-backdrop-filter`)
|
|
270
|
+
|
|
271
|
+
## 14. Real-User Monitoring
|
|
272
|
+
|
|
273
|
+
If RUM is set up:
|
|
274
|
+
|
|
275
|
+
- [ ] `web-vitals` library ships LCP, INP, CLS, FCP, TTFB to your pipeline
|
|
276
|
+
- [ ] Monitoring view shows p75 over rolling 28 days
|
|
277
|
+
- [ ] Alerts fire when p75 crosses thresholds
|
|
278
|
+
- [ ] Source maps uploaded for production error symbolication
|
|
279
|
+
|
|
280
|
+
## 15. Documentation
|
|
281
|
+
|
|
282
|
+
- [ ] Component docs updated (if applicable)
|
|
283
|
+
- [ ] Storybook / playground stories cover new states
|
|
284
|
+
- [ ] Design system tokens updated (if new tokens introduced)
|
|
285
|
+
- [ ] README / CHANGELOG updated (if significant change)
|
|
286
|
+
|
|
287
|
+
## 16. Git and Review
|
|
288
|
+
|
|
289
|
+
- [ ] Branch is up to date with main
|
|
290
|
+
- [ ] All changes are intentional (review the diff)
|
|
291
|
+
- [ ] No leftover console.log, debugger, TODO, FIXME without owner
|
|
292
|
+
- [ ] No leftover commented-out code
|
|
293
|
+
- [ ] Tests pass (unit, integration, e2e if applicable)
|
|
294
|
+
- [ ] Lint and format pass
|
|
295
|
+
- [ ] Type check passes
|
|
296
|
+
- [ ] Build succeeds for production target
|
|
297
|
+
|
|
298
|
+
## 17. Multi-Page Polish Gate
|
|
299
|
+
|
|
300
|
+
If the change affects multiple pages or shared widgets, the polish gate must pass before launch. The full procedure lives in [audit-workflow.md](audit-workflow.md) Phase 19. The launch-relevant subset is:
|
|
301
|
+
|
|
302
|
+
- [ ] Widget inventory exists for the affected widget families
|
|
303
|
+
- [ ] Same-purpose widgets are extracted to one source of truth or normalized to one contract
|
|
304
|
+
- [ ] Drift collector returns no unexplained differences across pages for shared widgets
|
|
305
|
+
- [ ] Geometry sweep returns zero issues on every affected route at `1440x900` and `375x812`
|
|
306
|
+
- [ ] Before-and-after screenshots captured at both viewports for every affected route
|
|
307
|
+
- [ ] Reference comparison heuristics in [design.md](design.md) pass
|
|
308
|
+
- [ ] No same-purpose widget looks different on two routes without a named, intentional variant
|
|
309
|
+
|
|
310
|
+
Treat any failure as blocking. The full Phase 19 acceptance list in [audit-workflow.md](audit-workflow.md) is authoritative when both gates apply; this section is the launch-time subset.
|
|
311
|
+
|
|
312
|
+
## 18. Final Smell Test
|
|
313
|
+
|
|
314
|
+
Open the page in a fresh browser (incognito to avoid cached assets). Walk through it as a new user would. Ask yourself:
|
|
315
|
+
|
|
316
|
+
- Is the primary action obvious within 2 seconds?
|
|
317
|
+
- Does the surface feel like a single product, or a collection of unrelated pieces?
|
|
318
|
+
- Does it look distinctive, or could it be any other product's equivalent screen?
|
|
319
|
+
- Would I be proud to share this URL?
|
|
320
|
+
|
|
321
|
+
If "no" to any, address it before declaring complete.
|
|
322
|
+
|
|
323
|
+
## When the Checklist Fails
|
|
324
|
+
|
|
325
|
+
Don't move on. The checklist exists because every item on it has, at some point, been the regression that shipped to production.
|
|
326
|
+
|
|
327
|
+
For each failure:
|
|
328
|
+
|
|
329
|
+
1. Identify the specific cause.
|
|
330
|
+
2. Fix at the right layer (component, page, system, or design token).
|
|
331
|
+
3. Re-run the relevant section of the checklist (not the whole thing).
|
|
332
|
+
4. Once green, run a final full pass to verify nothing else regressed.
|
|
333
|
+
|
|
334
|
+
## See Also
|
|
335
|
+
|
|
336
|
+
- [lighthouse.md](lighthouse.md) for score-driven audit fixes
|
|
337
|
+
- [accessibility.md](accessibility.md) for a11y deep dive
|
|
338
|
+
- [seo.md](seo.md) for SEO requirements
|
|
339
|
+
- [responsive.md](responsive.md) for layout testing
|
|
340
|
+
- [audit-workflow.md](audit-workflow.md) for multi-page polish work
|
|
341
|
+
- [components.md](components.md) for component contracts and drift detection
|
|
342
|
+
- [defects.md](defects.md) for symptom-to-fix lookup and geometry sweep
|