# Web Vitals Analyzer

> Web Vitals Analyzer

- Skill: `comeonoliver/web-vitals-analyzer` (Agent Skill)
- Install (CLI): `npx skillmds@latest add comeonoliver/web-vitals-analyzer`
- Raw SKILL.md: https://api.skillmd.com/api/skills/comeonoliver/web-vitals-analyzer/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: ComeOnOliver (https://skillmd.com/u/comeonoliver)
- Updated: 2026-09-21
- Page: https://skillmd.com/skills/comeonoliver/web-vitals-analyzer

---

# Web Vitals Analyzer

## Overview

Diagnoses Core Web Vitals failures and frontend performance issues by analyzing page structure, resource loading patterns, JavaScript bundle composition, and rendering behavior. Produces prioritized fixes with estimated metric improvements.

## Instructions

When asked to optimize frontend performance or Core Web Vitals:

1. **Gather the current state** — ask for or analyze:
   - Lighthouse report (JSON or screenshot)
   - The page URL or source code (HTML, CSS, JS entry points)
   - Framework used (React, Next.js, Vue, vanilla, etc.)
   - Current LCP, CLS, and INP values if available

2. **Analyze Largest Contentful Paint (LCP)** — target < 2.5s:
   - Identify the LCP element (usually hero image, heading, or above-fold content)
   - Check: Is the LCP image lazy-loaded? (it shouldn't be)
   - Check: Is there a `<link rel="preload">` for the LCP resource?
   - Check: Are render-blocking CSS/JS delaying first paint?
   - Check: Server response time (TTFB) — if > 800ms, it's a server issue
   - Check: Font loading strategy — is `font-display: swap` or `optional` used?
   - Check: Are critical CSS styles inlined or blocking?

3. **Analyze Cumulative Layout Shift (CLS)** — target < 0.1:
   - Identify elements causing layout shifts (images without dimensions, dynamic content, ads, web fonts)
   - Check: Do all `<img>` and `<video>` tags have explicit `width` and `height`?
   - Check: Is content injected above existing content after load?
   - Check: Are web fonts causing FOUT/FOIT shifts?
   - Check: Are dynamic ads or embeds reserving space with `aspect-ratio` or fixed containers?

4. **Analyze Interaction to Next Paint (INP)** — target < 200ms:
   - Identify heavy JavaScript on the main thread
   - Check: Are event handlers doing synchronous layout thrashing?
   - Check: Long tasks (> 50ms) blocking the main thread
   - Check: Is there unnecessary re-rendering (React: missing memoization, excessive state updates)?
   - Check: Are third-party scripts blocking interaction (analytics, chat widgets, A/B testing)?
   - Suggest: `requestIdleCallback`, `scheduler.yield()`, web workers for heavy computation

5. **Analyze bundle and resource loading:**
   - Identify total JS bundle size and largest chunks
   - Check for unused JavaScript (coverage analysis)
   - Suggest code splitting opportunities (route-based, component-based)
   - Check image formats (suggest WebP/AVIF for photos, SVG for icons)
   - Identify duplicate dependencies in the bundle

6. **Output format:**
   - Current scores vs targets for each metric
   - Prioritized list of fixes (highest impact first)
   - For each fix: what to change, where in the code, expected improvement
   - A "quick wins" section for changes that take < 15 minutes

## Examples

### Example 1: Poor LCP on a marketing site

**Input:**
```
Our landing page scores 38 on Lighthouse performance. LCP is 5.2s. Here's the page source.
```

**Output:**
```
Core Web Vitals Diagnosis
==========================
LCP: 5.2s (target: < 2.5s) ❌
CLS: 0.03 (target: < 0.1) ✓
INP: N/A (no interaction data)

Root Causes (ranked by impact):

1. CRITICAL: Hero image (2.4MB JPEG) is lazy-loaded
   File: src/components/Hero.tsx:12
   Fix: Remove loading="lazy" from the above-fold hero image.
        Add: <link rel="preload" as="image" href="/hero.jpg" fetchpriority="high">
        Convert to WebP: reduces 2.4MB → 340KB
   Expected LCP improvement: -2.1s

2. HIGH: 3 render-blocking CSS files (total 180KB uncompressed)
   Files: fonts.css (89KB), animations.css (52KB), above-fold.css (39KB)
   Fix: Inline critical CSS (above-fold.css) in <head>.
        Load fonts.css and animations.css with media="print" onload hack.
   Expected LCP improvement: -0.8s

3. MODERATE: Google Fonts loaded via @import in CSS (parser-blocking)
   Fix: Switch to <link rel="preconnect" href="https://fonts.gstatic.com">
        and <link rel="stylesheet" href="fonts-url"> in HTML <head>
   Expected LCP improvement: -0.3s

Quick wins (< 15 min each):
  • Add fetchpriority="high" to hero image tag
  • Add width/height to hero image (already good CLS, but defensive)
  • Enable text compression (gzip/brotli) on server — saves 60% on CSS
```

### Example 2: High INP on a React dashboard

**Input:**
```
Our dashboard app has INP of 890ms. Users complain clicks feel laggy. It's a React 18 app with Zustand state management.
```

**Output:**
```
INP Diagnosis: 890ms (target: < 200ms) ❌

Root Causes:

1. CRITICAL: Filter dropdown triggers full data grid re-render (45,000 rows)
   File: src/components/DataGrid.tsx
   The grid component re-renders on every filter change because the parent
   passes a new array reference each time.
   Fix: Memoize the filtered data with useMemo:
     const filteredData = useMemo(() => data.filter(filterFn), [data, filters]);
   Wrap DataGrid in React.memo().
   Expected INP improvement: -500ms

2. HIGH: Analytics script (third-party) runs 180ms synchronous task on click
   Source: analytics.min.js:1 — event listener on document.body
   Fix: Load analytics with async/defer. Move tracking to requestIdleCallback:
     document.addEventListener('click', (e) => {
       requestIdleCallback(() => trackClick(e));
     });
   Expected INP improvement: -180ms

3. MODERATE: Date formatting in table cells using Intl.DateTimeFormat per-render
   Fix: Create formatter once outside component:
     const fmt = new Intl.DateTimeFormat('en-US', { dateStyle: 'medium' });
   Expected INP improvement: -80ms
```

## Guidelines

- Always identify the specific LCP element — never give generic advice without knowing what's slow.
- CLS fixes must include explicit code changes (dimensions, aspect-ratio values, container styles).
- For INP, focus on the main thread. Network latency doesn't directly affect INP.
- Recommend `fetchpriority="high"` only for the single most important above-fold resource.
- When suggesting image format changes, note that AVIF has better compression but slower decode — WebP is the safer default.
- Account for framework-specific patterns: Next.js Image component, Nuxt's `useAsyncData`, SvelteKit's load functions.
- Don't recommend service workers for performance unless the use case specifically involves repeat visits.

