Skip to content

Commit c68cd8b

Browse files
authored
Merge pull request #61 from nucliweb/feat/agent-skills
Agent SKILLs
2 parents 3e1e2c5 + 926744c commit c68cd8b

123 files changed

Lines changed: 29509 additions & 49 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.claude/settings.json

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"skills": [
3+
{
4+
"path": "./skills/webperf"
5+
},
6+
{
7+
"path": "./skills/webperf-core-web-vitals"
8+
},
9+
{
10+
"path": "./skills/webperf-interaction"
11+
},
12+
{
13+
"path": "./skills/webperf-loading"
14+
},
15+
{
16+
"path": "./skills/webperf-media"
17+
},
18+
{
19+
"path": "./skills/webperf-resources"
20+
}
21+
]
22+
}
Lines changed: 311 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,311 @@
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. Compatible with Chrome DevTools MCP.
4+
---
5+
6+
# WebPerf: Core Web Vitals
7+
8+
JavaScript snippets for measuring web performance in Chrome DevTools. Execute with `mcp__chrome-devtools__evaluate_script`, capture output with `mcp__chrome-devtools__get_console_message`.
9+
10+
## Available Snippets
11+
12+
| Snippet | Description | File |
13+
|---------|-------------|------|
14+
| Cumulative Layout Shift (CLS) | Quick check for Cumulative Layout Shift, a Core Web Vital that measures visual stability | scripts/CLS.js |
15+
| Interaction to Next Paint (INP) | Tracks Interaction to Next Paint, a Core Web Vital that measures responsiveness | scripts/INP.js |
16+
| LCP Image Entropy | Checks if images qualify as LCP candidates based on their entropy (bits per pixel) | scripts/LCP-Image-Entropy.js |
17+
| LCP Sub-Parts | Breaks down Largest Contentful Paint into its four phases to identify optimization opportunities | scripts/LCP-Sub-Parts.js |
18+
| LCP Trail | Tracks every LCP candidate element during page load and highlights each one with a distinct pastel-c | scripts/LCP-Trail.js |
19+
| LCP Video Candidate | Detects whether the LCP element is a <video> and audits the poster image configuration — the most co | scripts/LCP-Video-Candidate.js |
20+
| Largest Contentful Paint (LCP) | Quick check for Largest Contentful Paint, a Core Web Vital that measures loading performance | scripts/LCP.js |
21+
22+
## Execution with Chrome DevTools MCP
23+
24+
```
25+
1. mcp__chrome-devtools__navigate_page → navigate to target URL
26+
2. mcp__chrome-devtools__evaluate_script → run snippet code (read from scripts/ file)
27+
3. mcp__chrome-devtools__get_console_message → capture console output
28+
4. Interpret results using thresholds below, provide recommendations
29+
```
30+
31+
## Common Workflows
32+
33+
### Complete Core Web Vitals Audit
34+
35+
When the user asks for a comprehensive Core Web Vitals analysis or "audit CWV":
36+
37+
1. **LCP.js** - Measure Largest Contentful Paint
38+
2. **CLS.js** - Measure Cumulative Layout Shift
39+
3. **INP.js** - Measure Interaction to Next Paint
40+
4. **LCP-Sub-Parts.js** - Break down LCP timing phases
41+
5. **LCP-Trail.js** - Track LCP candidate evolution
42+
43+
### LCP Deep Dive
44+
45+
When LCP is slow or the user asks "debug LCP" or "why is LCP slow":
46+
47+
1. **LCP.js** - Establish baseline LCP value
48+
2. **LCP-Sub-Parts.js** - Break down into TTFB, resource load, render delay
49+
3. **LCP-Trail.js** - Identify all LCP candidates and changes
50+
4. **LCP-Image-Entropy.js** - Check if LCP image has visual complexity issues
51+
5. **LCP-Video-Candidate.js** - Detect if LCP is a video (poster or video element)
52+
53+
### CLS Investigation
54+
55+
When layout shifts are detected or the user asks "debug CLS" or "layout shift issues":
56+
57+
1. **CLS.js** - Measure overall CLS score
58+
2. **Layout-Shift-Loading-and-Interaction.js** (from Interaction skill) - Separate loading vs interaction shifts
59+
3. Cross-reference with **webperf-loading** skill:
60+
- Find-Above-The-Fold-Lazy-Loaded-Images.js (lazy images causing shifts)
61+
- Fonts-Preloaded-Loaded-and-used-above-the-fold.js (font swap causing shifts)
62+
63+
### INP Debugging
64+
65+
When interactions feel slow or the user asks "debug INP" or "slow interactions":
66+
67+
1. **INP.js** - Measure overall INP value
68+
2. **Interactions.js** (from Interaction skill) - List all interactions with timing
69+
3. **Input-Latency-Breakdown.js** (from Interaction skill) - Break down input delay, processing, presentation
70+
4. **Long-Animation-Frames.js** (from Interaction skill) - Identify blocking animation frames
71+
5. **Long-Animation-Frames-Script-Attribution.js** (from Interaction skill) - Find scripts causing delays
72+
73+
### Video as LCP Investigation
74+
75+
When LCP is a video element (detected by LCP-Video-Candidate.js):
76+
77+
1. **LCP-Video-Candidate.js** - Identify video as LCP candidate
78+
2. **Video-Element-Audit.js** (from Media skill) - Audit video loading strategy
79+
3. **LCP-Sub-Parts.js** - Analyze video loading phases
80+
4. Cross-reference with **webperf-loading** skill:
81+
- Resource-Hints-Validation.js (check for video preload)
82+
- Priority-Hints-Audit.js (check for fetchpriority on video)
83+
84+
### Image as LCP Investigation
85+
86+
When LCP is an image (most common case):
87+
88+
1. **LCP.js** - Measure LCP timing
89+
2. **LCP-Sub-Parts.js** - Break down timing phases
90+
3. **LCP-Image-Entropy.js** - Analyze image complexity
91+
4. Cross-reference with **webperf-media** skill:
92+
- Image-Element-Audit.js (check format, dimensions, lazy loading)
93+
5. Cross-reference with **webperf-loading** skill:
94+
- Find-Above-The-Fold-Lazy-Loaded-Images.js (check if incorrectly lazy)
95+
- Priority-Hints-Audit.js (check for fetchpriority="high")
96+
- Resource-Hints-Validation.js (check for preload)
97+
98+
## Decision Tree
99+
100+
Use this decision tree to automatically run follow-up snippets based on results:
101+
102+
### After LCP.js
103+
104+
- **If LCP > 2.5s** → Run **LCP-Sub-Parts.js** to diagnose which phase is slow
105+
- **If LCP > 4.0s (poor)** → Run full LCP deep dive workflow (5 snippets)
106+
- **If LCP candidate is an image** → Run **LCP-Image-Entropy.js** and **webperf-media:Image-Element-Audit.js**
107+
- **If LCP candidate is a video** → Run **LCP-Video-Candidate.js** and **webperf-media:Video-Element-Audit.js**
108+
- **Always run****LCP-Trail.js** to understand candidate evolution
109+
110+
### After LCP-Sub-Parts.js
111+
112+
- **If TTFB phase > 600ms** → Switch to **webperf-loading** skill and run TTFB-Sub-Parts.js
113+
- **If Resource Load Time > 1500ms** → Run:
114+
1. **webperf-loading:Resource-Hints-Validation.js** (check for preload/preconnect)
115+
2. **webperf-loading:Priority-Hints-Audit.js** (check fetchpriority)
116+
3. **webperf-loading:Find-render-blocking-resources.js** (competing resources)
117+
- **If Render Delay > 200ms** → Run:
118+
1. **webperf-loading:Find-render-blocking-resources.js** (blocking CSS/JS)
119+
2. **webperf-loading:Script-Loading.js** (parser-blocking scripts)
120+
3. **webperf-interaction:Long-Animation-Frames.js** (main thread blocking)
121+
122+
### After LCP-Trail.js
123+
124+
- **If many LCP candidate changes (>3)** → This causes visual instability, investigate:
125+
1. **webperf-loading:Find-Above-The-Fold-Lazy-Loaded-Images.js** (late-loading images)
126+
2. **webperf-loading:Fonts-Preloaded-Loaded-and-used-above-the-fold.js** (font swaps)
127+
3. **CLS.js** (layout shifts contributing to LCP changes)
128+
- **If final LCP candidate appears late** → Run **webperf-loading:Resource-Hints-Validation.js**
129+
- **If early candidate was replaced** → Understand why initial content was pushed down (likely CLS issue)
130+
131+
### After LCP-Image-Entropy.js
132+
133+
- **If entropy is very high** → Image is visually complex, recommend:
134+
- Modern formats (WebP, AVIF)
135+
- Appropriate compression
136+
- Potentially a placeholder strategy
137+
- **If entropy is low** → Image may be over-optimized or placeholder-like
138+
- **If large file size detected** → Run **webperf-media:Image-Element-Audit.js** for format/sizing analysis
139+
140+
### After LCP-Video-Candidate.js
141+
142+
- **If video is LCP** → Run:
143+
1. **webperf-media:Video-Element-Audit.js** (check poster, preload, formats)
144+
2. **webperf-loading:Priority-Hints-Audit.js** (check fetchpriority on poster)
145+
3. **LCP-Sub-Parts.js** (analyze video loading phases)
146+
- **If poster image is LCP** → Treat as image LCP (run image workflows)
147+
148+
### After CLS.js
149+
150+
- **If CLS > 0.1** → Run **webperf-interaction:Layout-Shift-Loading-and-Interaction.js** to separate causes
151+
- **If CLS > 0.25 (poor)** → Run comprehensive shift investigation:
152+
1. **webperf-loading:Find-Above-The-Fold-Lazy-Loaded-Images.js** (images without dimensions)
153+
2. **webperf-loading:Fonts-Preloaded-Loaded-and-used-above-the-fold.js** (font loading strategy)
154+
3. **webperf-loading:Critical-CSS-Detection.js** (late-loading styles)
155+
4. **webperf-media:Image-Element-Audit.js** (missing width/height)
156+
- **If CLS = 0** → Confirm with multiple page loads (might be timing-dependent)
157+
158+
### After INP.js
159+
160+
- **If INP > 200ms** → Run **webperf-interaction:Interactions.js** to identify slow interactions
161+
- **If INP > 500ms (poor)** → Run full INP debugging workflow:
162+
1. **webperf-interaction:Interactions.js** (list all interactions)
163+
2. **webperf-interaction:Input-Latency-Breakdown.js** (phase breakdown)
164+
3. **webperf-interaction:Long-Animation-Frames.js** (blocking frames)
165+
4. **webperf-interaction:Long-Animation-Frames-Script-Attribution.js** (culprit scripts)
166+
- **If specific interaction type is slow (e.g., keyboard)** → Focus analysis on that interaction type
167+
168+
### Cross-Skill Triggers
169+
170+
These triggers recommend using snippets from other skills:
171+
172+
#### From LCP to Loading Skill
173+
174+
- **If LCP > 2.5s and TTFB phase is dominant** → Use **webperf-loading** skill:
175+
- TTFB.js, TTFB-Sub-Parts.js, Service-Worker-Analysis.js
176+
177+
- **If LCP image is lazy-loaded** → Use **webperf-loading** skill:
178+
- Find-Above-The-Fold-Lazy-Loaded-Images.js
179+
180+
- **If LCP has no fetchpriority** → Use **webperf-loading** skill:
181+
- Priority-Hints-Audit.js
182+
183+
#### From CLS to Loading Skill
184+
185+
- **If CLS caused by fonts** → Use **webperf-loading** skill:
186+
- Fonts-Preloaded-Loaded-and-used-above-the-fold.js
187+
- Resource-Hints-Validation.js (for font preload)
188+
189+
- **If CLS caused by images** → Use **webperf-media** skill:
190+
- Image-Element-Audit.js (check for width/height attributes)
191+
192+
#### From INP to Interaction Skill
193+
194+
- **If INP > 200ms** → Use **webperf-interaction** skill for full debugging:
195+
- Interactions.js, Input-Latency-Breakdown.js
196+
- Long-Animation-Frames.js, Long-Animation-Frames-Script-Attribution.js
197+
- LongTask.js (if pre-interaction blocking suspected)
198+
199+
#### From LCP/INP to Interaction Skill
200+
201+
- **If render delay or interaction delay is high** → Use **webperf-interaction** skill:
202+
- Long-Animation-Frames.js (main thread blocking)
203+
- LongTask.js (long tasks delaying rendering)
204+
205+
### Multi-Metric Correlation
206+
207+
When multiple CWV metrics are poor, prioritize investigation:
208+
209+
- **If LCP > 2.5s AND CLS > 0.1** → Likely shared root cause:
210+
1. Check for late-loading content pushing LCP element
211+
2. Run LCP-Trail.js to see LCP candidate changes
212+
3. Run Layout-Shift-Loading-and-Interaction.js to correlate timing
213+
214+
- **If LCP > 2.5s AND INP > 200ms** → Main thread congestion:
215+
1. Run Long-Animation-Frames.js
216+
2. Run webperf-loading:Script-Loading.js
217+
3. Run webperf-loading:JS-Execution-Time-Breakdown.js
218+
219+
- **If CLS > 0.1 AND INP > 200ms** → Layout thrashing or interaction-triggered shifts:
220+
1. Run Layout-Shift-Loading-and-Interaction.js
221+
2. Run Interactions.js
222+
3. Check if shifts occur during/after interactions
223+
224+
---
225+
226+
---
227+
228+
## Cumulative Layout Shift (CLS)
229+
230+
Quick check for Cumulative Layout Shift, a Core Web Vital that measures visual stability. CLS tracks how much the page layout shifts unexpectedly during its lifetime, providing a single score that represents the cumulative impact of all unexpected layout shifts.
231+
232+
**Script:** `scripts/CLS.js`
233+
234+
**Thresholds:**
235+
236+
| Rating | Score | Meaning |
237+
|--------|-------|---------|
238+
| 🟢 Good | ≤ 0.1 | Stable, minimal shifting |
239+
| 🟡 Needs Improvement | ≤ 0.25 | Noticeable shifting |
240+
| 🔴 Poor | > 0.25 | Significant layout instability |
241+
242+
---
243+
244+
## Interaction to Next Paint (INP)
245+
246+
Tracks Interaction to Next Paint, a Core Web Vital that measures responsiveness. INP evaluates how quickly a page responds to user interactions throughout the entire page visit, replacing First Input Delay (FID) as a Core Web Vital in March 2024.
247+
248+
**Script:** `scripts/INP.js`
249+
250+
**Thresholds:**
251+
252+
| Rating | Time | Meaning |
253+
|--------|------|---------|
254+
| 🟢 Good | ≤ 200ms | Responsive, feels instant |
255+
| 🟡 Needs Improvement | ≤ 500ms | Noticeable delay |
256+
| 🔴 Poor | > 500ms | Slow, frustrating experience |
257+
258+
---
259+
260+
## LCP Image Entropy
261+
262+
Checks if images qualify as LCP candidates based on their entropy (bits per pixel). Since Chrome 112, low-entropy images are ignored for LCP measurement.
263+
264+
**Script:** `scripts/LCP-Image-Entropy.js`
265+
266+
**Thresholds:**
267+
268+
| BPP | Entropy | LCP Eligible | Example |
269+
|-----|---------|--------------|---------|
270+
| < 0.05 | 🔴 Low | ❌ No | Solid colors, simple gradients, placeholders |
271+
| ≥ 0.05 | 🟢 Normal | ✅ Yes | Photos, complex graphics |
272+
273+
---
274+
275+
## LCP Sub-Parts
276+
277+
Breaks down Largest Contentful Paint into its four phases to identify optimization opportunities. Understanding which phase is slowest helps you focus your optimization efforts where they'll have the most impact. Based on the Web Vitals Chrome Extension.
278+
279+
**Script:** `scripts/LCP-Sub-Parts.js`
280+
281+
---
282+
283+
## LCP Trail
284+
285+
Tracks every LCP candidate element during page load and highlights each one with a distinct pastel-colored dashed outline — so you can see the full trail from first candidate to final LCP.
286+
287+
**Script:** `scripts/LCP-Trail.js`
288+
289+
---
290+
291+
## LCP Video Candidate
292+
293+
Detects whether the LCP element is a <video> and audits the poster image configuration — the most common source of avoidable LCP delay when video is the hero element.
294+
295+
**Script:** `scripts/LCP-Video-Candidate.js`
296+
297+
---
298+
299+
## Largest Contentful Paint (LCP)
300+
301+
Quick check for Largest Contentful Paint, a Core Web Vital that measures loading performance. LCP marks when the largest content element becomes visible in the viewport.
302+
303+
**Script:** `scripts/LCP.js`
304+
305+
**Thresholds:**
306+
307+
| Rating | Time | Meaning |
308+
|--------|------|---------|
309+
| 🟢 Good | ≤ 2.5s | Fast, content appears quickly |
310+
| 🟡 Needs Improvement | ≤ 4s | Moderate delay |
311+
| 🔴 Poor | > 4s | Slow, users may abandon |
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// CLS Quick Check
2+
// https://webperf-snippets.nucliweb.net
3+
4+
(() => {
5+
let cls = 0;
6+
7+
const valueToRating = (score) =>
8+
score <= 0.1 ? "good" : score <= 0.25 ? "needs-improvement" : "poor";
9+
10+
const RATING = {
11+
good: { icon: "🟢", color: "#0CCE6A" },
12+
"needs-improvement": { icon: "🟡", color: "#FFA400" },
13+
poor: { icon: "🔴", color: "#FF4E42" },
14+
};
15+
16+
const logCLS = () => {
17+
const rating = valueToRating(cls);
18+
const { icon, color } = RATING[rating];
19+
console.log(
20+
`%cCLS: ${icon} ${cls.toFixed(4)} (${rating})`,
21+
`color: ${color}; font-weight: bold; font-size: 14px;`
22+
);
23+
};
24+
25+
const observer = new PerformanceObserver((list) => {
26+
for (const entry of list.getEntries()) {
27+
if (!entry.hadRecentInput) {
28+
cls += entry.value;
29+
}
30+
}
31+
logCLS();
32+
});
33+
34+
observer.observe({ type: "layout-shift", buffered: true });
35+
36+
// Update on visibility change (final CLS)
37+
document.addEventListener("visibilitychange", () => {
38+
if (document.visibilityState === "hidden") {
39+
observer.takeRecords();
40+
console.log("%c📊 Final CLS (on page hide):", "font-weight: bold;");
41+
logCLS();
42+
}
43+
});
44+
45+
// Expose function for manual check
46+
window.getCLS = () => {
47+
logCLS();
48+
return cls;
49+
};
50+
51+
console.log(
52+
" Call %cgetCLS()%c anytime to check current value.",
53+
"font-family: monospace; background: #f3f4f6; padding: 2px 4px;",
54+
""
55+
);
56+
})();

0 commit comments

Comments
 (0)