Appendix A — The audit checklist
A printable, 120‑point audit. Work top to bottom; each item links to the lesson that explains it.
Score yourself: ✅ done · ⚠️ partial · ❌ missing · N/A.
How to use it: run this once as a baseline, then quarterly. The delta between runs is your
program's progress. Anything still ❌ after two quarters either doesn't matter for you (mark N/A
and move on) or needs an owner.
1. Measurement (do this first — 12 points)
Check
Lesson
☐
Field RUM collecting LCP, INP, CLS, FCP, TTFB
9.1
☐
Using the attribution build, not the basic one
9.1
☐
Paths normalized before sending (no unbounded cardinality)
9.1
☐
Dimensions: pageType, deviceClass, connection, releaseSha, experiments, isReturning, country
9.1
☐
Collection endpoint is same‑origin, async, always 204
9.1
☐
Commerce custom metrics (atc_ready, interaction latencies)
1.3
☐
Soft navigation timing approximated
9.1
☐
Dashboards: executive, engineering, diagnostic, business
9.1
☐
Alerts on change , not static thresholds
9.1
☐
Alert on RUM data volume dropping
9.1
☐
Baseline lab numbers committed and dated
1.4
☐
Conversion elasticity measured on your own data
1.1
2. Images (14 points)
Check
Lesson
☐
LCP image present in the initial HTML (curl verified)
2.1
☐
sizes matches real rendered width at every breakpoint
2.1
☐
Exactly one priority image per page, on the true LCP element
2.1
☐
Everything below the fold is lazy
2.1
☐
AVIF with WebP fallback enabled
2.1
☐
Quality tuned (AVIF q65–75), verified on a phone
2.1
☐
Every image has reserved space (aspect-ratio or width/height)
6.3
☐
deviceSizes/imageSizes limited to what layouts request
2.1
☐
Transform width allowlist enforced at the CDN
2.1
☐
Image CDN hit ratio > 98%
2.1
☐
Blur placeholders only where they earn their bytes
2.1
☐
SVG for icons and flat graphics, never PNG
2.1
☐
decoding="async" on grid images
5.4
☐
No image waste > 1.5× (console audit run)
2.1
3. Fonts (8 points)
Check
Lesson
☐
Self‑hosted via next/font; no third‑party font origin
2.2
☐
display: swap everywhere
2.2
☐
Metric‑compatible fallbacks (adjustFontFallback / size-adjust)
2.2
☐
WOFF2 only
2.2
☐
Subset to needed scripts + Latin‑1 + punctuation + currency
2.2
☐
Variable fonts where 3+ weights are used
2.2
☐
At most 1–2 preloaded fonts, with crossorigin
2.2
☐
No icon fonts
2.2
4. Third parties (10 points)
Check
Lesson
☐
Complete inventory with bytes, ms, and a named owner per tag
2.3
☐
Cost measured via WebPageTest request blocking
2.3
☐
Long Animation Frame monitoring in production
2.3
☐
Only genuinely required scripts use beforeInteractive
2.3
☐
Chat, video, maps, reviews, social behind facades
2.3
☐
Marketing tags on lazyOnload or idle
2.3
☐
Consent banner overlays (no CLS), bundle < 30 KB
2.3
☐
Zero non‑essential third parties on checkout
7.4
☐
Server‑side event collection for analytics
2.3
☐
CI blocks new third‑party origins
2.3
5. Delivery & caching (12 points)
Check
Lesson
☐
Brotli/Zstd on all text assets, verified with curl
2.4
☐
JSON, SVG, and RSC payloads compressed
2.4
☐
Compression happens in exactly one place
2.4
☐
immutable on all hashed assets
2.4
☐
s-maxage + stale-while-revalidate on cacheable HTML
2.4
☐
no-store only on cart/checkout/account
8.3
☐
Tracking params stripped from the cache key
2.4
☐
Device bucketing (2–3 buckets); no raw UA in the key
2.4
☐
Surrogate keys with soft purge as the default
7.2
☐
HTTP/3 enabled and verified
2.4
☐
≤ 3 preconnects, correct crossOrigin
2.4
☐
CDN HTML hit ratio > 90% on cacheable routes
7.2
6. Rendering architecture (14 points)
Check
Lesson
☐
Every route's intended mode documented and gated in CI
3.1
☐
No cookies()/headers() in the root or shared layouts
3.1
☐
generateStaticParams covers the traffic knee, not everything
3.5
☐
dynamicParams: true for the long tail
3.5
☐
Event‑driven revalidation, signed, batched, rate‑limited
3.5
☐
CDN purge alongside revalidateTag
7.2
☐
Jittered TTLs; stampede protection tested under load
3.5
☐
Shared cache handler if self‑hosting multi‑instance
3.4
☐
Every fetch has explicit cache intent
3.4
☐
Tag hierarchy designed; no single global tag
3.4
☐
Nothing session‑derived is cached, enforced by a CI test
3.6
☐
PPR: dynamic reads inside Suspense boundaries; 2–4 holes
3.6
☐
Middleware matcher is an allowlist; p95 ≤ 5 ms; no network calls
3.7
☐
Streaming verified end‑to‑end in production (curl -N)
3.3
7. JavaScript payload (12 points)
Check
Lesson
☐
First Load JS per route within budget
1.5
☐
Shared chunk understood line by line
4.1
☐
Root layout has no 'use client'; providers scoped by route group
3.2
☐
children pass‑through used for client shells
3.2
☐
'use client' only on interactive leaves
3.2
☐
RSC payload measured and budgeted per route
3.2
☐
Boundary mappers; no whole entities crossing
3.2
☐
No barrel imports from large packages
4.3
☐
optimizePackageImports configured
4.3
☐
Dates/prices via cached Intl formatters
4.3
☐
browserslist matches your real user base
4.1
☐
server-only on every data‑access module
3.2
8. React runtime (12 points)
Check
Lesson
☐
Profiling done on production builds at 4–6× throttling
5.1
☐
Commit count per interaction is 1–2
5.1
☐
No derived state computed in effects
5.1
☐
No monolithic context; split by change frequency
5.3
☐
All context values memoized; actions permanently stable
5.2
☐
High‑frequency shared state in an external store with selectors
5.3
☐
Filters/sort/pagination in the URL
5.3
☐
startTransition on every expensive update
5.5
☐
Urgent feedback outside every transition
5.5
☐
Long loops chunked with scheduler.yield
5.5
☐
Every memoization measured before/after
5.2
☐
Zero hydration mismatches; production reporting wired
4.4
9. Data & backend (10 points)
Check
Lesson
☐
Server-Timing emitted and forwarded to RUM
6.4
☐
No sequential awaits for independent data
7.1
☐
Preload pattern across layout/page boundaries
7.1
☐
cache() on every data accessor; DataLoaders per request
7.1
☐
Every external call has a timeout, with a documented budget
7.1
☐
Circuit breakers on flaky services
7.1
☐
BFF responses shaped to what the UI renders
7.1
☐
No N+1 patterns; batch endpoints where counts scale
7.1
☐
Keep‑alive configured for backend HTTP
8.6
☐
Cart repriced server‑side on every view
7.4
10. Search & lists (8 points)
Check
Lesson
☐
Search shell streams; TTFB independent of query latency
7.3
☐
Only displayed facets requested; values capped
7.3
☐
Filter keys normalized (allowlisted, deduped, sorted)
7.3
☐
Typeahead: debounced network, deferred render, aborted requests, ≤ 8 items
7.3
☐
Suggestion endpoint edge‑cached
7.3
☐
content-visibility on off‑screen list items
2.5
☐
Infinite scroll capped, URL‑synced, with a paginated fallback
5.4
☐
Scroll restoration works on back navigation
5.4
11. Advanced (10 points)
Check
Lesson
☐
bfcache working (restore rate measured in the field)
8.3
☐
Zero unload listeners; beforeunload conditional
8.3
☐
<Link prefetch> audited on dense grids
8.1
☐
Speculation Rules at moderate, cart/checkout excluded
8.1
☐
Analytics prerender‑aware
8.1
☐
Every listener/timer/observer cleaned up
8.4
☐
All client caches bounded
8.4
☐
Long‑session memory and INP tests in CI
8.4
☐
No anti‑flicker snippet ; variants assigned at the edge
8.5
☐
Flag registry with owners and expiry, enforced in CI
8.5
12. Operating (10 points)
Check
Lesson
☐
Budgets derived from a UX target, per page type
1.5
☐
Deterministic gates block; noisy ones warn
9.2
☐
Bundle budgets gzipped, compared against the base branch
9.2
☐
Route rendering mode gated
9.2
☐
Client Component count ratcheted
9.2
☐
PR comment explains failures and suggests fixes
9.2
☐
Synthetics on vitals, cache health, and a purchase journey
9.2
☐
Cross‑system change log (deploys, tags, CDN, CMS, vendors)
9.3
☐
Named owner per page type; one‑page scorecard
9.4
☐
Written budget exception process with expiry dates
1.5
13. Mobile (8 points)
Check
Lesson
☐
Tested on a real mid‑tier Android in the last quarter
10.6
☐
DevTools default is 4–6× CPU throttling
10.6
☐
Mobile budgets set tighter than desktop
10.6
☐
touch-action: manipulation on interactive elements
10.6
☐
Touch targets ≥ 44×44 px with spacing
10.6
☐
Viewport allows zoom
10.6
☐
Save-Data respected
10.6
☐
DOM ≤ 1,500 nodes on list pages
10.6
Scoring
Total items: 120
0–40 🔴 Start with sections 1, 2, 3, 4 — the Tier 1 quick wins
41–70 🟠 Foundations in place; move to sections 6 and 7 (architecture)
71–95 🟡 Solid. Focus on 8, 9, and 11 (interaction and advanced)
96–120 🟢 Mature. Section 12 is what keeps you here
The five items that matter most if you can only do five:
Field RUM with attribution (§1)
LCP image in the HTML with correct sizes (§2)
bfcache working (§11)
Nothing session‑derived is cached, with a CI test (§6)
Bundle budgets gated in CI (§12)