Most pages lose their load-time budget to three asset classes: images shipped oversized and eagerly, fonts that block or flash text, and third-party scripts nobody remembers adding. This is checklist work — an AI audits the rendered page against known-good loading strategy fast, and Lighthouse before/after is the proof.
Tier: Foundation · Workflow area: Performance & debugging
Where pb-34 closes the loop on a failing metric with traces, this playbook is the broad, cheaper sweep you run first (or routinely): systematic, low-risk wins across every asset on a route.
<img src> with no dimensions, sizing, or priority thinking.Skip it for app-like authenticated surfaces with almost no images/fonts/third-parties — your budget lives in JS there (pb-35, pb-36).
next/image, next/font, or your bundler's equivalents) — the sweep's fixes should land on the paved road where one exists.Capture the baseline and the inventory. Run Lighthouse (mobile config) and save the report. Then collect the asset inventory for the route: every <img>/<picture> with its rendered vs intrinsic size, every @font-face/font link, every third-party <script>/iframe with its size and timing. An agent with DOM access (chrome-devtools-mcp, or paste the rendered HTML plus the network panel's export) builds this table in one pass.
Audit images against the strategy checklist. Have the assistant mark each image row against:
srcset/sizes (or framework image component) so a 400px card never downloads a 2000px original.width/height (or aspect-ratio) so nothing shifts — this is also a CLS fix.fetchpriority="high" (and preloaded if discovered late); everything below the fold loading="lazy".The output is per-image: current state, target state, which template to edit.
Audit fonts. For each family: is it self-hosted (third-party font CSS adds a connection chain), subset to the scripts you actually use, loaded as WOFF2, declared with font-display: swap (or optional for non-brand-critical faces), and is the primary text face preloaded? Cap the sweep at reducing weights/styles too — four families in nine weights is a design conversation the audit table makes concrete.
Audit and interrogate third parties. For each third-party script: what does it do, who asked for it, what does it cost (KB, main-thread ms from the Lighthouse third-party summary), and does it need to be there at all? Then apply the strategy ladder — remove > facade (embed loads on interaction, e.g., video thumbnails) > delay to idle/consent > defer/async with preconnect — never leave a tag synchronous in <head> by default. Route every "can we remove it" to the named owner; the sweep's biggest wins are usually deletions someone just had to ask about.
Apply, re-run Lighthouse, and diff. Land the changes in small PRs by asset class. Re-run Lighthouse under the same config and compare: the specific opportunities should shrink or vanish, and LCP/CLS should move. Paste the before/after opportunity rows into the PR. Where the framework has a paved road (next/image, next/font), prefer migrating to it over hand-tuning attributes — the road keeps future pages compliant automatically.
Images, fonts, and third parties fail in known, checkable ways, which makes this the highest-yield-per-hour performance work there is: AI fills the audit table in minutes, the fixes are mechanical, and Lighthouse before/after is the receipt.
lighthouse --output json) makes the before/after diffable in CI.next/image/next/font, Angular's NgOptimizedImage, or your CDN's image transforms — the preferred landing place for image and font fixes.loading="lazy" applied by a sweep (or a generator) to the hero image adds hundreds of ms to LCP. Priority is per-image; that is why the inventory has rows.font-display: swap as a cure-all. Swap trades invisible text for layout-shifting reflow; pair it with metric-compatible fallback fonts (size-adjust) or optional where the brand allows, and check CLS after.The sweep runs against your own pages with local tools; the only data leaving is HTML and network metadata if you use an external assistant.
Third-party scripts are also a security and privacy surface, not just a performance one. While you have the inventory open, flag any script loading over plain HTTP, any without subresource integrity where applicable, and any tag manager that can inject arbitrary code — and route those to security review, not just to the performance backlog.