-
Notifications
You must be signed in to change notification settings - Fork 2.3k
feat: add webperf-core-web-vitals skill #1198
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
nucliweb
wants to merge
15
commits into
ChromeDevTools:main
Choose a base branch
from
nucliweb:feat/webperf-core-web-vitals-skill
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 11 commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
097ec5c
feat: add webperf-core-web-vitals SKILL.md with workflows and decisio…
nucliweb d2d5660
feat: add core CWV measurement scripts (LCP, CLS, INP)
nucliweb 4466cb1
feat: add LCP diagnostic scripts (Sub-Parts, Trail, Image-Entropy, Vi…
nucliweb 7773e96
feat: add webperf-core-web-vitals references (snippets and schema)
nucliweb 893f8d6
Merge branch 'main' into feat/webperf-core-web-vitals-skill
nucliweb 1c70868
refactor: make core CWV scripts agent-first (remove console output)
nucliweb e28fa02
refactor: make LCP diagnostic scripts agent-first (remove console out…
nucliweb 49f3c7c
feat: add context fork to webperf-core-web-vitals skill
nucliweb a8823bc
fix: apply skill-creator review feedback to webperf-core-web-vitals
nucliweb a9789ec
Merge branch 'main' into feat/webperf-core-web-vitals-skill
nucliweb 74b5155
Merge branch 'main' into feat/webperf-core-web-vitals-skill
nucliweb 4f7c0fb
Apply suggestions from code review
nucliweb 9a9fd2f
Rename LCP-Sub-Parts.js to LCP-SubParts.js
nucliweb 9ab0c12
Update skills/webperf-core-web-vitals/scripts/LCP-SubParts.js
nucliweb 860efed
Merge branch 'main' into feat/webperf-core-web-vitals-skill
nucliweb File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,239 @@ | ||
| --- | ||
| 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. | ||
| context: fork | ||
| --- | ||
|
|
||
| # WebPerf: Core Web Vitals | ||
|
|
||
| JavaScript snippets for measuring web performance in Chrome DevTools. Execute with `evaluate_script`, capture output with `get_console_message`. | ||
|
|
||
| ## 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-Sub-Parts.js` — LCP Sub-Parts | ||
| - `scripts/LCP-Trail.js` — LCP Trail | ||
| - `scripts/LCP-Video-Candidate.js` — LCP Video Candidate | ||
| - `scripts/LCP.js` — Largest Contentful Paint (LCP) | ||
|
|
||
| Descriptions, thresholds, and return schemas: `references/snippets.md`, `references/schema.md` | ||
|
|
||
| ## Script Execution Patterns | ||
|
|
||
| Scripts fall into two execution patterns: | ||
|
|
||
| ### Synchronous (LCP, CLS, LCP-Sub-Parts, LCP-Trail, LCP-Image-Entropy, LCP-Video-Candidate) | ||
|
|
||
| Run via `evaluate_script` and return structured JSON immediately from buffered performance data. The page must have already loaded. | ||
|
|
||
| ### Tracking (INP) | ||
|
|
||
| INP requires real user interactions to measure. The workflow is: | ||
|
|
||
| 1. Run `INP.js` via `evaluate_script` → returns `{ status: "tracking", getDataFn: "getINP" }` | ||
| 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." | ||
|
nucliweb marked this conversation as resolved.
Outdated
|
||
| 3. Wait for the user to confirm they've interacted. | ||
| 4. Call `evaluate_script("getINP()")` to collect results. | ||
| 5. If `getINP()` returns `status: "error"` → the user has not interacted yet. Remind them and wait. | ||
| 6. For a full breakdown of all interactions, call `evaluate_script("getINPDetails()")` — returns all recorded interactions sorted by duration. | ||
|
|
||
| > The agent cannot interact with the page on behalf of the user for INP measurement. Real user interactions are required. | ||
|
|
||
| ## 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-Sub-Parts.js** - Break down LCP timing phases | ||
|
nucliweb marked this conversation as resolved.
Outdated
|
||
| 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-Sub-Parts.js** - Break down into TTFB, resource load, render delay | ||
|
nucliweb marked this conversation as resolved.
Outdated
|
||
| 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** (from `webperf-interaction` skill) - Separate loading vs interaction shifts | ||
| 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** - Start tracking. Tell the user to interact with the page and confirm when done. | ||
|
nucliweb marked this conversation as resolved.
Outdated
|
||
| 2. Call `getINP()` to collect results once the user confirms. | ||
| 3. Call `getINPDetails()` to see all interactions ranked by duration. | ||
| 4. **Interactions.js** (from `webperf-interaction` skill) - List all interactions with timing | ||
| 5. **Input-Latency-Breakdown.js** (from `webperf-interaction` skill) - Break down input delay, processing, presentation | ||
| 6. **Long-Animation-Frames.js** (from `webperf-interaction` skill) - Identify blocking animation frames | ||
| 7. **Long-Animation-Frames-Script-Attribution.js** (from `webperf-interaction` skill) - Find scripts causing delays | ||
|
|
||
| ### 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-Sub-Parts.js** - Analyze video loading phases | ||
|
nucliweb marked this conversation as resolved.
Outdated
|
||
| 4. Cross-reference with **webperf-loading** skill: | ||
| - Resource-Hints-Validation.js (check for video preload) | ||
| - Priority-Hints-Audit.js (check for fetchpriority on video) | ||
|
Comment on lines
+95
to
+97
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should these be here? Ah I see these are part of #1114 |
||
|
|
||
| ### Image as LCP Investigation | ||
|
|
||
| When LCP is an image (most common case): | ||
|
|
||
| 1. **LCP.js** - Measure LCP timing | ||
| 2. **LCP-Sub-Parts.js** - Break down timing phases | ||
|
nucliweb marked this conversation as resolved.
Outdated
|
||
| 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) | ||
|
Comment on lines
+106
to
+111
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Needs #1114 to land first |
||
|
|
||
| ## Decision Tree | ||
|
|
||
| Use this decision tree to automatically run follow-up snippets based on results: | ||
|
|
||
| ### After LCP.js | ||
|
|
||
| - **If LCP > 2.5s** → Run **LCP-Sub-Parts.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-Sub-Parts.js | ||
|
nucliweb marked this conversation as resolved.
Outdated
|
||
|
|
||
| - **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-Sub-Parts.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** to separate causes | ||
| - **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 | ||
|
|
||
| ### Cross-Skill Triggers | ||
|
|
||
| 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) | ||
|
|
||
| > **Note on cross-skill references:** This skill runs in an isolated subagent (`context: fork`). When a decision tree recommends scripts from another skill (e.g., `webperf-loading`, `webperf-interaction`, `webperf-media`), report the recommendation to the user as a next step — do not attempt to execute those scripts directly. The user or the main agent can activate the appropriate skill to continue the investigation. | ||
|
|
||
| ## Error Recovery | ||
|
|
||
| When a script returns `status: "error"`: | ||
|
|
||
| - **LCP/CLS/LCP-Sub-Parts/LCP-Trail** → The page may not have finished loading. Ask the user to wait for full load or reload, then re-run the script. | ||
| - **INP** (`getINP()` returns error) → No interactions have been recorded yet. Remind the user to interact with the page, then call `getINP()` again. | ||
| - **LCP-Image-Entropy** → No images with measurable BPP found. This is normal for text-only pages or pages where all images are data URIs. | ||
| - **LCP-Video-Candidate** → No LCP entries found; see LCP error recovery above. | ||
|
|
||
| ## Visual Highlighting | ||
|
|
||
| By default, scripts highlight the LCP element(s) with colored dashed outlines — useful when the user is watching the browser while the agent runs. To disable: | ||
|
|
||
| ```js | ||
| window.__cwvHighlight = false; | ||
| // then run any LCP script | ||
| ``` | ||
|
|
||
| Scripts that support this flag: `LCP.js`, `LCP-Sub-Parts.js`, `LCP-Trail.js`. | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.