perf-cwv-audit
Paste into Claude Code, Claude.ai, the desktop app, or the browser extension — ⌘/Ctrl+V. ✓ Copied. Switch to Claude and paste — ⌘/Ctrl+V.
Core Web Vitals Audit
Full Lighthouse and CrUX diagnostic for LCP, INP, and CLS. Produces a finding report ranked by estimated user impact, with code-level fixes and next-step skill references.
Usage
/perf-cwv-audit <URL> [--platform sitecore|optimizely|umbraco|headless] [--device mobile|desktop|both] [--runs <n>]
Examples:
/perf-cwv-audit https://localhost:3000— mobile + desktop, autodetect stack/perf-cwv-audit https://staging.client.com --platform sitecore --device mobile --runs 3/perf-cwv-audit https://www.client.com --device both— production CWV baseline
Phase 1 — Environment and Toolchain Check
Check what Lighthouse tooling is available:
npx lighthouse --version 2>/dev/null && echo "lighthouse available"
npx lhci --version 2>/dev/null && echo "lhci available"
node --version 2>/dev/null
If no CLI is available, proceed with static analysis (Phases 3–5) and note the limitation.
Phase 2 — Run Lighthouse
Single run (quick baseline)
npx lighthouse <URL> \
--output json \
--output-path ./lh-report.json \
--chrome-flags="--headless --no-sandbox" \
--form-factor=mobile \
--throttling-method=simulate \
--preset=perf
For desktop:
npx lighthouse <URL> \
--output json \
--output-path ./lh-report-desktop.json \
--chrome-flags="--headless --no-sandbox" \
--form-factor=desktop \
--throttling-method=simulate \
--preset=perf
Multiple runs (reduce variance — recommended for client deliverables)
Run 3–5 times and average the metric values. Variance >10% in LCP suggests unstable server response times or third-party script interference — flag as a finding.
for i in 1 2 3; do
npx lighthouse <URL> \
--output json \
--output-path ./lh-run-$i.json \
--chrome-flags="--headless --no-sandbox" \
--form-factor=mobile \
--quiet
done
Parse and average lcp, inp, cls, fcp, tbt, si across runs.
Phase 3 — Extract Key Metrics
From the Lighthouse JSON, extract these values from audits and categories:
performance score → categories.performance.score × 100
LCP → audits['largest-contentful-paint'].numericValue (ms)
INP → audits['interaction-to-next-paint'].numericValue (ms)
CLS → audits['cumulative-layout-shift'].numericValue
FCP → audits['first-contentful-paint'].numericValue (ms)
TBT → audits['total-blocking-time'].numericValue (ms)
Speed Index → audits['speed-index'].numericValue (ms)
TTFB → audits['server-response-time'].numericValue (ms)
Render-blocking savings → audits['render-blocking-resources'].details.overallSavingsMs
Unused JS savings → audits['unused-javascript'].details.overallSavingsBytes
Unused CSS savings → audits['unused-css-rules'].details.overallSavingsBytes
Phase 4 — Root Cause Diagnosis per Metric
4.1 LCP (Largest Contentful Paint)
Identify the LCP element from audits['largest-contentful-paint-element']. Common causes:
| Cause | Lighthouse Signal | Platform Pattern |
|---|---|---|
| Slow TTFB | server-response-time > 600 ms |
Sitecore uncached rendering; Optimizely DXP cold start |
| Render-blocking resources | render-blocking-resources savings > 0 |
Synchronous CSS/JS in <head> |
| LCP image not preloaded | uses-rel-preload flags LCP image |
Missing fetchpriority="high" or <link rel="preload"> |
| LCP image uncompressed | uses-optimized-images or uses-webp-images |
Sitecore Media Library serving JPEG; Umbraco ImageSharp not configured |
| Lazy-loaded LCP image | efficient-animated-content or source inspection |
loading="lazy" on above-the-fold hero |
| No CDN | uses-long-cache-ttl or headers inspection |
Origin responses without CDN in front |
4.2 INP (Interaction to Next Paint)
INP > 200 ms typically traces to main-thread blocking during user interactions. Inspect:
audits['total-blocking-time']— proxy for long tasks; TBT > 300 ms on mobile → likely INP issues- Long JavaScript tasks (> 50 ms) blocking the main thread during user interaction
- DOM size (
audits['dom-size']) > 1,500 nodes slows style/layout recalculations - Third-party scripts injecting after interaction (
audits['third-party-summary'])
Common patterns:
- React event handlers that trigger synchronous state updates and large re-renders
- Optimizely personalisation JS running on click
- Analytics/tag manager firing synchronous callbacks on interaction
4.3 CLS (Cumulative Layout Shift)
Identify the shifting elements from audits['layout-shift-elements']. Causes:
| Cause | Signal | Fix |
|---|---|---|
| Unsized images/iframes | No width/height attributes |
Add explicit dimensions or CSS aspect-ratio |
| Font FOUT | uses-rel-preload misses font; no font-display: swap |
Preload + font-display: swap |
| Dynamic content injection | Cookie banner, chat widget, personalisation slot | Reserve space with min-height; use contain: layout |
| Ad slot without reserved height | Ad tags in body | Fixed-height container around ad units |
| CMS content above existing DOM | Sitecore personalisation variant swap | Use contain: size layout on swappable regions |
Phase 5 — Platform-Specific Checks
Sitecore XM Cloud / JSS
- TTFB: Is Sitecore output cache enabled for rendering hosts? Check
rendering-host-config.jsonforcacheProfiles. - LCP image: Is the hero image served from Sitecore Media Library with proper CDN rules? Look for
/~/media/URL patterns. - JSS hydration gap: LCP candidate rendered on server but re-rendered on client causes layout shift. Check for
data-hydrationwrappers without dimensions. - XM Cloud CDN: Is the XM Cloud Edge CDN configured with
stale-while-revalidatefor content pages?
Optimizely Content Cloud / DXP
- DXP CDN caching: Is
Cache-Controlset on content page responses? Check forno-storeon pages that could be cached. - Block rendering: Does the page waterfall show sequential block fetch requests? Use
IContentLoader.GetItems()batching. - Personalisation scripts: Optimizely's personalisation JS must be loaded with
defer; synchronous load blocks FCP.
Umbraco
- Output caching: Is
UmbracoOutputCacheAttributeapplied to controllers? Uncached Umbraco pages on high-traffic routes bottleneck TTFB. - ImageSharp: Is
Umbraco.Cms.Web.Common.Media.ImageSharpImageUrlGeneratorconfigured with WebP output? - Examine index: Is index warm-up happening on startup to prevent first-request latency spikes?
Headless / Composable (Next.js on Azure)
- Rendering strategy: Is ISR (
revalidate) configured for content-heavy pages, or are they falling back to SSR on every request? <Image>component: Are all images going throughnext/image? Bypassed images miss automatic lazy loading, sizing, and format negotiation.- App Router RSC: Are data-fetching components Server Components, or are they
'use client'components doing unnecessary client-side fetches? - Azure Static Web Apps / App Service: Is the origin behind Azure Front Door with compression and caching rules?
Phase 6 — Build the Finding Report
Output a structured Markdown report. See templates.md for the full schema.
Report structure:
## CWV Audit Report — [URL]
**Audited:** [date] | **Device:** [mobile/desktop/both] | **Platform:** [detected/specified]
**Lighthouse version:** [x.x.x] | **Runs:** [n] (averaged)
### Metric Summary
| Metric | Score | Value | Target | Status |
|--------|-------|-------|--------|--------|
| LCP | — | X.Xs | ≤ 2.5s | PASS/FAIL |
| INP | — | XXms | ≤ 200ms | PASS/FAIL |
| CLS | — | 0.XX | ≤ 0.1 | PASS/FAIL |
| TBT | — | XXXms | — | INFO |
| FCP | — | X.Xs | — | INFO |
| TTFB | — | XXXms | ≤ 600ms | PASS/FAIL |
| Perf Score | XX | — | ≥ 90 | PASS/FAIL |
### Findings (ranked by impact)
[one block per finding — see templates.md]
### Quick Wins (< 1 hour each)
[list of low-effort, high-impact items]
### Next Steps
- Run `/perf-render-blocking-analysis` for CSS/JS critical-path detail
- Run `/perf-asset-optimisation` for image/font/media detail
- Run `/perf-caching-review` for CDN and cache-header detail
- Run `/perf-backlog-builder ./cwv-audit-report.md` to generate sprint stories
Quality Checklist
- LCP element identified with tagName, src/text, and estimated size
- INP root cause traced (TBT, DOM size, or specific third-party script)
- Every CLS shift element named with its cause
- Every finding has a specific action, not "consider improving"
- CWV targets cited: LCP ≤ 2.5 s, INP ≤ 200 ms, CLS ≤ 0.1 at p75
- Platform-specific patterns checked where stack identified
Reference files
reference.md— CWV metric definitions, Lighthouse audit IDs, scoring thresholdstemplates.md— Report template and finding record schemaexamples.md— Real-world finding examples with before/after fixes
Technical details
- Plugin
- performance-auditor
- Author
- Dakota Smith
- Skill name
perf-cwv-audit- Maturity
- experimental
- Security review
- No security review
- Owners
-
- engineering
- Argument hint
<URL> [--platform sitecore|optimizely|umbraco|headless] [--device mobile|desktop|both] [--runs <n>]- Allowed tools
-
ReadWriteEditGlobGrepBash(npx lighthouse *)Bash(npx lhci *)Bash(node *)Bash(cat *)Bash(ls *)WebFetch(domain:localhost)WebFetch(domain:web.dev)WebFetch(domain:developers.google.com)WebFetch(domain:pagespeed.web.dev)
- Source
plugins/performance-auditor/skills/perf-cwv-audit/SKILL.md
Edit this skill on GitHub — opens GitHub's web editor. No git knowledge needed.