---
# === IDENTITY ===
id: software/landing-pages/performance-optimization-core-web-vitals/2026
canonical_question: "How do I optimize Core Web Vitals — LCP, image compression, lazy loading, CDN config, mobile benchmarks?"
aliases:
  - "How to fix slow LCP on landing pages"
  - "Image optimization WebP AVIF lazy loading for web performance"
  - "CDN configuration for landing page speed"
  - "Core Web Vitals optimization checklist for mobile"
entity_type: execution_recipe
domain: software > landing-pages > performance optimization core web vitals
region: global
jurisdiction: global
temporal_scope: 2025-2026

# === VERIFICATION ===
last_verified: 2026-03-12
confidence: 0.92
version: 1.0
first_published: 2026-03-12

# === TEMPORAL VALIDITY ===
temporal_validity:
  status: evolving
  last_breaking_change: "INP replaced FID as a Core Web Vital in March 2024; AVIF browser support reached 95% in 2025"
  next_review: 2026-09-08
  change_sensitivity: high

# === CONSTRAINTS ===
constraints:
  - "Core Web Vitals thresholds (Good): LCP <= 2.5s, INP <= 200ms, CLS <= 0.1 — must pass at 75th percentile of page loads"
  - "Hero images must NOT be lazy-loaded — use fetchpriority='high' and eager loading for above-the-fold content"
  - "WebP browser support: ~96%, AVIF: ~95% as of 2026 — always provide fallback format"
  - "CDN caching requires correct Cache-Control headers — incorrect headers serve stale content or bypass cache entirely"
  - "Mobile devices are the primary target — 83% of landing page visitors use mobile; optimize for 3G/4G connections"

# === SKIP CONDITIONS ===
skip_this_unit_if:
  - condition: "User needs to deploy a landing page, not optimize it"
    use_instead: "software/landing-pages/landing-page-platform-deployment/2026"
  - condition: "User needs analytics setup, not performance optimization"
    use_instead: "software/landing-pages/analytics-implementation/2026"
  - condition: "User needs full application performance tuning, not landing page"
    use_instead: "Search knowledgelib.io for MVP tech stack selection — no dedicated unit yet"

# === AGENT HINTS ===
inputs_needed:
  - key: hosting_platform
    question: "Where is the landing page hosted?"
    type: choice
    options: ["Vercel", "Netlify", "Cloudflare Pages", "Webflow", "Framer", "Custom server", "other"]
  - key: technical_skill
    question: "What is the user's technical skill level?"
    type: choice
    options: ["non-technical (no-code only)", "semi-technical (can edit code)", "developer (can write code)"]
  - key: current_performance
    question: "What is the current PageSpeed Insights score?"
    type: choice
    options: ["below 50 (poor)", "50-70 (needs improvement)", "70-90 (good)", "above 90 (excellent)", "unknown"]
  - key: budget_for_tools
    question: "What's the tool/API budget?"
    type: choice
    options: ["free tier only", "up to $20/month", "up to $50/month", "no limit"]

# === EXECUTION METADATA ===
execution:
  required_inputs:
    - name: "Deployed landing page"
      source: "software/landing-pages/landing-page-platform-deployment/2026"
      format: "live URL"
    - name: "Current performance baseline"
      source: "PageSpeed Insights or Lighthouse audit"
      format: "performance score and CWV metrics"
  outputs:
    - name: "Optimized landing page"
      format: "live URL with improved CWV scores"
      description: "Landing page passing all Core Web Vitals thresholds with documented before/after metrics"
    - name: "Performance audit report"
      format: "text document"
      description: "Before/after metrics, optimizations applied, and remaining opportunities"
  tools_required:
    - name: "Google PageSpeed Insights"
      purpose: "Measure Core Web Vitals and get optimization recommendations"
      tier: "free"
      cost: "$0"
      alternatives: ["Lighthouse CLI", "WebPageTest", "GTmetrix"]
    - name: "Image optimization tool"
      purpose: "Compress and convert images to WebP/AVIF"
      tier: "free"
      cost: "$0"
      alternatives: ["Squoosh", "Sharp (Node.js)", "TinyPNG", "Cloudinary"]
    - name: "CDN"
      purpose: "Serve assets from edge locations globally"
      tier: "free"
      cost: "$0 (Cloudflare free tier)"
      alternatives: ["Cloudflare", "Vercel Edge", "Netlify CDN", "BunnyCDN ($1/mo)"]
  credentials_needed:
    - service: "Google PageSpeed Insights API (optional)"
      type: "API key"
      where_to_get: "https://developers.google.com/speed/docs/insights/v5/get-started"
      free_tier_limits: "25,000 queries/day"
    - service: "Cloudflare (optional)"
      type: "username+password"
      where_to_get: "https://dash.cloudflare.com/sign-up"
      free_tier_limits: "Unlimited bandwidth, basic CDN features"
  estimated_duration: "1-3 hours depending on current performance"
  estimated_cost: "$0 (all free tools) to $20/mo (image CDN service)"

# === DISTRIBUTION ===
canonical_source: "https://knowledgelib.io/software/landing-pages/performance-optimization-core-web-vitals/2026"
suggested_citation: "Source: knowledgelib.io — AI Knowledge Library (verified 2026-03-12)"

# === RELATED UNITS ===
related_kos:
  depends_on:
    - id: "software/landing-pages/landing-page-platform-deployment/2026"
      label: "Landing page must be deployed before optimizing"
  feeds_into:
    - id: "software/landing-pages/ab-testing-infrastructure/2026"
      label: "A/B test performance variants"
  related_to:
    - id: "software/landing-pages/analytics-implementation/2026"
      label: "Analytics reveals performance bottlenecks"
  alternative_to: []

# === SOURCES ===
sources:
  - id: src1
    title: "Core Web Vitals — LCP, INP & CLS Explained"
    author: CoreWebVitals.io
    url: https://www.corewebvitals.io/core-web-vitals
    type: technical_reference
    published: 2026-01-01
    reliability: high
  - id: src2
    title: "How the Core Web Vitals metrics thresholds were defined"
    author: Google
    url: https://web.dev/articles/defining-core-web-vitals-thresholds
    type: official_docs
    published: 2025-01-01
    reliability: authoritative
  - id: src3
    title: "Image Optimization for The Web: 2026 Proven Techniques"
    author: NitroPack
    url: https://nitropack.io/blog/image-optimization-for-the-web-the-essential-guide/
    type: technical_blog
    published: 2026-01-01
    reliability: high
  - id: src4
    title: "Lazy Loading + Image CDN — Cut Initial Page Load by 50-70%"
    author: TheImageCDN
    url: https://theimagecdn.com/docs/lazy-loading-image-cdn
    type: technical_blog
    published: 2026-01-01
    reliability: high
  - id: src5
    title: "Core Web Vitals 2026: INP, LCP & CLS Optimization"
    author: Digital Applied
    url: https://www.digitalapplied.com/blog/core-web-vitals-2026-inp-lcp-cls-optimization-guide
    type: technical_blog
    published: 2026-01-01
    reliability: high
  - id: src6
    title: "Page Speed Optimization Guide for 2026"
    author: Replo
    url: https://www.replo.app/blog/page-speed-optimization
    type: technical_blog
    published: 2026-01-01
    reliability: high
  - id: src7
    title: "How to Optimize Website Images: The Complete 2026 Guide"
    author: Request Metrics
    url: https://requestmetrics.com/web-performance/high-performance-images/
    type: technical_blog
    published: 2026-01-01
    reliability: high
---

# Performance Optimization: Core Web Vitals

## Purpose

This recipe optimizes a landing page to pass all three Core Web Vitals thresholds — LCP under 2.5 seconds, INP under 200 milliseconds, and CLS under 0.1. The output is a measurably faster landing page with documented before/after metrics, covering image compression, lazy loading, CDN configuration, font optimization, JavaScript reduction, and mobile-specific techniques. Sites passing all CWV see 24% lower bounce rates and improved organic rankings. [src1]

## Prerequisites

- [ ] **Deployed landing page** — [Landing Page Platform Deployment](/software/landing-pages/landing-page-platform-deployment/2026)
- [ ] **Baseline performance measurement** — run [PageSpeed Insights](https://pagespeed.web.dev/) on your URL and record current scores
- [ ] **Code editing access** — ability to modify HTML, CSS, and image assets
- [ ] **Image source files** — original (uncompressed) versions of hero images and graphics if available
- [ ] **Chrome DevTools** — for Lighthouse audits and performance profiling

## Constraints

- Core Web Vitals thresholds: LCP <= 2.5s, INP <= 200ms, CLS <= 0.1. These are evaluated at the 75th percentile of all page loads over 28 days. [src2]
- Hero/above-the-fold images must NOT be lazy-loaded — they need `fetchpriority="high"` and eager loading. Lazy-loading above-the-fold content makes LCP worse. [src3]
- Only 62% of mobile pages achieve good LCP as of 2025 — LCP is the hardest CWV metric to pass. [src5]
- 43% of sites fail the INP 200ms threshold — INP is the most commonly failed CWV in 2026. [src5]
- Images comprise 34% of average mobile page weight. Optimizing images alone can cut load time by 30-50%. [src3]
- Every second of load time costs approximately 7% in conversions. 53% of mobile users abandon pages taking over 3 seconds. [src6]

## Tool Selection Decision

```
Which optimization path?
├── Page is image-heavy with LCP > 2.5s
│   └── PATH A: Image Optimization First — WebP/AVIF, sizing, lazy loading, preloading
├── Page has JavaScript-heavy interactions with INP > 200ms
│   └── PATH B: JavaScript Optimization — code splitting, defer/async, worker offload
├── Page has layout shifts with CLS > 0.1
│   └── PATH C: Layout Stability — explicit dimensions, font loading, reserved space
└── Page needs comprehensive optimization (all metrics poor)
    └── PATH D: Full Optimization — all paths in sequence A → C → B
```

| Path | Focus | Typical Improvement | Time Required |
|------|-------|-------------------|---------------|
| A: Images | LCP + page weight | LCP -40-60%, page weight -50% | 1-2 hours |
| B: JavaScript | INP + interactivity | INP -30-50%, TTI improvement | 1-2 hours |
| C: Layout | CLS + visual stability | CLS to near 0, no layout shifts | 30-60 minutes |
| D: Full | All CWV metrics | PSI score +20-40 points | 2-4 hours |

## Execution Flow

### Step 1: Run Baseline Audit

**Duration**: 10 minutes
**Tool**: PageSpeed Insights + Lighthouse

Run both lab and field measurements to understand current performance.

```bash
# Method 1: PageSpeed Insights (includes field data)
# Visit https://pagespeed.web.dev/ and enter your URL

# Method 2: Lighthouse CLI (lab data only, more detailed)
npm install -g lighthouse
lighthouse https://yourdomain.com --output=json --output-path=./baseline-audit.json

# Method 3: Chrome DevTools
# Open DevTools → Lighthouse tab → check "Performance" → Analyze page load
```

Record these baseline metrics:

```
Baseline Metrics Template:
─────────────────────────────────────────
LCP:           __.__ s  (Good: <= 2.5s)
INP:           ___ ms   (Good: <= 200ms)
CLS:           0.___    (Good: <= 0.1)
FCP:           __.__ s
TTFB:          ___ ms
Total page weight: ___ KB
Number of requests: ___
PSI Performance score: ___/100
```

**Verify**: You have numeric values for all three CWV metrics and a baseline PSI score.
**If failed**: If field data is unavailable (new page), use lab data from Lighthouse. Field data requires 28 days of Chrome UX Report data.

### Step 2: Optimize Images (Highest Impact for LCP)

**Duration**: 30-60 minutes
**Tool**: Squoosh, Sharp, or image CDN

Images are typically the largest content element (and therefore the LCP element) and account for 34% of page weight. [src3]

**Step 2a: Identify the LCP element**

```
In Chrome DevTools → Performance tab → Record page load → click LCP marker
This shows which element is the Largest Contentful Paint. Usually it's:
- Hero image
- Above-the-fold background image
- Large heading (if no images above fold)
```

**Step 2b: Convert images to modern formats**

```bash
# Using Sharp (Node.js) — batch convert to WebP
npm install sharp
node -e "
const sharp = require('sharp');
const fs = require('fs');
const images = fs.readdirSync('./images').filter(f => /\.(jpg|jpeg|png)$/i.test(f));
images.forEach(img => {
  sharp('./images/' + img)
    .webp({ quality: 80 })
    .toFile('./images/' + img.replace(/\.(jpg|jpeg|png)$/i, '.webp'));
  sharp('./images/' + img)
    .avif({ quality: 65 })
    .toFile('./images/' + img.replace(/\.(jpg|jpeg|png)$/i, '.avif'));
});
"

# Using Squoosh CLI
npx @nicolo-ribaudo/squoosh-cli --webp '{"quality":80}' --avif '{"quality":65}' ./images/*.jpg
```

**Step 2c: Implement responsive images with format fallback**

```html
<!-- Hero image (above-the-fold): eager load + high priority -->
<picture>
  <source srcset="/images/hero.avif" type="image/avif">
  <source srcset="/images/hero.webp" type="image/webp">
  <img src="/images/hero.jpg" alt="Hero description"
       width="1200" height="630"
       fetchpriority="high"
       decoding="async">
</picture>

<!-- Below-the-fold images: lazy load -->
<picture>
  <source srcset="/images/feature.avif" type="image/avif">
  <source srcset="/images/feature.webp" type="image/webp">
  <img src="/images/feature.jpg" alt="Feature description"
       width="600" height="400"
       loading="lazy"
       decoding="async">
</picture>
```

**Step 2d: Serve responsive sizes**

```html
<!-- Responsive hero image with srcset -->
<picture>
  <source srcset="/images/hero-400.avif 400w,
                  /images/hero-800.avif 800w,
                  /images/hero-1200.avif 1200w"
          sizes="100vw" type="image/avif">
  <source srcset="/images/hero-400.webp 400w,
                  /images/hero-800.webp 800w,
                  /images/hero-1200.webp 1200w"
          sizes="100vw" type="image/webp">
  <img src="/images/hero-800.jpg" alt="Hero"
       width="1200" height="630"
       fetchpriority="high" decoding="async">
</picture>
```

**Verify**: Run PageSpeed Insights again. LCP should improve by 0.5-2 seconds. Total page weight should decrease by 30-60%.
**If failed**: If LCP is still > 2.5s, check TTFB — the server response time may be the bottleneck, not images. Move to CDN configuration (Step 4). [src4]

### Step 3: Fix Layout Shifts (CLS)

**Duration**: 20-30 minutes
**Tool**: Code editor

CLS issues cause visible jumps as content loads. The most common causes: images without dimensions, late-loading fonts, and dynamically injected content. [src5]

**Step 3a: Add explicit dimensions to all media**

```html
<!-- Every <img> needs width and height attributes -->
<img src="/images/photo.webp" alt="Description" width="600" height="400" loading="lazy">

<!-- Every <video> and <iframe> needs dimensions -->
<iframe src="..." width="560" height="315" loading="lazy"></iframe>

<!-- Use CSS aspect-ratio for responsive containers -->
<style>
  .hero-image-container {
    aspect-ratio: 16 / 9;
    width: 100%;
    overflow: hidden;
  }
</style>
```

**Step 3b: Optimize font loading**

```html
<!-- Preload critical fonts -->
<link rel="preload" href="/fonts/inter-var.woff2" as="font" type="font/woff2" crossorigin>

<style>
  /* Use font-display: swap to prevent invisible text */
  @font-face {
    font-family: 'Inter';
    src: url('/fonts/inter-var.woff2') format('woff2');
    font-display: swap;
    font-weight: 100 900;
  }

  /* Optional: size-adjust to match fallback font metrics */
  @font-face {
    font-family: 'Inter';
    src: url('/fonts/inter-var.woff2') format('woff2');
    font-display: swap;
    size-adjust: 107%;
    ascent-override: 90%;
    descent-override: 22%;
    line-gap-override: 0%;
  }
</style>
```

**Step 3c: Reserve space for dynamic content**

```css
/* Reserve space for ads, embeds, or lazy-loaded content */
.ad-slot {
  min-height: 250px; /* Match expected ad height */
  background: #f5f5f5;
}

.testimonial-carousel {
  min-height: 200px; /* Prevent shift when carousel loads */
}
```

**Verify**: CLS should be <= 0.1 in Lighthouse. Use Chrome DevTools → Performance → check for layout shift entries (highlighted in pink).
**If failed**: If CLS persists, check for late-loading third-party scripts (chat widgets, analytics) that inject content. Defer these or reserve space.

### Step 4: Configure CDN and Caching

**Duration**: 15-30 minutes
**Tool**: CDN provider dashboard or hosting platform

Most modern hosting platforms (Vercel, Netlify, Cloudflare Pages) include CDN by default. For custom hosting, add Cloudflare or BunnyCDN.

**Step 4a: Set proper Cache-Control headers**

```
# Static assets (images, CSS, JS with hashed filenames)
Cache-Control: public, max-age=31536000, immutable

# HTML pages (need freshness checks)
Cache-Control: public, max-age=0, must-revalidate

# Fonts
Cache-Control: public, max-age=31536000, immutable
```

**Cloudflare Pages (_headers file):**

```
# prototype/_headers
/images/*
  Cache-Control: public, max-age=31536000, immutable

/css/*
  Cache-Control: public, max-age=31536000, immutable

/js/*
  Cache-Control: public, max-age=31536000, immutable

/fonts/*
  Cache-Control: public, max-age=31536000, immutable

/*.html
  Cache-Control: public, max-age=0, must-revalidate
```

**Step 4b: Preconnect to third-party origins**

```html
<!-- Add to <head> for any external resources -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="preconnect" href="https://www.googletagmanager.com">
```

**Verify**: Check response headers in DevTools → Network → select asset → Headers. Verify `Cache-Control` values match. Second page load should be significantly faster.
**If failed**: If CDN is not serving cached content, check for `Vary` headers that may prevent caching, or purge the CDN cache manually.

### Step 5: Optimize JavaScript and CSS

**Duration**: 20-40 minutes
**Tool**: Code editor + bundler

JavaScript blocking the main thread is the primary cause of poor INP scores. [src5]

**Step 5a: Defer non-critical JavaScript**

```html
<!-- Critical: load synchronously (keep minimal) -->
<script src="/js/critical.js"></script>

<!-- Non-critical: defer loading -->
<script defer src="/js/analytics.js"></script>
<script defer src="/js/form-validation.js"></script>

<!-- Third-party widgets: load after page is interactive -->
<script>
  window.addEventListener('load', function() {
    // Load chat widget, social embeds, etc. after page load
    const script = document.createElement('script');
    script.src = 'https://widget.example.com/embed.js';
    document.body.appendChild(script);
  });
</script>
```

**Step 5b: Inline critical CSS, defer the rest**

```html
<head>
  <!-- Inline critical CSS (above-the-fold styles only) -->
  <style>
    /* Only styles needed for initial render */
    body { margin: 0; font-family: Inter, system-ui, sans-serif; }
    .hero { padding: 4rem 2rem; text-align: center; }
    .cta-button { padding: 1rem 2rem; background: #2563eb; color: white; border: none; border-radius: 8px; font-size: 1.125rem; cursor: pointer; }
  </style>

  <!-- Load full stylesheet asynchronously -->
  <link rel="preload" href="/css/style.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
  <noscript><link rel="stylesheet" href="/css/style.css"></noscript>
</head>
```

**Step 5c: Break long JavaScript tasks**

```javascript
// Bad: single long task blocking main thread
function processAllItems(items) {
  items.forEach(item => heavyComputation(item)); // blocks for 500ms+
}

// Good: yield to main thread between chunks
async function processAllItems(items) {
  const CHUNK_SIZE = 10;
  for (let i = 0; i < items.length; i += CHUNK_SIZE) {
    const chunk = items.slice(i, i + CHUNK_SIZE);
    chunk.forEach(item => heavyComputation(item));
    // Yield to main thread
    await new Promise(resolve => setTimeout(resolve, 0));
  }
}
```

**Verify**: Run Lighthouse again. INP should be < 200ms. Check DevTools → Performance for long tasks (red flags on main thread).
**If failed**: If INP is still poor, identify the specific interaction causing delays using DevTools → Performance → record a click interaction and look for long tasks during that period.

### Step 6: Run Final Audit and Document Results

**Duration**: 10 minutes
**Tool**: PageSpeed Insights + documentation

```
Final Audit Template:
─────────────────────────────────────────
                    BEFORE      AFTER     TARGET
LCP:                __.__ s     __.__ s   <= 2.5s
INP:                ___ ms      ___ ms    <= 200ms
CLS:                0.___       0.___     <= 0.1
PSI Score (Mobile): ___/100     ___/100   >= 90
PSI Score (Desktop):___/100     ___/100   >= 90
Page Weight:        ___ KB      ___ KB    < 500 KB
Requests:           ___         ___       < 30
TTFB:               ___ ms      ___ ms    < 800ms

Optimizations Applied:
─────────────────────────────────────────
[ ] Images converted to WebP/AVIF
[ ] Hero image preloaded with fetchpriority="high"
[ ] Below-fold images lazy-loaded
[ ] Explicit dimensions on all media
[ ] Fonts preloaded with font-display: swap
[ ] CDN caching configured
[ ] Non-critical JS deferred
[ ] Critical CSS inlined
[ ] Third-party scripts delayed
```

**Verify**: All three CWV metrics are in the "Good" range. PSI Performance score is >= 90 on mobile.
**If failed**: If one metric is still failing, focus remaining effort on the specific bottleneck. LCP > 2.5s: check TTFB and server response. INP > 200ms: profile the specific interaction. CLS > 0.1: use Layout Shift debugger in DevTools.

## Output Schema

```json
{
  "output_type": "performance_optimized_page",
  "format": "live URL + audit report",
  "columns": [
    {"name": "url", "type": "string", "description": "Landing page URL", "required": true},
    {"name": "lcp_before", "type": "number", "description": "LCP before optimization (seconds)", "required": true},
    {"name": "lcp_after", "type": "number", "description": "LCP after optimization (seconds)", "required": true},
    {"name": "inp_before", "type": "number", "description": "INP before (milliseconds)", "required": true},
    {"name": "inp_after", "type": "number", "description": "INP after (milliseconds)", "required": true},
    {"name": "cls_before", "type": "number", "description": "CLS before optimization", "required": true},
    {"name": "cls_after", "type": "number", "description": "CLS after optimization", "required": true},
    {"name": "psi_score_before", "type": "number", "description": "PSI mobile score before", "required": true},
    {"name": "psi_score_after", "type": "number", "description": "PSI mobile score after", "required": true}
  ],
  "expected_row_count": "1",
  "sort_order": "N/A",
  "deduplication_key": "url"
}
```

## Quality Benchmarks

| Quality Metric | Minimum Acceptable | Good | Excellent |
|---------------|-------------------|------|-----------|
| LCP | <= 2.5s | <= 1.5s | <= 1.0s |
| INP | <= 200ms | <= 100ms | <= 50ms |
| CLS | <= 0.1 | <= 0.05 | <= 0.01 |
| PSI Mobile Score | >= 70 | >= 90 | >= 95 |
| Total Page Weight | < 1 MB | < 500 KB | < 200 KB |
| HTTP Requests | < 50 | < 30 | < 15 |

**If below minimum**: Focus on the single worst metric first. LCP failing: optimize hero image and server response time. INP failing: profile and eliminate long JavaScript tasks. CLS failing: add dimensions to all media elements. [src1]

## Error Handling

| Error | Likely Cause | Recovery Action |
|-------|-------------|----------------|
| LCP worse after optimization | Lazy-loaded the hero image by mistake | Remove `loading="lazy"` from LCP element; add `fetchpriority="high"` |
| CLS increased after font changes | font-display: swap causes flash of unstyled text | Add `size-adjust` to @font-face to match fallback metrics; preload fonts |
| WebP/AVIF images not serving | Server not configured for modern formats | Use `<picture>` element with fallback, not server-side content negotiation alone |
| PSI score varies between runs | Lab tests have inherent variance (±5 points) | Run 3 times and take the median; rely on field data for accurate CWV |
| CDN not caching assets | Missing or incorrect Cache-Control headers | Check response headers in DevTools; purge CDN cache after header changes |
| Third-party script blocking INP | Chat widget or analytics script blocking main thread | Delay third-party scripts until after page load event; use web worker where possible |

## Cost Breakdown

| Component | Free Tier | Paid Tier | At Scale |
|-----------|-----------|-----------|----------|
| PageSpeed Insights | $0 (unlimited) | $0 | $0 |
| Lighthouse CLI | $0 (unlimited) | $0 | $0 |
| Image compression (Squoosh) | $0 (unlimited) | $0 | $0 |
| Image compression (Sharp) | $0 (open source) | $0 | $0 |
| Image CDN (Cloudinary) | $0 (25 credits/mo) | $89/mo Plus | $224/mo Advanced |
| CDN (Cloudflare) | $0 (unlimited bandwidth) | $20/mo Pro | $200/mo Business |
| WebPageTest | $0 (limited) | $0 | $0 |
| **Total** | **$0** | **$0-20/mo** | **$89-224/mo** |

## Anti-Patterns

### Wrong: Lazy-loading above-the-fold images
Adding `loading="lazy"` to the hero image delays LCP because the browser deprioritizes the image load. This is one of the most common performance mistakes. [src3]

### Correct: Use fetchpriority="high" for the LCP element
The hero image should be eagerly loaded with `fetchpriority="high"` to tell the browser to prioritize it. Only lazy-load images that are below the fold.

### Wrong: Serving all images at full resolution
A 3000x2000 hero image compressed to WebP is still far larger than necessary for a mobile viewport that is 375px wide. Sending 10x more pixels than needed wastes bandwidth. [src7]

### Correct: Use responsive images with srcset and sizes
Serve different image sizes for different viewports using `srcset` and `sizes` attributes. On mobile, a 400px wide image is sufficient for most hero sections.

## When This Matters

Use this recipe when the agent needs to improve landing page load speed, Core Web Vitals scores, or PageSpeed Insights scores. Requires an already-deployed landing page with code editing access. This recipe diagnoses performance issues and applies specific fixes — it does not redesign the page or change its content.

## Related Units

- [Landing Page Platform Deployment](/software/landing-pages/landing-page-platform-deployment/2026) — deployment platform affects baseline performance
- [Analytics Implementation](/software/landing-pages/analytics-implementation/2026) — analytics can reveal real-user performance data
- [A/B Testing Infrastructure](/software/landing-pages/ab-testing-infrastructure/2026) — A/B test performance variants
