Skill: qa-perf
Application performance optimization. Trigger when the user wants to improve speed, reduce latency, or optimize resources.
Configuration
| Property | Value |
|---|---|
| Context | fork |
| Allowed tools | Read, Write, Edit, Bash, Glob, Grep |
| Keywords | perf |
Detailed description
Performance Optimization (pointer)
Canonical thresholds, current Web Vitals (LCP/INP/CLS — note INP replaced FID in 2024), and Chrome perf-team remediation patterns are at:
addyosmani/web-quality-skills— github.com/addyosmani/web-quality-skills (MIT, 1.8k★, maintained by Addy Osmani — Chrome DevTools / Lighthouse engineering lead). Covers Core Web Vitals, perf, a11y, SEO.- web.dev/vitals — web.dev/vitals (Google's canonical Web Vitals reference)
- Vercel React best practices — see
vercel-react-best-practicesskill (foundation-installed) for React-specific patterns
Foundation workflow (when to invoke this skill)
qa-perf is dispatched by qa-loop during the AUDIT phase, in parallel with qa-security / wcag-audit / qa-claudemd. It's a measurement workflow, not an optimisation cookbook:
- Measure first: run Lighthouse / WebPageTest / DevTools Performance against a known scope (the URL, page, or endpoint from
argument-hint). - Compare to canonical thresholds (see table below).
- Identify the bottleneck axis: render-blocking JS? N+1 DB query? Image weight? Bundle size? Each axis has a dedicated vendor remediation guide.
- Recommend with quantified impact (e.g. "lazy-loading hero image saves ~400ms LCP per Lighthouse run #3").
- Re-measure after the fix — a perf change without before/after numbers is theatre.
Canonical Web Vitals thresholds (2024-2026)
| Metric | Good | Needs improvement | Poor | Tool |
|---|---|---|---|---|
| LCP (Largest Contentful Paint) | < 2.5s | 2.5–4s | > 4s | Lighthouse, web-vitals |
| INP (Interaction to Next Paint, replaces FID) | < 200ms | 200–500ms | > 500ms | web-vitals |
| CLS (Cumulative Layout Shift) | < 0.1 | 0.1–0.25 | > 0.25 | Lighthouse, web-vitals |
| TTFB | < 200ms | 200–600ms | > 600ms | DevTools Network |
Foundation discipline (keep across releases)
- No optimisation without measurement: profile before changing code. Guessed bottlenecks are wrong ~70% of the time.
- Before/after numbers mandatory: every perf PR must include the Lighthouse delta or equivalent. Without numbers, the work is unprovable.
- Cache invalidation > caching: adding a cache is easy; correctly invalidating it is the bug surface. Surface cache TTLs in code review.
- N+1 is the #1 backend perf bug: when an endpoint feels slow, instrument query count before optimising anything else.
See also
qa-chromeskill — DevTools manual review (paired layer)dev-react-perfskill — React-specific re-render audit + memoization patternsops-monitoring— production perf instrumentation (OTEL, RUM)vercel-react-best-practicesskill (foundation-installed)- Audit pilot trace:
specs/marketplace-audit/qa-skills-pilot-2026-05-06.md
Automatic triggering
This skill is automatically activated when:
- The matching keywords are detected in the conversation
- The task context matches the skill's domain
Triggering examples
- "I want to perf..."
Context fork
Fork means the skill runs in an isolated context:
- Does not pollute the main conversation
- Results are returned cleanly
- Ideal for autonomous tasks
Practical examples
1. Example: Performance Audit Report
Example: Performance Audit Report
Scenario
Audit a Next.js e-commerce site with poor Core Web Vitals scores.
Lighthouse Results (Before)
| Metric | Score | Value | Target |
|---|---|---|---|
| Performance | 42 | - | > 90 |
| LCP | Poor | 4.8s | < 2.5s |
| FID/INP | Needs Improvement | 280ms | < 200ms |
| CLS | Poor | 0.35 | < 0.1 |
| FCP | Needs Improvement | 2.1s | < 1.8s |
| TTFB | Poor | 1.2s | < 0.8s |
Issues Identified
1. LCP: Unoptimized hero image (4.8s)
- Hero image: 2.4MB PNG, no lazy loading, no srcset
- Fix: next/image with priority, WebP format, responsive sizes
2. CLS: Layout shifts from web fonts + images (0.35)
- No width/height on images causing reflow
- FOUT from Google Fonts loaded client-side
- Fix: font-display: swap + preload, explicit image dimensions
3. INP: Heavy JS on product grid (280ms)
- 450KB unminified JS bundle on initial load
- Synchronous filtering on 500+ products
- Fix: dynamic import, virtualized list, debounced filters
4. TTFB: No caching strategy (1.2s)
- Every page request hits database
- Fix: ISR with revalidate: 60, CDN caching headers
Recommended Fixes
// 1. Optimized hero image
<Image src="/hero.webp" alt="Sale" width={1200} height={600} priority
sizes="(max-width: 768px) 100vw, 1200px" />
// 2. Font optimization in next.config
import { Inter } from 'next/font/google';
const inter = Inter({ subsets: ['latin'], display: 'swap' });
// 3. Dynamic import for heavy component
const ProductFilters = dynamic(() => import('./ProductFilters'), {
loading: () => <FilterSkeleton />,
});
// 4. ISR caching
export async function getStaticProps() {
const products = await getProducts();
return { props: { products }, revalidate: 60 };
}
Results (After)
| Metric | Before | After | Improvement |
|---|---|---|---|
| Performance | 42 | 94 | +52 points |
| LCP | 4.8s | 1.8s | -62% |
| INP | 280ms | 120ms | -57% |
| CLS | 0.35 | 0.04 | -89% |
| TTFB | 1.2s | 0.3s | -75% |
Key Decisions
- next/image with priority: Preloads LCP image, auto-optimizes format and size
- ISR over SSR: Static generation with revalidation eliminates per-request DB hits
- Dynamic imports: Code-split heavy components, load on interaction
- Font subsetting:
next/fontself-hosts and subsets, eliminates external request