$npx -y skills add ziniman/ai-instruct --skill web-performanceUse this skill whenever the user is improving Core Web Vitals or page load performance, or mentions slow pages, PageSpeed Insights / Lighthouse failures, LCP/CLS/INP scores, bundle size, image/font optimization, or third-party script impact. Covers Core Web Vitals, image and font
| 1 | # Web Performance Guide |
| 2 | |
| 3 | > Applies to: Any website or web app | Updated: March 2026 |
| 4 | |
| 5 | A practical reference for measuring and improving web performance - covering Core Web Vitals, image and font optimization, JavaScript bundle size, CSS build size, CDN caching, third-party JavaScript impact, and validation tools. |
| 6 | |
| 7 | --- |
| 8 | |
| 9 | ## Section 0: Before You Start |
| 10 | |
| 11 | Answer these questions before making any performance changes. Each has a default - use it if the user hasn't said otherwise. |
| 12 | |
| 13 | **Q: Which pages are the priority targets?** |
| 14 | (landing page, dashboard, auth-gated app pages, all pages) |
| 15 | Default: public-facing pages first - these are indexed by search engines and directly affect user experience. Auth-gated pages matter less for Core Web Vitals field data because CrUX only collects data from logged-in users on those routes. |
| 16 | |
| 17 | **Q: What is the current performance baseline?** |
| 18 | Default: unknown - run PageSpeed Insights on the target URL before making any changes, so you have a before/after comparison. Note the LCP element type (image or text), TTFB, and the specific audits flagged as failing. |
| 19 | |
| 20 | **Q: Are you optimizing for lab scores (Lighthouse) or field data (real users)?** |
| 21 | Default: both - but prioritize fixing field data issues flagged in Google Search Console > Core Web Vitals first. Lab scores are easier to game; field data reflects real users on real devices and networks. |
| 22 | |
| 23 | **Q: What framework or rendering model is the site using?** |
| 24 | (plain HTML, SPA/Vite, Next.js App Router, Astro, Nuxt, WordPress) |
| 25 | Default: detect from config files (`next.config.*`, `vite.config.*`, `astro.config.*`) if visible; otherwise assume plain HTML. Framework-specific advice is in clearly labeled subsections throughout this guide. |
| 26 | |
| 27 | **Q: What image formats are currently in use?** |
| 28 | Default: JPEG/PNG - check the `public/` or `assets/` directory and any image references in source before assuming. |
| 29 | |
| 30 | **Q: How are web fonts loaded?** |
| 31 | (Google Fonts via `<link>`, `@import` in CSS, self-hosted, framework font utility) |
| 32 | Default: check the HTML `<head>` and any global CSS files before assuming. |
| 33 | |
| 34 | **Q: Is a CDN or hosting platform configured with custom cache headers?** |
| 35 | Default: no - most platforms (AWS Amplify, plain S3, some shared hosts) do not set long-lived cache on static assets by default. Check the hosting config before assuming. |
| 36 | |
| 37 | **Q: Is a `browserslist` target configured?** |
| 38 | Default: no - without it, many transpilers and bundlers use a conservative target and ship legacy polyfills for features that modern browsers have supported for years. |
| 39 | |
| 40 | > **AI assistant:** Read the user's answers (or use the defaults above) before generating any code. Run PageSpeed Insights first if no baseline exists. Identify the LCP element type before optimizing images - if the LCP element is a `<p>` or `<h1>`, TTFB and render-blocking CSS reduction matter more than image optimization. Skip framework-specific subsections that don't match the user's stack. |
| 41 | |
| 42 | --- |
| 43 | |
| 44 | ## Contents |
| 45 | |
| 46 | 1. [Core Web Vitals Overview](#core-web-vitals-overview) |
| 47 | 2. [LCP: Largest Contentful Paint](#lcp-largest-contentful-paint) |
| 48 | 3. [CLS: Cumulative Layout Shift](#cls-cumulative-layout-shift) |
| 49 | 4. [INP: Interaction to Next Paint](#inp-interaction-to-next-paint) |
| 50 | 5. [Image Optimization](#image-optimization) |
| 51 | 6. [Font Loading](#font-loading) |
| 52 | 7. [JavaScript Bundle Size](#javascript-bundle-size) |
| 53 | 8. [Legacy JavaScript and Browser Targets](#legacy-javascript-and-browser-targets) |
| 54 | 9. [Third-Party JavaScript](#third-party-javascript) |
| 55 | 10. [CSS Build Size](#css-build-size) |
| 56 | 11. [CDN and Caching](#cdn-and-caching) |
| 57 | 12. [Measurement and Validation](#measurement-and-validation) |
| 58 | |
| 59 | --- |
| 60 | |
| 61 | ## Core Web Vitals Overview |
| 62 | |
| 63 | Applies when: any public-facing page. |
| 64 | |
| 65 | Core Web Vitals are Google's user-experience metrics, measured in the field via the Chrome User Experience Report (CrUX). They are ranking signals. The three metrics as of 2026: |
| 66 | |
| 67 | | Metric | Measures | Good | Needs improvement | Poor | |
| 68 | |---|---|---|---|---| |
| 69 | | **LCP** | Loading speed of the largest visible element | < 2.5 s | 2.5 - 4 s | > 4 s | |
| 70 | | **CLS** | Visual instability from layout shifts | < 0.1 | 0.1 - 0.25 | > 0.25 | |
| 71 | | **INP** | Responsiveness of all interactions | < 200 ms | 200 - 500 ms | > 500 ms | |
| 72 | |
| 73 | INP replaced FID (First Input Delay) in March 2024. FID only measured the first interaction; INP measures every interaction throughout the visit. A page that passes INP must remain responsive throughout the entire session, not just at initial load. |
| 74 | |
| 75 | Field data appear |