How we cut our homepage from 4 MB to 179 KB and reached Lighthouse 100
Two PNG images made up almost all of quantumines.com's 4 MB homepage. Serving them as AVIF and WebP at the size each screen needs cut the page to 179 KB and the mobile Largest Contentful Paint (LCP) from about 17 seconds
Two PNG images made up almost all of quantumines.com's 4 MB homepage. Serving them as AVIF and WebP at the size each screen needs cut the page to 179 KB and the mobile Largest Contentful Paint (LCP) from about 17 seconds to 1.8 seconds. Self-hosted fonts with size-matched fallbacks, two colour fixes and an accessible-name fix took the remaining Lighthouse scores to 100. We made all of these changes on 10 November 2026 in one commit. This write-up lists each one, with the code, so another small team can repeat it in an afternoon.
Where did the 4 MB come from?
The network list in Lighthouse and Chrome DevTools answered that quickly. The homepage loaded a 2.0 MB PNG for the hero sculpture and a 2.1 MB PNG for the product artwork, both exported straight from a design tool at full quality. Everything else on the page, HTML, CSS, JavaScript and icons, was small. A 1.6 MB logo PNG was also referenced from our structured data, though not displayed.
On a phone over a throttled mobile connection, which is what Lighthouse simulates, two megabytes take many seconds to arrive. And because the hero is the largest thing on screen, it is the element LCP measures: until it finishes, the page counts as not loaded.
quantumines.com homepage before and after (Lighthouse mobile, 10 November 2026)
| Measure | Before | After |
|---|---|---|
| Total page weight | about 4 MB | 179 KB |
| Largest Contentful Paint (mobile) | about 17 s | 1.8 s |
| Accessibility score | 96 | 100 |
| All four Lighthouse categories | not all 100 | 100 / 100 / 100 / 100 |
| Cumulative Layout Shift | not recorded | 0 |
Step 1: serve images as AVIF and WebP, at the right size
We exported each large image three times (480, 768 and 1,024 pixels wide for the hero) in AVIF and in WebP, and let the browser pick with <picture>, srcset and sizes. The 1,024-pixel hero dropped from 2.0 MB as PNG to 44 KB as AVIF; a phone downloads the 480-pixel AVIF, which is 12.5 KB.
<picture>
<source type="image/avif"
srcset="assets/hero-480.avif 480w, assets/hero-768.avif 768w, assets/hero-1024.avif 1024w"
sizes="(max-width: 760px) 100vw, 55vw">
<source type="image/webp"
srcset="assets/hero-480.webp 480w, assets/hero-768.webp 768w, assets/hero-1024.webp 1024w"
sizes="(max-width: 760px) 100vw, 55vw">
<img id="hero-image" src="assets/hero-1024.webp"
alt="Sculpture of mint metal, glass and textured stone"
width="1024" height="1280" fetchpriority="high">
</picture>
Three details matter. The width and height attributes let the browser reserve the space before the image arrives, so nothing jumps. fetchpriority="high" tells it to fetch the LCP image before other images. And the hero is never lazy-loaded: lazy loading the largest image on screen delays exactly the thing LCP measures. The product artwork, further down the page, got the same AVIF and WebP treatment at 768 and 1,536 pixels.
The 1.6 MB logo in our Organization schema was replaced with a 512-pixel PNG of 137 KB. Search engines don't need more than that, and it no longer turns up in audits.
Step 2: self-host the fonts and stop the text from jumping
The site used Manrope and DM Sans from Google Fonts. That meant a render-blocking stylesheet request to another domain, then the font files from a third. We downloaded the variable versions of both (they are under the SIL Open Font License), serve them as WOFF2 from our own domain and preload them:
<link rel="preload" href="/fonts/manrope-var.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="/fonts/dm-sans-var.woff2" as="font" type="font/woff2" crossorigin>
With font-display: swap, text appears at once in a fallback font and switches when the web font arrives. The switch can move text, because Arial is wider or taller than the real font. So we defined fallback faces measured against Arial, with size-adjust and the ascent and descent overrides, and listed them right after the real font:
@font-face {
font-family: 'Manrope Fallback';
src: local('Arial'), local('Liberation Sans'), local('Helvetica');
size-adjust: 94.9%;
ascent-override: 112.4%;
descent-override: 31.6%;
line-gap-override: 0%;
}
--display: 'Manrope', 'Manrope Fallback', sans-serif;
Together with the image dimensions, this is why Cumulative Layout Shift is 0.
Step 3: fix the last accessibility points
Accessibility was at 96. Lighthouse flagged two things. Some muted text in the light theme was below the 4.5:1 contrast ratio that WCAG requires for normal text, so we darkened those colours until each passed. And the mobile menu button's accessible name didn't match its visible label "Menu", which confuses people who use voice control: they say what they see. Making the name match the label fixed it. Both changes took minutes; finding them is what the audit is for.
Step 4: cache by file type
Our Node server sets Cache-Control from the file extension. Fonts never change under the same name, so browsers may keep them for a year. Images can be kept for a week and refreshed in the background. HTML, CSS and JavaScript are checked again after an hour, so a deploy shows up quickly:
ext === '.woff2' ? 'public, max-age=31536000, immutable'
: /^(\.avif|\.webp|\.png|\.jpe?g|\.svg|\.ico)$/.test(ext)
? 'public, max-age=604800, stale-while-revalidate=86400'
: 'public, max-age=3600'
Step 5: make the next page feel instant
Two newer browser features cost a few lines each. Speculation Rules tell Chrome to prefetch a same-site page when the visitor hovers over its link, so the click usually lands on a page that is already downloaded. We exclude anything with side effects or private data, such as log-in, the app, admin pages and the API:
<script type="speculationrules">
{"prefetch":[{"source":"document","where":{"and":[
{"href_matches":"/*"},
{"not":{"href_matches":["/login","/app/*","/admin/*","/api/*","/logout"]}}
]},"eagerness":"moderate"}]}
</script>
Cross-document view transitions add a short cross-fade between pages with one CSS rule, turned off for people who ask their system for reduced motion:
@view-transition { navigation: auto; }
@media (prefers-reduced-motion: reduce) {
@view-transition { navigation: none; }
}
Browsers that don't support either feature ignore them, so there is no downside for anyone.
How do we keep it at 100?
Scores drift as pages are added. Every time the site is rebuilt, we run Lighthouse on the homepage, the newest post and one product page, and fix anything below 95 before it goes live. New images must be AVIF or WebP with width, height and srcset. Each page's preview image for social media is generated at build time, so nobody uploads a multi-megabyte PNG by hand. The same discipline carried over to adding WebMCP for AI agents: the site still scores 100 in all four categories with it.
What would we tell another small team?
- Open the network list before touching code. On most small sites one or two images are most of the weight.
- Fix the LCP image first: modern format, right size,
fetchpriority="high", never lazy. - Give every image width and height, and give web fonts a size-matched fallback. That is most of CLS.
- Treat accessibility warnings as bugs. They are usually quick to fix and they affect real people.
- Re-run the audit on every build, not once a quarter.
Frequently asked questions
Is AVIF supported in all browsers?
AVIF works in current versions of Chrome, Edge, Firefox and Safari. The <picture> element falls back to WebP and then to the <img> source, so older browsers still get an image.
What is a good Largest Contentful Paint?
Google's Core Web Vitals treat an LCP of 2.5 seconds or less as good, measured at the 75th percentile of real page loads. quantumines.com's homepage measures 1.8 seconds in Lighthouse's mobile test.
Does a Lighthouse score of 100 guarantee good Core Web Vitals?
No. Lighthouse is a lab test on one simulated device. Core Web Vitals in Search Console come from real visitors' browsers. A high lab score makes good field data likely, but the field data is what Google uses.
Quantumines is a technology and product studio in Lahore, Pakistan, founded by Muhammad Ali Raza (Ali Arbi). We build websites and web apps for clients with the same standards; see our services.
Originally published on quantumines.com.
Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.