Performance
Core Web Vitals, load time and the handful of changes that move them most.
Headless Chrome for Social Cards and Visual Checks
Generating per-route social cards from real HTML, plus the screenshot helper I use to verify layout work — and the colour bug that fools both.
Prefetch on Hover: Navigation That Feels Instant
A pointer arrives at a link about 200ms before the click. That gap is enough to load the next page — if you spend it carefully and not on everything.
Lazy-Loading the Heavy Libraries Nobody Uses
A PDF generator, a chart library and an editor in your main bundle serve a fraction of visits. How to move them behind the click that needs them.
What Third-Party Scripts Actually Cost You
A tag manager, a chat widget and two analytics scripts can outweigh your entire application. How to measure the damage and what to do about each one.
Field Data vs Lab Data: Which Number Do You Trust?
Lighthouse says 98 and Search Console says the page is failing. Both are right. Here is what each measurement is for and which one decides.
Images Are the Performance Problem
Format, dimensions, the sizes attribute nobody sets, and why build-time optimisation beats an on-demand service for most sites.
Bundle Splitting That Actually Changes the Number
Splitting moves bytes around; it does not remove them. What to split, what to delete instead, and why the shared chunk grows quietly.
Cloudflare Pages or Vercel: Deciding by What You Deploy
Both serve static files fast. The decision is about runtime, framework fit and what happens when the bill scales — not about which edge is closer.
Getting CLS to Near Zero by Reserving Space
Every shift is something arriving into space nobody reserved. Aspect ratios, font metrics, and the banner that pushes the page down mid-read.
Core Web Vitals in Next.js: The Handful of Changes That Move the Number
LCP is usually one image, INP is usually one handler, and CLS is usually one element with no reserved space. Fixing those beats a rewrite.