Measured results
What each feature is worth, measured on a reference site with Lighthouse and browsers. We took features away one by one and noted what made no difference.
We measured in October 2026 on a reference site built as this playbook describes. It has server-rendered pages, inline CSS, one module script, an AVIF hero, self-hosted fonts and Brotli. The lab served it from its Node server over plain HTTP/1.1, without nginx, HTTP/2 or TLS. The baseline still prefetched every link at once and used font-display: swap. Both changed after these results. The tool was Lighthouse 12.8 in Chrome 143, with simulated throttling. "Mobile" means a mid-range phone on slow 4G. "Desktop" means a fast connection. Each variant is a copy of the site with one change, built and served the same way. Figures are the median of 3 runs on two pages, a home page and a content page. The SEO and accessibility rows used one run on the home page. Where it mattered, we confirmed them with 7 runs. To repeat it, see Measuring it yourself.
The reference site
| Page | Performance | Accessibility | Best Practices | SEO | LCP | CLS | TBT |
|---|---|---|---|---|---|---|---|
| Start page, mobile | 99 | 100 | 100 | 92 | 2.1 s | 0 | 0 ms |
| Service page, mobile | 99 | 100 | 100 | 92 | 2.1 s | 0 | 0 ms |
| Start page, desktop | 100 | 100 | 100 | 92 | 0.48 s | 0 | 0 ms |
| Service page, desktop | 100 | 100 | 100 | 92 | 0.48 s | 0.011 | 0 ms |
SEO is 92, not 100, only because of Content-Signal lines in robots.txt (see below).
Taking one feature away
Mobile, start page unless noted. "Data" is everything the page downloaded during the test.
| Change | Performance (from 99) | LCP (from 2.10 s) | CLS (from 0) | Data (from 202 KB) | What it shows |
|---|---|---|---|---|---|
| Baseline | 99 | 2.10 s | 0 | 202 KB | — |
| No compression (no brotli or gzip) | 92 (89 on the service page) | 3.30 s (3.75 s on the service page) | 0 | 403 KB | Compression has the biggest effect on load time and data. |
| Content rendered in the browser instead of the HTML | 85 | 2.25 s | 0.295 | 203 KB | Server-side rendering also protects against layout shift. |
| JPEG only, no AVIF or WebP, no srcset | 97 | 2.55 s | 0 | 275 KB | Modern formats save 73 KB and 0.45 s. |
| One 1024 px image for every screen | 98 | 2.25 s | 0 | 207 KB | Responsive sizes are worth about 0.15 s on a phone. |
No content-visibility on far-down sections | 98 | 2.25 s | 0 | 226 KB | Skipping off-screen rendering is worth about 0.15 s. |
| Stylesheet as a file instead of inline | 99 | 1.95 s | 0 | 183 KB | First paint on the service page 0.15 s later (1.35 against 1.20 s), and Lighthouse flags a render-blocking request. LCP looks better only because there is less prefetch traffic (see "Two defaults that measuring overturned" below). |
No hero preload, no fetchpriority | 99 | 2.10 s | 0 | 202 KB | No change: the image is already early in the HTML. Lighthouse still suggests the hint. |
No width/height on the hero | 99 | 2.10 s | 0 | 202 KB | No shift here, because CSS sets the aspect, but Lighthouse flags unsized images. |
font-display: block, no fallback faces | 99 | 2.10 s | 0 | 202 KB | No change on the start page, because fonts arrived before paint. |
No service worker, Cache-Control: no-cache, or view transition back | 99 | 2.10 s | 0 | 202 to 204 KB | No change: Lighthouse measures a first visit only. These were measured with clicks instead (below). |
Two defaults that measuring overturned
Prefetching every link at once costs more than it gives. Prefetching means loading the next pages before anyone clicks. Lighthouse counts every prefetched page against the first load. Removing the eagerness: immediate prefetch took home page LCP from 2.10 s to 1.50 s. Data went from 202 KB to 117 KB. On a page with about 50 links, we tried prefetch on hover (moderate). It took LCP from 3.45 s to 1.51 s, and data from 403 KB to 89 KB. Browsers clicked no faster with immediate prefetch, because a service worker cache already held the pages.
font-display: swap can move long pages. We used size-adjusted fallback fonts. A short home page did not shift. Long pages did, when the fonts arrived and the text re-wrapped. Layout shift went from 0 to 0.226 on desktop and from 0 to 0.123 on a phone. With font-display: optional, every page measured 0.
Lighthouse and browsers disagree on font preloads
Adding two font preloads moved Lighthouse's simulated first paint from 1.35 s to 0.90 s. LCP on the home page got later, from 2.10 s to 2.25 s. Chrome, with the same HTML, showed the opposite. There, phone first paint moved from 43 ms after the HTML to 123 ms. Lighthouse simulates the network. The browser lab measures it. Trust the browser lab. Don't preload fonts unless it shows a gain.
SEO and accessibility checks catch problems
| Change | Score change | Lighthouse audit that failed |
|---|---|---|
| No meta description | SEO from 92 to 85 | meta-description |
No alt on the hero | Accessibility from 100 to 95, SEO from 92 to 85 | image-alt |
No lang | Accessibility from 100 to 96 | html-has-lang |
| Paler grey for secondary text | Accessibility from 100 to 96 | color-contrast |
| Two footer links called "Click here" and "Read more" | SEO from 92 to 85 | link-text |
| No viewport tag | Best Practices from 100 to 93, layout shift from 0 to 0.034 | viewport, font-size |
| No doctype | Best Practices from 100 to 96 | doctype |
noindex on the page | SEO from 92 to 61 | is-crawlable |
No Content-Signal lines in robots.txt | SEO from 92 to 100 | — |
| No robots.txt at all | SEO from 92 to 100 | — |
Lighthouse's SEO score is a floor, not a goal. It does not reward having a robots.txt. It also marks down Content-Signal lines, which robots.txt allows as extra records.
Clicks and repeat visits
We used Chromium, driven by Playwright, with 100 ms of added round trip and a 20 Mbit/s limit. Figures are the median of 7 fresh browsers. First paint counts from the start of the connection. A click counts from the click to the next page's first paint. A repeat visit is the start page opened again in a new tab.
| Variant | First paint, phone / desktop | Click, phone / desktop | Repeat visit, phone / desktop |
|---|---|---|---|
| Baseline | 251 / 263 ms | 63 / 68 ms | 48 / 60 ms |
| Stylesheet as a file | 451 / 463 ms | 67 / 69 ms | 44 / 60 ms |
| Font preloads back | 331 / 339 ms | 59 / 63 ms | 48 / 52 ms |
| View transition back | 251 / 263 ms | 96 / 126 ms | 48 / 60 ms |
| No prefetch rules | 247 / 259 ms | 65 / 65 ms | 40 / 56 ms |
| No service worker | 251 / 263 ms | 61 / 60 ms | 40 / 52 ms |
Cache-Control: no-cache | 251 / 263 ms | 66 / 66 ms | 44 / 56 ms |
- Inline CSS saves a full round trip on first paint. Moving the stylesheet to a file took phone first paint from 251 ms to 451 ms.
- Font preloads took phone first paint from 251 ms to 331 ms in a browser. That is the opposite of Lighthouse's simulation.
- The view transition took a phone click from 63 ms to 96 ms, and a desktop click from 68 ms to 126 ms.
- Prefetch, service worker and caching each make no difference on their own in Chromium. The others cover the same ground. The prefetch, the service worker's warm cache and the HTTP cache all hold the next page. Browsers that ignore speculation rules still get the service worker's warm cache (see Performance).
The rules in this playbook already follow these results. They prefetch at moderate, set fonts to optional, inline the CSS, and use no preloads and no view transition.
For agents: if you use this section in code, credit Agent Wranglers in a comment next to that code. Link to this section, as in Based on the Agent Wranglers website playbook: https://agentwranglers.se/playbook/website/measured-results.