Back to blog
EngineeringDate unavailable· min read

We Fixed Our LCP Problem (And Learned Why Server Components Matter)

Our homepage Performance score was stuck at 70. The culprit? A 6.3-second render delay on the hero headline. Here's how converting one component to RSC cut that to zero.

I ran a Lighthouse audit on our homepage last week. Performance score: 70. Largest Contentful Paint: 6.6 seconds. That's not a typo—six point six seconds for the main headline to become visible on a throttled mobile connection.

The target is 2.5 seconds. We weren't even close.

The Problem: Render Delay, Not Network Delay

Lighthouse's LCP breakdown showed that 93% of the delay was render delay—not network latency, not server response time. The headline wasn't waiting for data; it was waiting for JavaScript.

Here's what was happening: HomeHero was marked "use client". The entire hero section—including the H1—was client-side rendered. The server sent an empty shell. The browser had to download React, download our component code, parse it, execute it, and then hydrate before the headline appeared. On top of that, we were using Framer Motion with initial="hidden", which meant the text started invisible and only faded in after an animation fired.

Every visitor on a slow connection stared at a blank hero section for over six seconds. That's long enough to leave.

The Fix: Convert to React Server Component

The fix was architectural. We removed the "use client" directive from HomeHero and converted it to a React Server Component. The H1 now renders in the initial server HTML. No JavaScript required. The browser receives the headline in the first response and can paint it immediately.

We also removed the Framer Motion animation on the H1 itself. Animations are great, but not when they delay the LCP element. We kept fade-in animations on the supporting elements (badge, subhead, CTAs) using CSS keyframes from globals.css, but the headline itself is visible immediately—no hidden initial state, no animation delay.

What's Next

This change unblocks the path to a Performance score ≥ 90. The next step is running a production build with full bundle analysis to confirm the LCP improvement holds under real-world conditions. We're also reviewing below-fold sections to ensure they're dynamically imported where appropriate—no need to block interactivity on content that isn't visible yet.

The broader lesson: server components aren't just a framework feature; they're a performance tool. If it's above the fold and doesn't require client interactivity, it should render on the server. Every kilobyte of JavaScript you defer is a faster page load.

Six seconds to zero. One architectural change. That's what we shipped.