web-perf
Attaches itself automatically when a prompt matches.
Core Web Vitals thresholds (LCP, INP, CLS, TTFB, FCP, TBT) and the bundle / network / render-path patterns that move them. Use when reviewing or optimizing page load speed, Lighthouse scores, slow pages, jank, or site performance. Pairs with react-perf-kit when the target is React/Next.
Scaffolds
Source
Adapted from cloudflare/skills (adapted — Chrome DevTools MCP workflow stripped)
Instructions
The full instruction set the agent receives when this skill is active.
Web Performance
Knowledge of the metrics, the thresholds, and the levers that move them. Use this when the user asks for perf review, mentions Lighthouse, or describes slow page load / janky interaction.
Core Web Vitals — Thresholds
| Metric | Good | Needs work | Poor | What it measures |
|---|---|---|---|---|
| TTFB (server) | < 800ms | < 1.8s | > 1.8s | Time to first byte |
| FCP (paint) | < 1.8s | < 3s | > 3s | First contentful paint |
| LCP (paint) | < 2.5s | < 4s | > 4s | Largest contentful paint — the hero element |
| INP (interaction) | < 200ms | < 500ms | > 500ms | Interaction-to-next-paint |
| TBT (interaction) | < 200ms | < 600ms | > 600ms | Total blocking time |
| CLS (stability) | < 0.1 | < 0.25 | > 0.25 | Cumulative layout shift |
| Speed Index | < 3.4s | < 5.8s | > 5.8s | Visual completeness |
Where the wins are (in order)
1. LCP — almost always a network problem
- Hero image not preloaded → add
<link rel="preload" as="image">or<Image priority>in Next.js - Hero image too big → use WebP/AVIF, correct
sizesattribute, responsivesrcset - Render-blocking CSS → inline critical CSS, defer the rest (
media="print" onload="this.media='all'"trick or Next.js does it automatically) - Render-blocking JS →
async/deferon<script>, or move non-critical tonext/dynamic - Web font swap →
font-display: swap+ preload the font file;next/fontdoes this for you
2. INP — JavaScript blocking the main thread
- Hydration cost → server-render more, hydrate less. In Next, prefer Server Components for static content
- Long tasks in event handlers → break with
requestIdleCallbackor split work intosetTimeout(0)chunks - Heavy third-party scripts → load after hydration with
next/script strategy="lazyOnload"ordefer - Bundle bloat → see [[react-perf-kit]] bundle-* rules — barrel imports, dynamic imports, conditional loads
3. CLS — visual stability
- Images without dimensions → always set
width/height(orfillwith reserved aspect ratio) - Injected content → reserve space for ads, banners, embeds
- Font swap shift →
font-display: optionalif shift is intolerable, else accept the FOUT - Late-loaded fonts → preload, or use
size-adjustdescriptor to match fallback metrics
Network analysis checklist
Walk the network tab (or codebase) looking for:
- Render-blocking resources: JS/CSS in
<head>withoutasync/defer/mediaattributes - Network chains: resources discovered late because they depend on others (CSS imports, JS-loaded fonts)
- Missing preloads: critical resources (fonts, hero images, key scripts) not preloaded
- Caching gaps: missing or weak
Cache-Control,ETag, orLast-Modifiedheaders - Large payloads: uncompressed or oversized JS/CSS bundles
- Unused preconnects: preconnect directives where zero requests went to that origin
Framework / bundler detection (when reviewing an existing codebase)
| Tool | Config files |
|---|---|
| Next.js | next.config.js, next.config.mjs, next.config.ts |
| Vite | vite.config.js, vite.config.ts |
| SvelteKit | svelte.config.js |
| Astro | astro.config.mjs |
| Webpack | webpack.config.js, webpack.*.js |
| Rollup | rollup.config.js, rollup.config.mjs |
Then check package.json scripts + dependencies. For Next-specific perf rules, defer to [[react-perf-kit]].
What to say when reporting
- Quantify impact: "compress hero.png (450KB) → WebP (~80KB)" beats "optimize images"
- Be specific: name the file and the metric it moves
- Skip non-issues: if LCP is 1.4s, say so — don't invent problems
- One change, one metric: don't bundle unrelated suggestions
Verification
The authoritative tool is Chrome DevTools (or its MCP version, when available). When you don't have it, fall back to:
- Read the source tree for the patterns above
- Inspect
<Head>/ metadata routes for preload/preconnect tags - Check
package.jsonfor known-heavy libs (moment, lodash whole-package, large icon sets)
Don't claim a fix improved a metric without measuring — see [[evidence-before-claim]].
See also: [[react-perf-kit]], [[motion-perf]], [[seo-meta-kit]].