|
| 1 | +--- |
| 2 | +name: webperf-core-web-vitals |
| 3 | +description: Intelligent Core Web Vitals analysis with automated workflows and decision trees. Measures LCP, CLS, INP with guided debugging that automatically determines follow-up analysis based on results. Includes workflows for LCP deep dive (5 phases), CLS investigation (loading vs interaction), INP debugging (latency breakdown + attribution), and cross-skill integration with loading, interaction, and media skills. Use when the user asks about Core Web Vitals, LCP optimization, layout shifts, or interaction responsiveness. |
| 4 | +--- |
| 5 | + |
| 6 | +# WebPerf: Core Web Vitals |
| 7 | + |
| 8 | +JavaScript snippets for measuring web performance in Chrome DevTools. Execute with `evaluate_script`, capture output with `get_console_message`. |
| 9 | + |
| 10 | +## Scripts |
| 11 | + |
| 12 | +- `scripts/CLS.js` — Cumulative Layout Shift (CLS) |
| 13 | +- `scripts/INP.js` — Interaction to Next Paint (INP) |
| 14 | +- `scripts/LCP-Image-Entropy.js` — LCP Image Entropy |
| 15 | +- `scripts/LCP-Sub-Parts.js` — LCP Sub-Parts |
| 16 | +- `scripts/LCP-Trail.js` — LCP Trail |
| 17 | +- `scripts/LCP-Video-Candidate.js` — LCP Video Candidate |
| 18 | +- `scripts/LCP.js` — Largest Contentful Paint (LCP) |
| 19 | + |
| 20 | +Descriptions, thresholds, and return schemas: `references/snippets.md`, `references/schema.md` |
| 21 | + |
| 22 | +## Script Execution Patterns |
| 23 | + |
| 24 | +Scripts fall into two execution patterns: |
| 25 | + |
| 26 | +### Synchronous (LCP, CLS, LCP-Sub-Parts, LCP-Trail, LCP-Image-Entropy, LCP-Video-Candidate) |
| 27 | + |
| 28 | +Run via `evaluate_script` and return structured JSON immediately from buffered performance data. The page must have already loaded. |
| 29 | + |
| 30 | +### Tracking (INP) |
| 31 | + |
| 32 | +INP requires real user interactions to measure. The workflow is: |
| 33 | + |
| 34 | +1. Run `INP.js` via `evaluate_script` → returns `{ status: "tracking", getDataFn: "getINP" }` |
| 35 | +2. **Tell the user:** "INP tracking is now active. Please interact with the page — click buttons, open menus, fill form fields — then let me know when you're done." |
| 36 | +3. Wait for the user to confirm they've interacted. |
| 37 | +4. Call `evaluate_script("getINP()")` to collect results. |
| 38 | + |
| 39 | +> The agent cannot interact with the page on behalf of the user for INP measurement. Real user interactions are required. |
| 40 | +
|
| 41 | +## Common Workflows |
| 42 | + |
| 43 | +### Complete Core Web Vitals Audit |
| 44 | + |
| 45 | +When the user asks for a comprehensive Core Web Vitals analysis or "audit CWV": |
| 46 | + |
| 47 | +1. **LCP.js** - Measure Largest Contentful Paint |
| 48 | +2. **CLS.js** - Measure Cumulative Layout Shift |
| 49 | +3. **INP.js** - Measure Interaction to Next Paint |
| 50 | +4. **LCP-Sub-Parts.js** - Break down LCP timing phases |
| 51 | +5. **LCP-Trail.js** - Track LCP candidate evolution |
| 52 | + |
| 53 | +### LCP Deep Dive |
| 54 | + |
| 55 | +When LCP is slow or the user asks "debug LCP" or "why is LCP slow": |
| 56 | + |
| 57 | +1. **LCP.js** - Establish baseline LCP value |
| 58 | +2. **LCP-Sub-Parts.js** - Break down into TTFB, resource load, render delay |
| 59 | +3. **LCP-Trail.js** - Identify all LCP candidates and changes |
| 60 | +4. **LCP-Image-Entropy.js** - Check if LCP image has visual complexity issues |
| 61 | +5. **LCP-Video-Candidate.js** - Detect if LCP is a video (poster or video element) |
| 62 | + |
| 63 | +### CLS Investigation |
| 64 | + |
| 65 | +When layout shifts are detected or the user asks "debug CLS" or "layout shift issues": |
| 66 | + |
| 67 | +1. **CLS.js** - Measure overall CLS score |
| 68 | +2. **Layout-Shift-Loading-and-Interaction.js** (from Interaction skill) - Separate loading vs interaction shifts |
| 69 | +3. Cross-reference with **webperf-loading** skill: |
| 70 | + - Find-Above-The-Fold-Lazy-Loaded-Images.js (lazy images causing shifts) |
| 71 | + - Fonts-Preloaded-Loaded-and-used-above-the-fold.js (font swap causing shifts) |
| 72 | + |
| 73 | +### INP Debugging |
| 74 | + |
| 75 | +When interactions feel slow or the user asks "debug INP" or "slow interactions": |
| 76 | + |
| 77 | +1. **INP.js** - Start tracking. Tell the user to interact with the page and confirm when done. |
| 78 | +2. Call `getINP()` to collect results once the user confirms. |
| 79 | +3. **Interactions.js** (from Interaction skill) - List all interactions with timing |
| 80 | +4. **Input-Latency-Breakdown.js** (from Interaction skill) - Break down input delay, processing, presentation |
| 81 | +5. **Long-Animation-Frames.js** (from Interaction skill) - Identify blocking animation frames |
| 82 | +6. **Long-Animation-Frames-Script-Attribution.js** (from Interaction skill) - Find scripts causing delays |
| 83 | + |
| 84 | +### Video as LCP Investigation |
| 85 | + |
| 86 | +When LCP is a video element (detected by LCP-Video-Candidate.js): |
| 87 | + |
| 88 | +1. **LCP-Video-Candidate.js** - Identify video as LCP candidate |
| 89 | +2. **Video-Element-Audit.js** (from Media skill) - Audit video loading strategy |
| 90 | +3. **LCP-Sub-Parts.js** - Analyze video loading phases |
| 91 | +4. Cross-reference with **webperf-loading** skill: |
| 92 | + - Resource-Hints-Validation.js (check for video preload) |
| 93 | + - Priority-Hints-Audit.js (check for fetchpriority on video) |
| 94 | + |
| 95 | +### Image as LCP Investigation |
| 96 | + |
| 97 | +When LCP is an image (most common case): |
| 98 | + |
| 99 | +1. **LCP.js** - Measure LCP timing |
| 100 | +2. **LCP-Sub-Parts.js** - Break down timing phases |
| 101 | +3. **LCP-Image-Entropy.js** - Analyze image complexity |
| 102 | +4. Cross-reference with **webperf-media** skill: |
| 103 | + - Image-Element-Audit.js (check format, dimensions, lazy loading) |
| 104 | +5. Cross-reference with **webperf-loading** skill: |
| 105 | + - Find-Above-The-Fold-Lazy-Loaded-Images.js (check if incorrectly lazy) |
| 106 | + - Priority-Hints-Audit.js (check for fetchpriority="high") |
| 107 | + - Resource-Hints-Validation.js (check for preload) |
| 108 | + |
| 109 | +## Decision Tree |
| 110 | + |
| 111 | +Use this decision tree to automatically run follow-up snippets based on results: |
| 112 | + |
| 113 | +### After LCP.js |
| 114 | + |
| 115 | +- **If LCP > 2.5s** → Run **LCP-Sub-Parts.js** to diagnose which phase is slow |
| 116 | +- **If LCP > 4.0s (poor)** → Run full LCP deep dive workflow (5 snippets) |
| 117 | +- **If LCP candidate is an image** → Run **LCP-Image-Entropy.js** and **webperf-media:Image-Element-Audit.js** |
| 118 | +- **If LCP candidate is a video** → Run **LCP-Video-Candidate.js** and **webperf-media:Video-Element-Audit.js** |
| 119 | +- **Always run** → **LCP-Trail.js** to understand candidate evolution |
| 120 | + |
| 121 | +### After LCP-Sub-Parts.js |
| 122 | + |
| 123 | +- **If TTFB phase > 600ms** → Switch to **webperf-loading** skill and run TTFB-Sub-Parts.js |
| 124 | +- **If Resource Load Time > 1500ms** → Run: |
| 125 | + 1. **webperf-loading:Resource-Hints-Validation.js** (check for preload/preconnect) |
| 126 | + 2. **webperf-loading:Priority-Hints-Audit.js** (check fetchpriority) |
| 127 | + 3. **webperf-loading:Find-render-blocking-resources.js** (competing resources) |
| 128 | +- **If Render Delay > 200ms** → Run: |
| 129 | + 1. **webperf-loading:Find-render-blocking-resources.js** (blocking CSS/JS) |
| 130 | + 2. **webperf-loading:Script-Loading.js** (parser-blocking scripts) |
| 131 | + 3. **webperf-interaction:Long-Animation-Frames.js** (main thread blocking) |
| 132 | + |
| 133 | +### After LCP-Trail.js |
| 134 | + |
| 135 | +- **If many LCP candidate changes (>3)** → This causes visual instability, investigate: |
| 136 | + 1. **webperf-loading:Find-Above-The-Fold-Lazy-Loaded-Images.js** (late-loading images) |
| 137 | + 2. **webperf-loading:Fonts-Preloaded-Loaded-and-used-above-the-fold.js** (font swaps) |
| 138 | + 3. **CLS.js** (layout shifts contributing to LCP changes) |
| 139 | +- **If final LCP candidate appears late** → Run **webperf-loading:Resource-Hints-Validation.js** |
| 140 | +- **If early candidate was replaced** → Understand why initial content was pushed down (likely CLS issue) |
| 141 | + |
| 142 | +### After LCP-Image-Entropy.js |
| 143 | + |
| 144 | +- **If entropy is very high** → Image is visually complex, recommend: |
| 145 | + - Modern formats (WebP, AVIF) |
| 146 | + - Appropriate compression |
| 147 | + - Potentially a placeholder strategy |
| 148 | +- **If entropy is low** → Image may be over-optimized or placeholder-like |
| 149 | +- **If large file size detected** → Run **webperf-media:Image-Element-Audit.js** for format/sizing analysis |
| 150 | + |
| 151 | +### After LCP-Video-Candidate.js |
| 152 | + |
| 153 | +- **If video is LCP** → Run: |
| 154 | + 1. **webperf-media:Video-Element-Audit.js** (check poster, preload, formats) |
| 155 | + 2. **webperf-loading:Priority-Hints-Audit.js** (check fetchpriority on poster) |
| 156 | + 3. **LCP-Sub-Parts.js** (analyze video loading phases) |
| 157 | +- **If poster image is LCP** → Treat as image LCP (run image workflows) |
| 158 | + |
| 159 | +### After CLS.js |
| 160 | + |
| 161 | +- **If CLS > 0.1** → Run **webperf-interaction:Layout-Shift-Loading-and-Interaction.js** to separate causes |
| 162 | +- **If CLS > 0.25 (poor)** → Run comprehensive shift investigation: |
| 163 | + 1. **webperf-loading:Find-Above-The-Fold-Lazy-Loaded-Images.js** (images without dimensions) |
| 164 | + 2. **webperf-loading:Fonts-Preloaded-Loaded-and-used-above-the-fold.js** (font loading strategy) |
| 165 | + 3. **webperf-loading:Critical-CSS-Detection.js** (late-loading styles) |
| 166 | + 4. **webperf-media:Image-Element-Audit.js** (missing width/height) |
| 167 | +- **If CLS = 0** → Confirm with multiple page loads (might be timing-dependent) |
| 168 | + |
| 169 | +### After INP.js |
| 170 | + |
| 171 | +- **If INP > 200ms** → Run **webperf-interaction:Interactions.js** to identify slow interactions |
| 172 | +- **If INP > 500ms (poor)** → Run full INP debugging workflow: |
| 173 | + 1. **webperf-interaction:Interactions.js** (list all interactions) |
| 174 | + 2. **webperf-interaction:Input-Latency-Breakdown.js** (phase breakdown) |
| 175 | + 3. **webperf-interaction:Long-Animation-Frames.js** (blocking frames) |
| 176 | + 4. **webperf-interaction:Long-Animation-Frames-Script-Attribution.js** (culprit scripts) |
| 177 | +- **If specific interaction type is slow (e.g., keyboard)** → Focus analysis on that interaction type |
| 178 | + |
| 179 | +### Cross-Skill Triggers |
| 180 | + |
| 181 | +These triggers recommend using snippets from other skills: |
| 182 | + |
| 183 | +#### From LCP to Loading Skill |
| 184 | + |
| 185 | +- **If LCP > 2.5s and TTFB phase is dominant** → Use **webperf-loading** skill: |
| 186 | + - TTFB.js, TTFB-Sub-Parts.js, Service-Worker-Analysis.js |
| 187 | + |
| 188 | +- **If LCP image is lazy-loaded** → Use **webperf-loading** skill: |
| 189 | + - Find-Above-The-Fold-Lazy-Loaded-Images.js |
| 190 | + |
| 191 | +- **If LCP has no fetchpriority** → Use **webperf-loading** skill: |
| 192 | + - Priority-Hints-Audit.js |
| 193 | + |
| 194 | +#### From CLS to Loading Skill |
| 195 | + |
| 196 | +- **If CLS caused by fonts** → Use **webperf-loading** skill: |
| 197 | + - Fonts-Preloaded-Loaded-and-used-above-the-fold.js |
| 198 | + - Resource-Hints-Validation.js (for font preload) |
| 199 | + |
| 200 | +- **If CLS caused by images** → Use **webperf-media** skill: |
| 201 | + - Image-Element-Audit.js (check for width/height attributes) |
| 202 | + |
| 203 | +#### From INP to Interaction Skill |
| 204 | + |
| 205 | +- **If INP > 200ms** → Use **webperf-interaction** skill for full debugging: |
| 206 | + - Interactions.js, Input-Latency-Breakdown.js |
| 207 | + - Long-Animation-Frames.js, Long-Animation-Frames-Script-Attribution.js |
| 208 | + - LongTask.js (if pre-interaction blocking suspected) |
| 209 | + |
| 210 | +#### From LCP/INP to Interaction Skill |
| 211 | + |
| 212 | +- **If render delay or interaction delay is high** → Use **webperf-interaction** skill: |
| 213 | + - Long-Animation-Frames.js (main thread blocking) |
0 commit comments