From 3.3 MB to 180 KB, the image diet behind a fast landing page

A premium product needs big, beautiful photos, and a paid-traffic page needs to load on a phone in a basement car park. A small Node pipeline that gets you both.

27 Oct 2026 2 min readCase study · Luxury home-automation landing page

The problem

The ads landing page carried 3.3 MB of photos.

The solution

A sharp pipeline: WebP, exact display sizes and lazy loading.

−94%image weight
1.77 MB → 35 KBhero image
32lazy-loaded images

Luxury sells on photography. A premium home-automation brand can’t use small, muddy images. But people arrive at an ads landing page on phones, often on patchy mobile data, and every extra second on a slow load loses some of them.

The question wasn’t “big images or fast page”. It was how to serve images that look big without weighing much.

Where the weight was

The source folder was what you’d expect from a design team: camera exports and renders of up to 16–17 MB each. After a first round of compression the page still pulled about 3.3 MB of images:

Image set Before After
Hero 1,772 KB 35 KB
Two experience-centre photos 429 KB 53 KB
Five project photos 393 KB 73 KB
Six product cut-outs (PNG) 701 KB 22 KB

Step 1: convert

convert-webp.js runs every source image through sharp and writes WebP at quality 82. At that setting I couldn’t see a difference on a phone, and the files are a fraction of the size. Product cut-outs that had been huge transparent PNGs gained the most.

Step 2: resize to the layout, not the camera

Most of the waste wasn’t compression; it was pixels nobody sees. A 4,000 px photo shown in a 600 px card makes the phone download and then throw away almost everything. resize-for-cdn.js crops and resizes each image to the exact size it displays at, so Lighthouse reports no wasted bytes.

Step 3: let the browser help

  • Every image goes through <picture> with WebP first and JPG or PNG as the fallback.
  • Every image has explicit width and height, so nothing jumps as it loads.
  • Everything below the fold is loading="lazy": 32 images in all.
  • The hero is preloaded with fetchpriority="high", and the CDN gets a preconnect.

What else came out of the critical path

  • An icon font was replaced with a handful of inline SVGs.
  • The web font loads asynchronously, and the theme CSS is inlined.
  • The tag manager waits for the first interaction, or a timeout, before loading.

Result

The images went from about 3.3 MB to about 0.18 MB, 94% lighter, with no visible loss on a phone. The page still looks like a luxury brand; it just doesn’t make visitors pay for it in mobile data.

More problems, more solutions.

All posts

Non-brand clicks are the SEO number that matters

+183% non-brand clicks

A path-traced showroom in a TV browser

22 renders, path-traced offline in about 2 hours