Skip to content

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:

  1. Field RUM with attribution (§1)
  2. LCP image in the HTML with correct sizes (§2)
  3. bfcache working (§11)
  4. Nothing session‑derived is cached, with a CI test (§6)
  5. Bundle budgets gated in CI (§12)