web-perf

Web Performance Audit

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "web-perf" with this command: npx skills add oimiragieo/agent-studio/oimiragieo-agent-studio-web-perf

Web Performance Audit

Structured 5-phase web performance audit workflow. Diagnose performance bottlenecks, measure Core Web Vitals, and produce actionable optimization recommendations.

When to Apply

Use this skill when:

  • Auditing website performance for Core Web Vitals compliance

  • Diagnosing slow page loads, high Time to Interactive, or layout shifts

  • Optimizing Largest Contentful Paint (LCP), Cumulative Layout Shift (CLS), or Interaction to Next Paint (INP)

  • Reviewing frontend code for performance anti-patterns

  • Preparing a site for Google's page experience ranking signals

  • Optimizing build output for Webpack, Vite, Next.js, or Nuxt

Core Web Vitals Thresholds

Metric Good Needs Improvement Poor What It Measures

LCP <= 2.5s 2.5s - 4.0s

4.0s Loading performance

CLS <= 0.1 0.1 - 0.25

0.25 Visual stability

INP <= 200ms 200ms - 500ms

500ms Interactivity (replaced FID)

Additional Performance Metrics

Metric Good Poor What It Measures

FCP <= 1.8s

3.0s First content rendered

TTFB <= 800ms

1800ms Server response time

TBT <= 200ms

600ms Main thread blocking

Speed Index <= 3.4s

5.8s Visual completeness over time

5-Phase Audit Workflow

Phase 1: Performance Trace

Capture a performance trace to establish baseline metrics.

Browser-Based (Chrome DevTools):

  • Open Chrome DevTools (F12) > Performance tab

  • Click "Record" and reload the page

  • Stop recording after page fully loads

  • Analyze the flame chart for:

  • Long tasks (> 50ms, marked in red)

  • Layout thrashing (forced reflow cycles)

  • Render-blocking resources

  • JavaScript execution bottlenecks

Lighthouse Audit:

CLI-based Lighthouse audit

npx lighthouse https://example.com --output=json --output-path=./lighthouse-report.json

With specific categories

npx lighthouse https://example.com --only-categories=performance --output=html

Mobile simulation (default)

npx lighthouse https://example.com --preset=perf --throttling-method=simulate

Key Trace Indicators:

  • Main thread busy time: Should be < 4s total

  • Largest task duration: Should be < 250ms

  • Script evaluation time: Should be < 2s

  • Layout/style recalculation: Should be < 500ms

Phase 2: Core Web Vitals Analysis

Measure each Core Web Vital and identify specific causes.

LCP Diagnosis

LCP measures loading performance -- when the largest content element becomes visible.

Common LCP Elements:

  • <img> elements (hero images)

  • <video> poster images

  • Block-level elements with background images

  • Text blocks (<h1> , <p> )

LCP Optimization Checklist:

Preload the LCP resource

<link rel="preload" as="image" href="/hero.webp" fetchpriority="high" />

Eliminate render-blocking resources

<!-- Defer non-critical CSS --> <link rel="stylesheet" href="/non-critical.css" media="print" onload="this.media='all'" />

<!-- Async non-critical JS --> <script src="/analytics.js" async></script>

Optimize server response time (TTFB)

  • Use CDN for static assets

  • Enable HTTP/2 or HTTP/3

  • Implement server-side caching

  • Use streaming SSR where supported

Optimize image delivery

<!-- Modern format with fallback --> <picture> <source srcset="/hero.avif" type="image/avif" /> <source srcset="/hero.webp" type="image/webp" /> <img src="/hero.jpg" alt="Hero" width="1200" height="600" fetchpriority="high" decoding="async" /> </picture>

CLS Diagnosis

CLS measures visual stability -- unexpected layout shifts during page load.

Common CLS Causes:

  • Images without explicit dimensions

  • Ads or embeds without reserved space

  • Dynamically injected content above the fold

  • Web fonts causing FOIT/FOUT (Flash of Invisible/Unstyled Text)

CLS Optimization Checklist:

Always set image dimensions

<img src="/photo.jpg" width="800" height="600" alt="Photo" />

Or use CSS aspect-ratio:

.hero-image { aspect-ratio: 16 / 9; width: 100%; }

Reserve space for dynamic content

.ad-slot { min-height: 250px; } .skeleton { height: 200px; background: #f0f0f0; }

Use font-display: swap with size-adjust

@font-face { font-family: 'CustomFont'; src: url('/font.woff2') format('woff2'); font-display: swap; size-adjust: 100.5%; /* Match fallback font metrics */ }

Avoid inserting content above existing content

  • Banners should push down from top, not shift existing content

  • Use transform animations instead of top /left /width /height

INP Diagnosis

INP measures interactivity -- the delay between user interaction and visual response.

Common INP Causes:

  • Long JavaScript tasks blocking the main thread

  • Synchronous layout/style recalculations

  • Heavy event handlers

  • Excessive re-renders (React, Vue)

INP Optimization Checklist:

Break up long tasks

// Instead of one long task function processAllItems(items) { for (const item of items) { /* heavy work */ } }

// Break into chunks with scheduler async function processAllItems(items) { for (const item of items) { processItem(item); // Yield to main thread between items await scheduler.yield(); } }

Debounce/throttle event handlers

// Throttle scroll handler let ticking = false; window.addEventListener( 'scroll', () => { if (!ticking) { requestAnimationFrame(() => { updateUI(); ticking = false; }); ticking = true; } }, { passive: true } );

Use requestIdleCallback for non-urgent work

requestIdleCallback(() => { // Analytics, prefetching, non-visible updates sendAnalytics(data); });

Phase 3: Network Analysis

Analyze network waterfall for optimization opportunities.

Key Checks:

Resource count and total size

  • Target: < 100 requests, < 2MB total (compressed)

  • Check: performance.getEntriesByType('resource').length

Critical request chains

  • Identify chains longer than 3 requests

  • Break chains with preload/prefetch hints

Compression

  • All text resources should use Brotli (br) or gzip

  • Check Content-Encoding header in response

Caching headers

Immutable assets (hashed filenames)

Cache-Control: public, max-age=31536000, immutable

HTML documents

Cache-Control: no-cache

API responses

Cache-Control: private, max-age=0, must-revalidate

HTTP/2+ multiplexing

  • Verify protocol in DevTools Network tab

  • Multiple resources should load in parallel over single connection

Phase 4: Accessibility Performance

Performance optimizations must not degrade accessibility.

Validation Checklist:

  • Lazy-loaded images have alt attributes

  • Deferred scripts do not break keyboard navigation

  • Skeleton loaders have aria-busy="true" and aria-label

  • prefers-reduced-motion is respected for animations

  • Focus management works with dynamically loaded content

/* Respect reduced motion preference */ @media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; scroll-behavior: auto !important; } }

Phase 5: Codebase Analysis

Review source code for performance anti-patterns.

Webpack Optimization

// webpack.config.js module.exports = { optimization: { splitChunks: { chunks: 'all', maxInitialRequests: 25, minSize: 20000, cacheGroups: { vendor: { test: /[\/]node_modules[\/]/, name(module) { const packageName = module.context.match(/[\/]node_modules\/([\/]|$)/)[1]; return vendor.${packageName.replace('@', '')}; }, }, }, }, }, };

Vite Optimization

// vite.config.ts export default defineConfig({ build: { rollupOptions: { output: { manualChunks: { vendor: ['react', 'react-dom'], router: ['react-router-dom'], }, }, }, cssCodeSplit: true, sourcemap: false, // Disable in production }, });

Next.js Optimization

// next.config.ts const nextConfig = { images: { formats: ['image/avif', 'image/webp'], deviceSizes: [640, 750, 828, 1080, 1200], }, experimental: { optimizePackageImports: ['lucide-react', '@heroicons/react'], }, };

Common Code Anti-Patterns

Anti-Pattern Impact Fix

Barrel file imports Bundle bloat Import directly from module

Synchronous localStorage in render Main thread block Move to useEffect or worker

Unoptimized images LCP, bandwidth Use next/image or <picture>

Inline <script> in body Render blocking Use async or defer

CSS @import chains CSSOM blocking Concatenate or inline critical CSS

Unthrottled scroll listeners INP Use passive: true

  • requestAnimationFrame

document.querySelectorAll in loops Layout thrashing Cache DOM references

Audit Report Template

Web Performance Audit Report

URL: [target URL] Date: [audit date] Tool: Lighthouse [version] / Chrome DevTools

Core Web Vitals Summary

MetricScoreRatingTarget
LCPX.XsGOOD/NEEDS IMPROVEMENT/POOR<= 2.5s
CLSX.XXGOOD/NEEDS IMPROVEMENT/POOR<= 0.1
INPXmsGOOD/NEEDS IMPROVEMENT/POOR<= 200ms
FCPX.Xs-<= 1.8s
TTFBXms-<= 800ms
TBTXms-<= 200ms

Critical Findings

P0 (Immediate Action Required)

  1. [Finding] - [Impact] - [Recommended Fix]

P1 (Address This Sprint)

  1. [Finding] - [Impact] - [Recommended Fix]

P2 (Address This Quarter)

  1. [Finding] - [Impact] - [Recommended Fix]

Optimization Recommendations (Priority Order)

  1. [Recommendation with estimated impact]
  2. [Recommendation with estimated impact]
  3. [Recommendation with estimated impact]

Anti-Patterns

  • Do NOT optimize without measuring first -- always capture baseline metrics

  • Do NOT lazy-load above-the-fold content -- it worsens LCP

  • Do NOT remove image dimensions to "fix" CLS -- use CSS aspect-ratio instead

  • Do NOT bundle all JS into a single file -- use code splitting

  • Do NOT ignore mobile performance -- test with CPU/network throttling

  • Do NOT use loading="lazy" on the LCP image -- it delays loading

  • Do NOT serve images without modern formats (AVIF/WebP)

References

  • web.dev Core Web Vitals

  • Chrome User Experience Report

  • Lighthouse Performance Scoring

  • Web Almanac Performance Chapter

Iron Laws

  • ALWAYS measure Core Web Vitals (LCP, INP, CLS) with field data (CrUX) before proposing optimizations

  • NEVER optimize based on lab data alone — real user metrics determine actual user experience

  • ALWAYS prioritize LCP ≤2.5s, INP ≤200ms, CLS ≤0.1 as the primary performance targets

  • NEVER ship a performance fix without a before/after measurement proving improvement

  • ALWAYS address critical rendering path issues before layout or paint optimizations

Anti-Patterns

Anti-Pattern Why It Fails Correct Approach

Optimizing without baseline measurement Can't prove improvement, may optimize wrong thing Measure CWV with Lighthouse and CrUX first

Lab-only metrics (Lighthouse only) Doesn't reflect real user network/device conditions Combine lab data with CrUX field data

Fixing CLS before LCP is addressed LCP impacts far more users than CLS Prioritize in order: LCP → INP → CLS

Shipping without before/after metrics No evidence of improvement for stakeholders Record pre-fix and post-fix CWV scores

Adding polyfills without code splitting Bloats JS bundle for all users Use dynamic import() with target browserslist

Memory Protocol (MANDATORY)

Before starting: Read .claude/context/memory/learnings.md

After completing:

  • New pattern -> .claude/context/memory/learnings.md

  • Issue found -> .claude/context/memory/issues.md

  • Decision made -> .claude/context/memory/decisions.md

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Security

auth-security-expert

No summary provided by upstream source.

Repository SourceNeeds Review
Security

tauri-security-rules

No summary provided by upstream source.

Repository SourceNeeds Review
Security

security-architect

No summary provided by upstream source.

Repository SourceNeeds Review
Security

rule-auditor

No summary provided by upstream source.

Repository SourceNeeds Review