webperf-core-web-vitals
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 interac
Install
npx skills add https://github.com/nucliweb/webperf-snippets/tree/main/.claude/skills/webperf-core-web-vitals
claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install nucliweb-webperf-snippets@llmmart
git clone https://github.com/nucliweb/webperf-snippets.git
The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole nucliweb/webperf-snippets collection as a plugin from our marketplace. Git is the plain clone.
Skill manifest
WebPerf: Core Web Vitals
JavaScript snippets for measuring web performance in Chrome DevTools.
Running a script
- Run the script with
mcp__chrome-devtools__evaluate_scriptand read the object it returns. The scripts have no console output, so the returned object is the result:script,statusand the metric data (value,rating,details,items,issues), as described inreferences/schema.md. - When
statusis"tracking", the script keeps observing the page. After the interactions, call the function named ingetDataFnwith anothermcp__chrome-devtools__evaluate_scriptcall, for examplegetINP(), and read the object it returns. - When
statusis"error"or"unsupported", readerror: the page may not have loaded yet, or the browser lacks the API.
Without Chrome DevTools MCP, run the same snippet with the webperf-snippets CLI, which loads the page in headless Chromium and prints the same result objects: npx webperf-snippets <url> --snippet <Name> --json, where <Name> is the script name without .js. It needs Playwright and Chromium (npm install --save-dev webperf-snippets playwright, then npx playwright install chromium), and tracking snippets take --interact-script <file> to drive the interactions.
Scripts
scripts/CLS.js— Cumulative layout shift (CLS)scripts/INP.js— Interaction to next paint (INP)scripts/LCP-Image-Entropy.js— LCP image entropyscripts/LCP-Subparts.js— LCP subpartsscripts/LCP-Trail.js— LCP trailscripts/LCP-Video-Candidate.js— LCP video candidatescripts/LCP.js— Largest contentful paint (LCP)
Common Workflows
Complete Core Web Vitals Audit
When the user asks for a comprehensive Core Web Vitals analysis or "audit CWV":
- LCP.js - Measure Largest Contentful Paint
- CLS.js - Measure Cumulative Layout Shift
- INP.js - Measure Interaction to Next Paint
- LCP-Subparts.js - Break down LCP timing phases
- LCP-Trail.js - Track LCP candidate evolution
LCP Deep Dive
When LCP is slow or the user asks "debug LCP" or "why is LCP slow":
- LCP.js - Establish baseline LCP value
- LCP-Subparts.js - Break down into TTFB, resource load, render delay
- LCP-Trail.js - Identify all LCP candidates and changes
- LCP-Image-Entropy.js - Check if LCP image has visual complexity issues
- LCP-Video-Candidate.js - Detect if LCP is a video (poster or video element)
CLS Investigation
When layout shifts are detected or the user asks "debug CLS" or "layout shift issues":
- CLS.js - Measure overall CLS score
- Layout-Shift-Loading-and-Interaction.js (pending — available in webperf-interaction skill)
- Cross-reference with webperf-loading skill:
- Find-Above-The-Fold-Lazy-Loaded-Images.js (lazy images causing shifts)
- Fonts-Preloaded-Loaded-and-used-above-the-fold.js (font swap causing shifts)
INP Debugging
When interactions feel slow or the user asks "debug INP" or "slow interactions":
- INP.js - Measure overall INP value; call
getINP()after interactions,getINPDetails()for the 15 slowest interactions - Interactions.js (pending — available in webperf-interaction skill)
- Input-Latency-Breakdown.js (pending — available in webperf-interaction skill)
- Long-Animation-Frames.js (pending — available in webperf-interaction skill)
- Long-Animation-Frames-Script-Attribution.js (pending — available in webperf-interaction skill)
Video as LCP Investigation
When LCP is a video element (detected by LCP-Video-Candidate.js):
- LCP-Video-Candidate.js - Identify video as LCP candidate
- Video-Element-Audit.js (from Media skill) - Audit video loading strategy
- LCP-Subparts.js - Analyze video loading phases
- Cross-reference with webperf-loading skill:
- Resource-Hints-Validation.js (check for video preload)
- Priority-Hints-Audit.js (check for fetchpriority on video)
Image as LCP Investigation
When LCP is an image (most common case):
- LCP.js - Measure LCP timing
- LCP-Subparts.js - Break down timing phases
- LCP-Image-Entropy.js - Analyze image complexity
- Cross-reference with webperf-media skill:
- Image-Element-Audit.js (check format, dimensions, lazy loading)
- Cross-reference with webperf-loading skill:
- Find-Above-The-Fold-Lazy-Loaded-Images.js (check if incorrectly lazy)
- Priority-Hints-Audit.js (check for fetchpriority="high")
- Resource-Hints-Validation.js (check for preload)
Decision Tree
Use this decision tree to automatically run follow-up snippets based on results:
After LCP.js
- If LCP > 2.5s → Run LCP-Subparts.js to diagnose which phase is slow
- If LCP > 4.0s (poor) → Run full LCP deep dive workflow (5 snippets)
- If LCP candidate is an image → Run LCP-Image-Entropy.js and webperf-media:Image-Element-Audit.js
- If LCP candidate is a video → Run LCP-Video-Candidate.js and webperf-media:Video-Element-Audit.js
- Always run → LCP-Trail.js to understand candidate evolution
After LCP-Subparts.js
- If TTFB phase > 600ms → Switch to webperf-loading skill and run TTFB-Sub-Parts.js
- If Resource Load Time > 1500ms → Run:
- webperf-loading:Resource-Hints-Validation.js (check for preload/preconnect)
- webperf-loading:Priority-Hints-Audit.js (check fetchpriority)
- webperf-loading:Find-render-blocking-resources.js (competing resources)
- If Render Delay > 200ms → Run:
- webperf-loading:Find-render-blocking-resources.js (blocking CSS/JS)
- webperf-loading:Script-Loading.js (parser-blocking scripts)
- webperf-interaction:Long-Animation-Frames.js (main thread blocking)
After LCP-Trail.js
- If many LCP candidate changes (>3) → This causes visual instability, investigate:
- webperf-loading:Find-Above-The-Fold-Lazy-Loaded-Images.js (late-loading images)
- webperf-loading:Fonts-Preloaded-Loaded-and-used-above-the-fold.js (font swaps)
- CLS.js (layout shifts contributing to LCP changes)
- If final LCP candidate appears late → Run webperf-loading:Resource-Hints-Validation.js
- If early candidate was replaced → Understand why initial content was pushed down (likely CLS issue)
After LCP-Image-Entropy.js
- If entropy is very high → Image is visually complex, recommend:
- Modern formats (WebP, AVIF)
- Appropriate compression
- Potentially a placeholder strategy
- If entropy is low → Image may be over-optimized or placeholder-like
- If large file size detected → Run webperf-media:Image-Element-Audit.js for format/sizing analysis
After LCP-Video-Candidate.js
- If video is LCP → Run:
- webperf-media:Video-Element-Audit.js (check poster, preload, formats)
- webperf-loading:Priority-Hints-Audit.js (check fetchpriority on poster)
- LCP-Subparts.js (analyze video loading phases)
- If poster image is LCP → Treat as image LCP (run image workflows)
After CLS.js
- If CLS > 0.1 → Run webperf-interaction:Layout-Shift-Loading-and-Interaction.js (pending — available in webperf-interaction skill)
- If CLS > 0.25 (poor) → Run comprehensive shift investigation:
- webperf-loading:Find-Above-The-Fold-Lazy-Loaded-Images.js (images without dimensions)
- webperf-loading:Fonts-Preloaded-Loaded-and-used-above-the-fold.js (font loading strategy)
- webperf-loading:Critical-CSS-Detection.js (late-loading styles)
- webperf-media:Image-Element-Audit.js (missing width/height)
- If CLS = 0 → Confirm with multiple page loads (might be timing-dependent)
After INP.js
- If INP > 200ms → Run webperf-interaction:Interactions.js to identify slow interactions
- If INP > 500ms (poor) → Run full INP debugging workflow:
- webperf-interaction:Interactions.js (list all interactions)
- webperf-interaction:Input-Latency-Breakdown.js (phase breakdown)
- webperf-interaction:Long-Animation-Frames.js (blocking frames)
- webperf-interaction:Long-Animation-Frames-Script-Attribution.js (culprit scripts)
- If specific interaction type is slow (e.g., keyboard) → Focus analysis on that interaction type
- After INP data is collected → call
getINPDetails()for the 15 slowest interactions, slowest first (useful for identifying patterns across multiple slow interactions)
Error Recovery
- If any script returns
status: "error"→ Check if the page has finished loading:- If early in load: wait and re-run the script
- If page is an SPA: user may need to navigate to the target route first
- If LCP.js / LCP-Subparts.js returns
status: "error"→ Tell the user: "LCP data is not available yet. Please ensure the page has fully loaded, then run the analysis again." - If INP.js
getINP()returnsstatus: "error"→ ThegetDataFn: "getINP"field signals the agent can retry after user interaction. Prompt the user to click, type, or scroll, then callgetINP()again.
Cross-Skill Triggers
Context fork note: This skill runs with
context: fork. Cross-skill triggers below are recommendations to report back to the parent agent, not direct calls this subagent can execute. When a cross-skill trigger fires, tell the user which skill and script to run next. Scripts marked (pending) are not yet available — skip them and note the limitation.
These triggers recommend using snippets from other skills:
From LCP to Loading Skill
If LCP > 2.5s and TTFB phase is dominant → Use webperf-loading skill:
- TTFB.js, TTFB-Sub-Parts.js, Service-Worker-Analysis.js
If LCP image is lazy-loaded → Use webperf-loading skill:
- Find-Above-The-Fold-Lazy-Loaded-Images.js
If LCP has no fetchpriority → Use webperf-loading skill:
- Priority-Hints-Audit.js
From CLS to Loading Skill
If CLS caused by fonts → Use webperf-loading skill:
- Fonts-Preloaded-Loaded-and-used-above-the-fold.js
- Resource-Hints-Validation.js (for font preload)
If CLS caused by images → Use webperf-media skill:
- Image-Element-Audit.js (check for width/height attributes)
From INP to Interaction Skill
- If INP > 200ms → Use webperf-interaction skill for full debugging:
- Interactions.js, Input-Latency-Breakdown.js
- Long-Animation-Frames.js, Long-Animation-Frames-Script-Attribution.js
- LongTask.js (if pre-interaction blocking suspected)
From LCP/INP to Interaction Skill
- If render delay or interaction delay is high → Use webperf-interaction skill:
- Long-Animation-Frames.js (main thread blocking)
- LongTask.js (long tasks delaying rendering)
Multi-Metric Correlation
When multiple CWV metrics are poor, prioritize investigation:
If LCP > 2.5s AND CLS > 0.1 → Likely shared root cause:
- Check for late-loading content pushing LCP element
- Run LCP-Trail.js to see LCP candidate changes
- Run Layout-Shift-Loading-and-Interaction.js to correlate timing
If LCP > 2.5s AND INP > 200ms → Main thread congestion:
- Run Long-Animation-Frames.js
- Run webperf-loading:Script-Loading.js
- Run webperf-loading:JS-Execution-Time-Breakdown.js
If CLS > 0.1 AND INP > 200ms → Layout thrashing or interaction-triggered shifts:
- Run Layout-Shift-Loading-and-Interaction.js
- Run Interactions.js
- Check if shifts occur during/after interactions
References
references/snippets.md— Descriptions and thresholds for each scriptreferences/schema.md— Return value schema for interpreting script output
Files (webperf-snippets)
-
references
-
schema.md 48 KB
Loading… -
snippets.md 2.8 KB
Loading…
-
-
scripts
-
CLS.js 1.2 KB
Loading… -
INP.js 5.4 KB
Loading… -
LCP-Image-Entropy.js 4.2 KB
Loading… -
LCP-Subparts.js 4.6 KB
Loading… -
LCP-Trail.js 3.1 KB
Loading… -
LCP-Video-Candidate.js 4.1 KB
Loading… -
LCP.js 2.2 KB
Loading…
-
-
SKILL.md 12.3 KB
--- name: webperf-core-web-vitals 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. Compatible with Chrome DevTools MCP. context: fork license: MIT metadata: author: Joan Leon | @nucliweb version: 2.0.1 mcp-server: chrome-devtools category: web-performance repository: https://github.com/nucliweb/webperf-snippets --- # WebPerf: Core Web Vitals JavaScript snippets for measuring web performance in Chrome DevTools. ## Running a script 1. Run the script with `mcp__chrome-devtools__evaluate_script` and read the object it returns. The scripts have no console output, so the returned object is the result: `script`, `status` and the metric data (`value`, `rating`, `details`, `items`, `issues`), as described in `references/schema.md`. 2. When `status` is `"tracking"`, the script keeps observing the page. After the interactions, call the function named in `getDataFn` with another `mcp__chrome-devtools__evaluate_script` call, for example `getINP()`, and read the object it returns. 3. When `status` is `"error"` or `"unsupported"`, read `error`: the page may not have loaded yet, or the browser lacks the API. Without Chrome DevTools MCP, run the same snippet with the [webperf-snippets CLI](https://webperf-snippets.net/CLI), which loads the page in headless Chromium and prints the same result objects: `npx webperf-snippets <url> --snippet <Name> --json`, where `<Name>` is the script name without `.js`. It needs Playwright and Chromium (`npm install --save-dev webperf-snippets playwright`, then `npx playwright install chromium`), and tracking snippets take `--interact-script <file>` to drive the interactions. ## Scripts - `scripts/CLS.js` — Cumulative layout shift (CLS) - `scripts/INP.js` — Interaction to next paint (INP) - `scripts/LCP-Image-Entropy.js` — LCP image entropy - `scripts/LCP-Subparts.js` — LCP subparts - `scripts/LCP-Trail.js` — LCP trail - `scripts/LCP-Video-Candidate.js` — LCP video candidate - `scripts/LCP.js` — Largest contentful paint (LCP) ## Common Workflows ### Complete Core Web Vitals Audit When the user asks for a comprehensive Core Web Vitals analysis or "audit CWV": 1. **LCP.js** - Measure Largest Contentful Paint 2. **CLS.js** - Measure Cumulative Layout Shift 3. **INP.js** - Measure Interaction to Next Paint 4. **LCP-Subparts.js** - Break down LCP timing phases 5. **LCP-Trail.js** - Track LCP candidate evolution ### LCP Deep Dive When LCP is slow or the user asks "debug LCP" or "why is LCP slow": 1. **LCP.js** - Establish baseline LCP value 2. **LCP-Subparts.js** - Break down into TTFB, resource load, render delay 3. **LCP-Trail.js** - Identify all LCP candidates and changes 4. **LCP-Image-Entropy.js** - Check if LCP image has visual complexity issues 5. **LCP-Video-Candidate.js** - Detect if LCP is a video (poster or video element) ### CLS Investigation When layout shifts are detected or the user asks "debug CLS" or "layout shift issues": 1. **CLS.js** - Measure overall CLS score 2. **Layout-Shift-Loading-and-Interaction.js** _(pending — available in webperf-interaction skill)_ 3. Cross-reference with **webperf-loading** skill: - Find-Above-The-Fold-Lazy-Loaded-Images.js (lazy images causing shifts) - Fonts-Preloaded-Loaded-and-used-above-the-fold.js (font swap causing shifts) ### INP Debugging When interactions feel slow or the user asks "debug INP" or "slow interactions": 1. **INP.js** - Measure overall INP value; call `getINP()` after interactions, `getINPDetails()` for the 15 slowest interactions 2. **Interactions.js** _(pending — available in webperf-interaction skill)_ 3. **Input-Latency-Breakdown.js** _(pending — available in webperf-interaction skill)_ 4. **Long-Animation-Frames.js** _(pending — available in webperf-interaction skill)_ 5. **Long-Animation-Frames-Script-Attribution.js** _(pending — available in webperf-interaction skill)_ ### Video as LCP Investigation When LCP is a video element (detected by LCP-Video-Candidate.js): 1. **LCP-Video-Candidate.js** - Identify video as LCP candidate 2. **Video-Element-Audit.js** (from Media skill) - Audit video loading strategy 3. **LCP-Subparts.js** - Analyze video loading phases 4. Cross-reference with **webperf-loading** skill: - Resource-Hints-Validation.js (check for video preload) - Priority-Hints-Audit.js (check for fetchpriority on video) ### Image as LCP Investigation When LCP is an image (most common case): 1. **LCP.js** - Measure LCP timing 2. **LCP-Subparts.js** - Break down timing phases 3. **LCP-Image-Entropy.js** - Analyze image complexity 4. Cross-reference with **webperf-media** skill: - Image-Element-Audit.js (check format, dimensions, lazy loading) 5. Cross-reference with **webperf-loading** skill: - Find-Above-The-Fold-Lazy-Loaded-Images.js (check if incorrectly lazy) - Priority-Hints-Audit.js (check for fetchpriority="high") - Resource-Hints-Validation.js (check for preload) ## Decision Tree Use this decision tree to automatically run follow-up snippets based on results: ### After LCP.js - **If LCP > 2.5s** → Run **LCP-Subparts.js** to diagnose which phase is slow - **If LCP > 4.0s (poor)** → Run full LCP deep dive workflow (5 snippets) - **If LCP candidate is an image** → Run **LCP-Image-Entropy.js** and **webperf-media:Image-Element-Audit.js** - **If LCP candidate is a video** → Run **LCP-Video-Candidate.js** and **webperf-media:Video-Element-Audit.js** - **Always run** → **LCP-Trail.js** to understand candidate evolution ### After LCP-Subparts.js - **If TTFB phase > 600ms** → Switch to **webperf-loading** skill and run TTFB-Sub-Parts.js - **If Resource Load Time > 1500ms** → Run: 1. **webperf-loading:Resource-Hints-Validation.js** (check for preload/preconnect) 2. **webperf-loading:Priority-Hints-Audit.js** (check fetchpriority) 3. **webperf-loading:Find-render-blocking-resources.js** (competing resources) - **If Render Delay > 200ms** → Run: 1. **webperf-loading:Find-render-blocking-resources.js** (blocking CSS/JS) 2. **webperf-loading:Script-Loading.js** (parser-blocking scripts) 3. **webperf-interaction:Long-Animation-Frames.js** (main thread blocking) ### After LCP-Trail.js - **If many LCP candidate changes (>3)** → This causes visual instability, investigate: 1. **webperf-loading:Find-Above-The-Fold-Lazy-Loaded-Images.js** (late-loading images) 2. **webperf-loading:Fonts-Preloaded-Loaded-and-used-above-the-fold.js** (font swaps) 3. **CLS.js** (layout shifts contributing to LCP changes) - **If final LCP candidate appears late** → Run **webperf-loading:Resource-Hints-Validation.js** - **If early candidate was replaced** → Understand why initial content was pushed down (likely CLS issue) ### After LCP-Image-Entropy.js - **If entropy is very high** → Image is visually complex, recommend: - Modern formats (WebP, AVIF) - Appropriate compression - Potentially a placeholder strategy - **If entropy is low** → Image may be over-optimized or placeholder-like - **If large file size detected** → Run **webperf-media:Image-Element-Audit.js** for format/sizing analysis ### After LCP-Video-Candidate.js - **If video is LCP** → Run: 1. **webperf-media:Video-Element-Audit.js** (check poster, preload, formats) 2. **webperf-loading:Priority-Hints-Audit.js** (check fetchpriority on poster) 3. **LCP-Subparts.js** (analyze video loading phases) - **If poster image is LCP** → Treat as image LCP (run image workflows) ### After CLS.js - **If CLS > 0.1** → Run **webperf-interaction:Layout-Shift-Loading-and-Interaction.js** _(pending — available in webperf-interaction skill)_ - **If CLS > 0.25 (poor)** → Run comprehensive shift investigation: 1. **webperf-loading:Find-Above-The-Fold-Lazy-Loaded-Images.js** (images without dimensions) 2. **webperf-loading:Fonts-Preloaded-Loaded-and-used-above-the-fold.js** (font loading strategy) 3. **webperf-loading:Critical-CSS-Detection.js** (late-loading styles) 4. **webperf-media:Image-Element-Audit.js** (missing width/height) - **If CLS = 0** → Confirm with multiple page loads (might be timing-dependent) ### After INP.js - **If INP > 200ms** → Run **webperf-interaction:Interactions.js** to identify slow interactions - **If INP > 500ms (poor)** → Run full INP debugging workflow: 1. **webperf-interaction:Interactions.js** (list all interactions) 2. **webperf-interaction:Input-Latency-Breakdown.js** (phase breakdown) 3. **webperf-interaction:Long-Animation-Frames.js** (blocking frames) 4. **webperf-interaction:Long-Animation-Frames-Script-Attribution.js** (culprit scripts) - **If specific interaction type is slow (e.g., keyboard)** → Focus analysis on that interaction type - **After INP data is collected** → call `getINPDetails()` for the 15 slowest interactions, slowest first (useful for identifying patterns across multiple slow interactions) ### Error Recovery - **If any script returns `status: "error"`** → Check if the page has finished loading: - If early in load: wait and re-run the script - If page is an SPA: user may need to navigate to the target route first - **If LCP.js / LCP-Subparts.js returns `status: "error"`** → Tell the user: "LCP data is not available yet. Please ensure the page has fully loaded, then run the analysis again." - **If INP.js `getINP()` returns `status: "error"`** → The `getDataFn: "getINP"` field signals the agent can retry after user interaction. Prompt the user to click, type, or scroll, then call `getINP()` again. ### Cross-Skill Triggers > **Context fork note:** This skill runs with `context: fork`. Cross-skill triggers below are **recommendations to report back to the parent agent**, not direct calls this subagent can execute. When a cross-skill trigger fires, tell the user which skill and script to run next. Scripts marked _(pending)_ are not yet available — skip them and note the limitation. These triggers recommend using snippets from other skills: #### From LCP to Loading Skill - **If LCP > 2.5s and TTFB phase is dominant** → Use **webperf-loading** skill: - TTFB.js, TTFB-Sub-Parts.js, Service-Worker-Analysis.js - **If LCP image is lazy-loaded** → Use **webperf-loading** skill: - Find-Above-The-Fold-Lazy-Loaded-Images.js - **If LCP has no fetchpriority** → Use **webperf-loading** skill: - Priority-Hints-Audit.js #### From CLS to Loading Skill - **If CLS caused by fonts** → Use **webperf-loading** skill: - Fonts-Preloaded-Loaded-and-used-above-the-fold.js - Resource-Hints-Validation.js (for font preload) - **If CLS caused by images** → Use **webperf-media** skill: - Image-Element-Audit.js (check for width/height attributes) #### From INP to Interaction Skill - **If INP > 200ms** → Use **webperf-interaction** skill for full debugging: - Interactions.js, Input-Latency-Breakdown.js - Long-Animation-Frames.js, Long-Animation-Frames-Script-Attribution.js - LongTask.js (if pre-interaction blocking suspected) #### From LCP/INP to Interaction Skill - **If render delay or interaction delay is high** → Use **webperf-interaction** skill: - Long-Animation-Frames.js (main thread blocking) - LongTask.js (long tasks delaying rendering) ### Multi-Metric Correlation When multiple CWV metrics are poor, prioritize investigation: - **If LCP > 2.5s AND CLS > 0.1** → Likely shared root cause: 1. Check for late-loading content pushing LCP element 2. Run LCP-Trail.js to see LCP candidate changes 3. Run Layout-Shift-Loading-and-Interaction.js to correlate timing - **If LCP > 2.5s AND INP > 200ms** → Main thread congestion: 1. Run Long-Animation-Frames.js 2. Run webperf-loading:Script-Loading.js 3. Run webperf-loading:JS-Execution-Time-Breakdown.js - **If CLS > 0.1 AND INP > 200ms** → Layout thrashing or interaction-triggered shifts: 1. Run Layout-Shift-Loading-and-Interaction.js 2. Run Interactions.js 3. Check if shifts occur during/after interactions ## References - `references/snippets.md` — Descriptions and thresholds for each script - `references/schema.md` — Return value schema for interpreting script output
Comments (0)
Sign in to join the conversation.
Reviews (0)
No reviews yet.
No comments yet.