Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
643 changes: 0 additions & 643 deletions .claude/skills/SCHEMA.md

This file was deleted.

30 changes: 19 additions & 11 deletions .claude/skills/webperf-core-web-vitals/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ JavaScript snippets for measuring web performance in Chrome DevTools. Execute wi
- `scripts/LCP-Video-Candidate.js` — LCP Video Candidate
- `scripts/LCP.js` — Largest Contentful Paint (LCP)

Descriptions and thresholds: `references/snippets.md`

## Common Workflows

Expand Down Expand Up @@ -54,7 +53,7 @@ When LCP is slow or the user asks "debug LCP" or "why is LCP slow":
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 Interaction skill) - Separate loading vs interaction shifts
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)
Expand All @@ -63,11 +62,11 @@ When layout shifts are detected or the user asks "debug CLS" or "layout shift is

When interactions feel slow or the user asks "debug INP" or "slow interactions":

1. **INP.js** - Measure overall INP value
2. **Interactions.js** (from Interaction skill) - List all interactions with timing
3. **Input-Latency-Breakdown.js** (from Interaction skill) - Break down input delay, processing, presentation
4. **Long-Animation-Frames.js** (from Interaction skill) - Identify blocking animation frames
5. **Long-Animation-Frames-Script-Attribution.js** (from Interaction skill) - Find scripts causing delays
1. **INP.js** - Measure overall INP value; call `getINP()` after interactions, `getINPDetails()` for full list
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

Expand Down Expand Up @@ -146,7 +145,7 @@ Use this decision tree to automatically run follow-up snippets based on results:

### After CLS.js

- **If CLS > 0.1** → Run **webperf-interaction:Layout-Shift-Loading-and-Interaction.js** to separate causes
- **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)
Expand All @@ -163,9 +162,20 @@ Use this decision tree to automatically run follow-up snippets based on results:
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 full sorted interaction list (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-Sub-Parts.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
Expand Down Expand Up @@ -223,6 +233,4 @@ When multiple CWV metrics are poor, prioritize investigation:
## References

- `references/snippets.md` — Descriptions and thresholds for each script
- `references/schema.md` — Return value schema for interpreting script output

> Execute via `mcp__chrome-devtools__evaluate_script` → read with `mcp__chrome-devtools__get_console_message`.
- `references/schema.md` — Return value schema for interpreting script output
15 changes: 14 additions & 1 deletion .claude/skills/webperf-core-web-vitals/references/schema.md
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ Keep the existing `async () => {}` wrapper. Add a `return` statement with struct
```

#### CLS
Returns buffered CLS immediately and keeps tracking. Always call `getCLS()` after interactions to get an updated value.
```json
{
"script": "CLS",
Expand All @@ -194,9 +195,12 @@ Keep the existing `async () => {}` wrapper. Add a `return` statement with struct
"value": 0.05,
"unit": "score",
"rating": "good",
"thresholds": { "good": 0.1, "needsImprovement": 0.25 }
"thresholds": { "good": 0.1, "needsImprovement": 0.25 },
"message": "CLS tracking active. Call getCLS() for updated value after page interactions.",
"getDataFn": "getCLS"
}
```
`getCLS()` returns the same shape with the latest accumulated value.

#### INP (tracking)
```json
Expand Down Expand Up @@ -224,6 +228,15 @@ Keep the existing `async () => {}` wrapper. Add a `return` statement with struct
}
}
```
If no interactions yet, `getINP()` returns `status: "error"` with `getDataFn: "getINP"` — retry after user interaction.

`getINPDetails()` returns the full sorted interaction list (array of up to 15 entries). Use when `getINP()` shows poor INP and you need to identify patterns across multiple slow interactions:
```json
[
{ "formattedName": "click → button.submit", "duration": 450, "startTime": 1200,
"phases": { "inputDelay": 120, "processingTime": 280, "presentationDelay": 50 } }
]
```

#### LCP-Sub-Parts
```json
Expand Down
2 changes: 1 addition & 1 deletion .claude/skills/webperf-core-web-vitals/scripts/CLS.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions .claude/skills/webperf-core-web-vitals/scripts/INP.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading