Puppeteer died

November 2025.

It worked. That's the frustrating part - it actually worked.

Puppeteer opens page in headless Chrome, waits for Vue to render, saves HTML. Next request - serve the cached file, Vue hydrates on client. Response time dropped from 800ms to 50ms. SEO perfect - search engines see real content.

Beautiful architecture. I was proud of it.

Then the bug reports started. "Page flickers when I open it." Thought it was their browser. Then I saw it myself.

User opens page. Sees cached HTML - dark theme. Vue hydrates. Flash of white. Then dark again. Half a second of eye-burning flicker.

The cache was saved with one theme. Browser renders it. Then Vue kicks in, checks actual preference, applies the right theme. That transition - visible.

I tried everything. CSS transitions to smooth it over - flicker still there, just smoother. Preloader covering content until hydration completes - works, but feels like a hack. Separate cache for each theme - combinatorial explosion when you add language and other variants.

A month of this. Optimizing something that fundamentally couldn't be solved. The architecture was flawed at the core - you can't cache dynamic content that depends on client state.

Killed it. Switched to static partials. _header.html, _footer.html - truly static, pre-rendered. Middle section - dynamic, rendered on each request.

Not as fast. Not as elegant. But no flicker.

"Almost works" turned out worse than "doesn't work at all". At least with broken code you don't waste a month trying to fix the unfixable.

← Back to blog