Skip to content
back to journal

core web vitals

Extreme Performance: Getting to Lighthouse 100 on Real Apps

Practical techniques for achieving perfect Lighthouse scores in production. No tricks, just engineering.

Ralph DuinJanuary 27, 20262 min read
<p>Perfect Lighthouse scores aren't just for toy demos. Here's how we consistently ship production apps that score 100 on SEO and 98+ on Performance.</p> <h2>The Performance Budget</h2> <p>Start with constraints:</p> <ul> <li>LCP (Largest Contentful Paint) ≤ 2.5s</li> <li>INP (Interaction to Next Paint) ≤ 200ms</li> <li>CLS (Cumulative Layout Shift) ≤ 0.1</li> </ul> <p>These aren't suggestions. They're requirements.</p> <h2>1. Server-First Rendering</h2> <p>Client-side JavaScript is the enemy of performance. Use Next.js Server Components by default. Ship HTML that works without JS.</p> <pre><code>// ❌ Client-heavy 'use client' export default function Page() { const [data, setData] = useState(null) useEffect(() => { fetch('/api/data').then(r => setData(r)) }, []) return <div>{data?.title}</div> } // ✅ Server-first export default async function Page() { const data = await fetchData() return <div>{data.title}</div> }</code></pre> <h2>2. Image Optimization</h2> <p>Images kill performance. Use <code>next/image</code> with proper sizing:</p> <pre><code>&lt;Image src="/hero.jpg" alt="Hero" width={1200} height={600} priority // Above fold sizes="(max-width: 768px) 100vw, 1200px" /&gt;</code></pre> <p>Key wins:</p> <ul> <li>Automatic WebP/AVIF format selection</li> <li>Lazy loading below the fold</li> <li>Responsive srcset generation</li> </ul> <h2>3. Font Loading Strategy</h2> <p>Web fonts block rendering. Use Next.js font optimization:</p> <pre><code>import { Inter } from 'next/font/google' const inter = Inter({ subsets: ['latin'], display: 'swap', // Prevent FOIT preload: true, })</code></pre> <h2>4. Resource Hints</h2> <p>Tell the browser what's coming:</p> <pre><code>&lt;link rel="preconnect" href="https://fonts.googleapis.com" /&gt; &lt;link rel="dns-prefetch" href="https://api.example.com" /&gt;</code></pre> <h2>5. Bundle Size Discipline</h2> <p>Every dependency costs performance. Audit regularly:</p> <pre><code>npx @next/bundle-analyzer</code></pre> <p>Questions to ask:</p> <ul> <li>Do we really need this library?</li> <li>Can we lazy load this?</li> <li>Is there a lighter alternative?</li> </ul> <h2>6. Caching Strategy</h2> <p>Use ISR (Incremental Static Regeneration) for content:</p> <pre><code>export const revalidate = 3600 // Revalidate hourly</code></pre> <p>Add Cloudflare in front for edge caching. Purge on content updates.</p> <h2>7. Prevent Layout Shift</h2> <p>Reserve space for dynamic content:</p> <pre><code>// ❌ Causes CLS &lt;div className="dynamic-height"&gt; {loading ? &lt;Spinner /&gt; : &lt;Content /&gt;} &lt;/div&gt; // ✅ Fixed height &lt;div className="h-96"&gt; {loading ? &lt;Spinner /&gt; : &lt;Content /&gt;} &lt;/div&gt;</code></pre> <h2>Monitoring in Production</h2> <p>Lighthouse scores in CI don't guarantee real-user performance. Use Real User Monitoring:</p> <ul> <li>Vercel Analytics (built-in for Next.js)</li> <li>Google Search Console (Core Web Vitals report)</li> <li>Custom Web Vitals tracking with analytics</li> </ul> <h2>The Workflow</h2> <ol> <li>Lighthouse CI in PR checks (block on regressions)</li> <li>Bundle size checks (block on growth > 5%)</li> <li>Manual Lighthouse audit before deploy</li> <li>Monitor Core Web Vitals post-deploy</li> </ol> <p>Perfect scores aren't magic. They're the result of disciplined engineering and performance-first architecture.</p> <!-- related:/technical-seo --> <h2>Further reading</h2> <p>Performance is one half of the ranking story. For the full picture — crawlability, schema, AI search readiness, and a 90-day remediation roadmap — see the <a href="/technical-seo">technical SEO audit service</a>, which pairs Lighthouse diagnosis with SEMrush and DataForSEO signals.</p>