Install
$ agentstack add skill-dembrandt-dembrandt-skills-performance-and-web-vitals ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
Performance and Web Vitals
Run a Lighthouse Audit
# CLI audit — outputs JSON and HTML report
npx lighthouse https://example.com --output html --output-path ./lighthouse-report.html
# Headless, useful in CI
npx lighthouse https://example.com --chrome-flags="--headless" --output json --output-path ./report.json
# Audit specific categories only
npx lighthouse https://example.com --only-categories=performance,accessibility,seo
Or open Chrome DevTools → Lighthouse tab → Analyse page load.
Target scores: | Category | Target | |---|---| | Performance | ≥ 90 | | Accessibility | 100 | | Best Practices | ≥ 95 | | SEO | ≥ 95 |
Core Web Vitals
LCP — Largest Contentful Paint
How fast does the main content appear?
Target: ≤ 2.5s
LCP measures when the largest visible element (hero image, heading, video poster) renders. It is the user's perception of "did the page load?"
Common causes and fixes:
| Cause | Fix | |---|---| | Unoptimised hero image | Use WebP/AVIF, correct size, fetchpriority="high" | | Image not preloaded | ` | | Render-blocking CSS/JS | Defer non-critical JS, inline critical CSS | | Slow server response | CDN, caching headers, edge delivery | | Web font blocking render | font-display: swap or optional` |
Never use loading="lazy" on the LCP image — it delays the most important render.
CLS — Cumulative Layout Shift
Does content jump around while loading?
Target: ≤ 0.1
CLS measures unexpected layout shifts — content moving after it has rendered. Caused by images without dimensions, late-loading ads, fonts swapping, or dynamic content injected above existing content.
Common causes and fixes:
| Cause | Fix | |---|---| | Images without width/height | Always set width and height on ` | | Web font swap | Use font-display: optional or preload fonts | | Dynamic content above fold | Reserve space with min-height on containers | | Late-loading ads or embeds | Reserve fixed dimensions for ad slots | | Animations that shift layout | Animate transform only, never top/left/width/height` |
/* Reserve space for dynamic content */
.ad-slot { min-height: 250px; }
/* Animate transform, not layout properties */
.slide-in { transform: translateY(0); transition: transform 300ms; }
INP — Interaction to Next Paint
How quickly does the page respond to user input?
Target: ≤ 200ms
INP measures the delay between a user interaction (click, tap, keyboard) and the next visual update. High INP makes the UI feel sluggish or frozen.
Common causes and fixes:
| Cause | Fix | |---|---| | Heavy JS on main thread | Break into smaller tasks, use requestIdleCallback | | Large event handlers | Debounce/throttle scroll and resize handlers | | Synchronous DOM updates | Batch DOM writes with requestAnimationFrame | | Third-party scripts blocking | Load third-party scripts with async or defer | | React re-renders | Memoize with useMemo, useCallback, React.memo |
Images
Images are the single biggest performance lever on most pages.
Rules:
- Always set
widthandheight— prevents CLS - Use
loading="lazy"below the fold, never on LCP image - Serve WebP or AVIF — typically 30–50% smaller than JPEG
- Size images to their display size — do not serve 2000px image for a 400px slot
- Use a CDN with automatic format conversion where possible
Fonts
Web fonts block rendering if not handled correctly.
@font-face {
font-family: 'Brand';
src: url('/fonts/brand.woff2') format('woff2');
font-display: swap; /* show fallback immediately, swap when loaded */
/* font-display: optional; — never swap, use fallback if not cached */
}
font-display: swap— good for headings, acceptable CLSfont-display: optional— zero CLS, font only used if cached (best for body text)- Subset fonts to the characters actually used — reduces file size by 60–80%
JavaScript
defer: executes after HTML parsed, in order — use for most scriptsasync: executes as soon as downloaded, out of order — use for independent scripts (analytics)- Never block the main thread with synchronous `
in`
Lighthouse CI (automated audits)
Run Lighthouse in CI to catch regressions before deployment.
# Install
npm install -g @lhci/cli
# Run
lhci autorun --upload.target=temporary-public-storage
# .lighthouserc.json
{
"ci": {
"assert": {
"assertions": {
"categories:performance": ["warn", { "minScore": 0.9 }],
"categories:accessibility": ["error", { "minScore": 1.0 }],
"categories:seo": ["warn", { "minScore": 0.95 }]
}
}
}
}
Review Checklist
- [ ] Lighthouse performance score ≥ 90
- [ ] Lighthouse accessibility score = 100
- [ ] LCP ≤ 2.5s — LCP image preloaded, no
loading="lazy"on it - [ ] CLS ≤ 0.1 — all images have
widthandheight, no layout-shifting animations - [ ] INP ≤ 200ms — no heavy synchronous JS on main thread
- [ ] Images served as WebP or AVIF with correct dimensions
- [ ]
loading="lazy"on all below-fold images - [ ] Web fonts use
font-display: swaporoptional - [ ] Non-critical JS loaded with
deferorasync - [ ] Lighthouse CI configured to catch regressions in deployment pipeline
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: dembrandt
- Source: dembrandt/dembrandt-skills
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.