# The Website Specification — checklist (25 items)

## Performance
- [ ] **Core Web Vitals (LCP, INP, CLS)** _(required)_ — Core Web Vitals measure loading, responsiveness, and visual stability. Hit LCP ≤ 2.5s, INP ≤ 200ms, and CLS ≤ 0.1 at the 75th percentile of real users.
      https://specification.website/spec/performance/core-web-vitals/
- [ ] **Image optimisation** _(required)_ — Serve images in modern formats (WebP, AVIF), at the right size for the viewport, with explicit dimensions. Images are the largest payload on most pages.
      https://specification.website/spec/performance/image-optimization/
- [ ] **Lazy loading images, iframes, and video** _(recommended)_ — Native lazy loading defers off-screen images, iframes, and (recently) video until the user scrolls near them. Use loading="lazy" — but never on the LCP element.
      https://specification.website/spec/performance/lazy-loading/
- [ ] **Preload, prefetch, preconnect** _(recommended)_ — Resource hints let you tell the browser what is coming. Preload the LCP image and critical fonts, preconnect to third-party origins, prefetch the next navigation.
      https://specification.website/spec/performance/preload-prefetch-preconnect/
- [ ] **103 Early Hints** _(optional)_ — An informational HTTP response that carries Link headers — preload, preconnect — to the browser before the final response is ready, putting server think-time to work.
      https://specification.website/spec/performance/early-hints/
- [ ] **Cache-Control headers** _(required)_ — Cache-Control tells browsers and CDNs how long to keep a response. Use immutable + max-age=31536000 for fingerprinted assets and short or no-cache for HTML.
      https://specification.website/spec/performance/cache-control/
- [ ] **Conditional requests (ETag, Last-Modified, 304)** _(recommended)_ — Send a validator — ETag or Last-Modified — on every cacheable response, and honour If-None-Match / If-Modified-Since so unchanged resources return an empty 304 instead of the full body.
      https://specification.website/spec/performance/conditional-requests/
- [ ] **No-Vary-Search response header** _(recommended)_ — The `No-Vary-Search` response header tells browsers and caches that some URL query parameters (tracking, UTM, sort order) do not change the response. The cached entry for the canonical URL is reused for variants — fewer fetches, better prefetch hits, less duplicate work.
      https://specification.website/spec/performance/no-vary-search/
- [ ] **Compression (gzip, brotli, zstd)** _(required)_ — Compress text responses with brotli where supported, gzip everywhere else. zstd is emerging. Don't compress already-compressed media.
      https://specification.website/spec/performance/compression/
- [ ] **Web font loading** _(recommended)_ — Self-host WOFF2 fonts, subset them, set font-display: swap so text is readable while the font loads, and preload the critical face only when it styles above-the-fold content.
      https://specification.website/spec/performance/font-loading/
- [ ] **Critical CSS and render-blocking resources** _(recommended)_ — Inline the CSS needed for above-the-fold content and defer the rest. Render-blocking resources in <head> are the single biggest cause of slow first paint.
      https://specification.website/spec/performance/critical-css/
- [ ] **Script loading — defer, async, module** _(recommended)_ — Choose the right script-loading attribute for every <script>: defer for app code, async for independent third-party, type=module for modern code. Bare <script> in <head> is always wrong.
      https://specification.website/spec/performance/script-loading/
- [ ] **HTTP/2 and HTTP/3** _(recommended)_ — Serve over HTTP/2 at minimum and HTTP/3 where you can. Multiplexing eliminates head-of-line blocking; QUIC removes TCP handshake delays.
      https://specification.website/spec/performance/http3/
- [ ] **HTTP/1.1 workarounds: sharding, sprites, and bundling** _(avoid)_ — Domain sharding and image sprites were workarounds for HTTP/1.1's connection limit; under HTTP/2 and HTTP/3 they hurt — drop them. Bundling is the nuanced one: stop concatenating to cut requests, start doing it to cut bytes.
      https://specification.website/spec/performance/http1-workarounds/
- [ ] **Speculation Rules** _(recommended)_ — Tell the browser which links to prefetch or prerender before the user clicks. Done well, navigations feel instant; done carelessly, you burn bandwidth on pages nobody visits.
      https://specification.website/spec/performance/speculation-rules/
- [ ] **Resource hints overview** _(recommended)_ — Five resource hints — dns-prefetch, preconnect, preload, modulepreload, prefetch — cover every stage of the request lifecycle. Pick the right one for the job.
      https://specification.website/spec/performance/resource-hints/
- [ ] **View Transitions** _(optional)_ — Animate between states (same-document) or between pages (cross-document) with a single CSS opt-in. Replaces ad-hoc SPA animation libraries with a platform primitive.
      https://specification.website/spec/performance/view-transitions/
- [ ] **Back/forward cache (BFCache)** _(recommended)_ — Keep pages BFCache-eligible so back/forward navigation restores them instantly from memory, with no reload, no hydration, and no repaint.
      https://specification.website/spec/performance/bfcache/
- [ ] **Visibility-aware rendering** _(optional)_ — Use `content-visibility` with `contain-intrinsic-size` to skip layout and paint for off-screen content, and Intersection Observer to drive lazy behaviour, instead of scroll and resize listeners.
      https://specification.website/spec/performance/visibility-aware-rendering/
- [ ] **CSS containment** _(optional)_ — Use `contain: layout paint style` (or the `contain: content` shorthand) to tell the browser that an element's internals cannot affect the rest of the page, so reflow and repaint stay isolated to that subtree.
      https://specification.website/spec/performance/css-containment/
- [ ] **Scroll-driven animations** _(optional)_ — Drive CSS animations from scroll position or element visibility with `scroll-timeline` and `view-timeline`, replacing JS scroll-listener libraries with compositor-thread animation.
      https://specification.website/spec/performance/scroll-driven-animations/
- [ ] **Scrollbar gutter** _(recommended)_ — Use scrollbar-gutter: stable to reserve scrollbar space and stop horizontal layout shift between pages or states that overflow vs. don't.
      https://specification.website/spec/performance/scrollbar-gutter/
- [ ] **Dynamic viewport units (dvh, svh, lvh)** _(recommended)_ — On mobile, 100vh is taller than the screen because it ignores the browser's collapsing toolbar. Use dvh, svh, and lvh to size full-height elements to the viewport that is actually visible.
      https://specification.website/spec/performance/dynamic-viewport-units/
- [ ] **Compression Dictionary Transport** _(optional)_ — Use a previously served response, or a dedicated dictionary, as a Brotli/Zstandard dictionary so updated assets compress to a fraction of their size. Pure progressive enhancement over ordinary compression.
      https://specification.website/spec/performance/compression-dictionary-transport/
- [ ] **Server-Timing header** _(optional)_ — Server-Timing surfaces backend metrics — database time, cache hits, edge processing — in browser DevTools and to RUM via the PerformanceServerTiming API. Send it when you measure server-side latency, and keep the values free of sensitive infrastructure detail.
      https://specification.website/spec/performance/server-timing/
