Get an AI receptionist

Digital Storming
Back to Blog

Websites

How We Got Our Site to 100 in Lighthouse (and How to Speed Up Yours)

How to improve website speed, from a real rebuild: what got our pages to 100 in Lighthouse, what didn't, and how to apply it on WordPress or Shopify.

By Angel Lord, Web Design Lead11 min read

Developer in a plaid shirt typing at a desk with code on a large monitor and a second laptop beside a mechanical keyboard

Most advice on how to improve website speed is a list of tips with no numbers attached. This is the other kind: one real site, every page measured, and what each change did.

We rebuilt digitalstorming.com in 2026 as a static site with Astro, Tailwind CSS and a small amount of JavaScript for smooth scrolling, menus and forms. It went live on October 9, 2026, served from our own Apache server with HTTP/2 and gzip. Then we tested every page and fixed what the tests found.

Below is what moved the score, what fooled us, and where we stopped short of 100. The last big section turns each lesson into steps you can apply on WordPress, Shopify or anything else.

Two things up front. We didn’t change the design to chase the score, lower photo quality, or remove our web font. And not every page reached 100 on a phone. Four didn’t, and we’ll show you why.

How we tested

We ran Lighthouse 13.5 on every page we could test, which was 59 pages (Lighthouse can’t test a 404 page), with both the phone and desktop profiles. Lighthouse 13 also adds an “Agentic Browsing” category, scored as a fraction of the checks that apply: an accessibility tree an AI agent can use, layout stability, and an llms.txt file.

Speed work can quietly break a layout, so we checked that too. Before and after the changes, a script compared every element’s position and size, plus a full-page screenshot, on all 60 pages at 390 px and 1440 px wide. The result: no layout changes anywhere. Pixel differences were under 0.003%, which is image-codec rounding.

What does a Lighthouse score actually measure?

Short answer: Lighthouse’s performance score is a weighted mix of five lab metrics: Total Blocking Time (30%), Largest Contentful Paint (25%), Cumulative Layout Shift (25%), First Contentful Paint (10%) and Speed Index (10%). A score of 90 to 100 counts as good.

Those weights come from Chrome’s Lighthouse scoring documentation, and they tell you where to look first. Total Blocking Time is the biggest single slice: the time the page is too busy running scripts to respond. Largest Contentful Paint is when the main content, usually the headline or hero image, appears.

Lighthouse is a lab test. By default it simulates a slow connection (150 ms of latency and 1.6 Mbps download) and a 4x CPU slowdown to imitate a mid-range phone. Real visitors are measured separately: Google’s Core Web Vitals count a page as good when, at the 75th percentile of visits, LCP is 2.5 seconds or less, Interaction to Next Paint is 200 ms or less and CLS is 0.1 or less. PageSpeed Insights shows that field data, from the previous 28 days of Chrome users, above its lab score when your site has enough traffic.

Lesson 1: check the test before you trust the score

Our first full run showed some pages at 97 to 98 with a Speed Index around 3.7 seconds, while others scored 100. It looked like a real problem on certain pages.

The cause was our test script, not the site. On Windows, it launched Lighthouse through a shell that split the Chrome flags into separate arguments, so Chrome lost the flags that stop background-window throttling. Frames were then randomly delayed by about 2 seconds. Once the script passed the flags correctly, the same pages painted in about 0.4 seconds every time.

The takeaway is to doubt a surprising result before you act on it. Run Lighthouse several times, compare its “observed” and “simulated” numbers, and check the page in PageSpeed Insights, which runs on Google’s own machines.

Tip: Lighthouse’s own variability guide says the median score of 5 runs is twice as stable as a single run. Run one test at a time, close other heavy programs, and use a browser profile without extensions.

Images: from WebP to AVIF without losing quality

Next came the photos. We converted all 424 stock photo files, 212 photos at 1600 and 800 px wide, to AVIF. We converted from the original downloads, not from our WebP files, so nothing was compressed twice.

The quality rule was strict. Each AVIF was kept only if it was smaller and at least as close to the original as the WebP. “Close” here means SSIM, a measure of visual similarity, scored against the original. All 424 passed, and the set went from 32.0 MB to 21.4 MB, 33% smaller.

Logos and blog screenshots got the same check at build time: 199 AVIF copies, from 3.15 MB to 2.2 MB, or 30% smaller. Five files were left as they were because AVIF wasn’t at least 10% smaller. Animated images are skipped entirely: converting an animated WebP to AVIF kept only its first frame, and the visual comparison caught it.

Delivery uses a <picture> element with an AVIF <source> and the WebP <img> as the fallback, so browsers without AVIF get WebP. That’s the pattern MDN recommends, since AVIF support only arrived in Safari 16.1 and Edge 121. On the phone profile, the homepage’s total transfer fell from 296 KB to 214 KB.

Watch out: Wrapping an image in <picture> can change a flex layout. In our photo strip, each <source> became an empty flex item and added a 20 px gap, which the visual check caught. The fix was picture { display: contents } plus picture > source { display: none }.

Close-up of a man in a blue button-down shirt with a bag strap holding a smartphone outdoors, screen turned away from view

The main thread: stop measuring the page while it loads

Total Blocking Time carries the most weight in the score, and on our pages the main-thread problem was forced layouts. When a script asks for a size or scroll position, the browser has to calculate the page’s layout right then, instead of once at its normal time. Google’s guide to layout thrashing explains the mechanics.

We found three versions of this:

  1. Measuring during load. A header script read scrollY the moment it loaded, which forced Chrome to lay out the whole homepage before the first paint, about 131 ms of work. Wide tables were also measured while the page was still being parsed, costing up to about 170 ms on a long guide. The fix: start at 0 and measure only after the first paint, using requestAnimationFrame plus setTimeout.
  2. Libraries measuring at start-up. The smooth-scroll library and two carousels read sizes as soon as they started. They now start after the first paint. The carousels’ “previous” buttons start disabled in the HTML, so the first frame is already correct.
  3. The result. Homepage Total Blocking Time on the phone profile fell from about 230 ms to under 60 ms in our runs.

Largest Contentful Paint: keep decoration out of the way

Our LCP fixes were all about things that downloaded or rendered before the headline painted. Three changes mattered:

  • Gallery photos below the headline. On the homepage, the photos under the headline were set to load immediately, so on a phone they downloaded before the headline painted. That included cards hidden on phones, which still downloaded. Making them lazy-load cut the photos fetched before the headline from 5 (147 KB) to 3 (71 KB), and Lighthouse’s LCP estimate fell from about 2.0 s to 1.5 s.
  • Decorative photo columns on landing pages. These purely decorative photos drift upward next to the headline. They now load just after the first paint, and phones get a 400 px copy instead of the 800 px one, about 13 KB instead of 26 KB as AVIF. LCP estimates on those pages fell from 2.0 to 2.2 s to between 1.2 and 1.7 s.
  • Long articles. Paragraphs and headings far below the screen use content-visibility: auto, which lets the browser skip laying them out until they come near the screen. That cut the first layout of a very long blog post from about 55 ms to about 22 ms.

Caching: the rule that never matched

We had an Apache rule meant to cache the site’s hashed scripts for a year. It never matched. FilesMatch sees only file names, not folders, as the Apache documentation describes, so the rule never applied and the scripts were never cached.

The fix was <LocationMatch "^/_astro/"> with Cache-Control: public, max-age=31536000, immutable, which is what Google’s HTTP cache guide recommends for files whose names change whenever their content does. We also added .avif to the 30-day image cache rule, since the new format wasn’t covered.

Did every page score 100?

Short answer: On desktop, yes: 100 in performance, accessibility and best practices on all 59 testable pages. On a phone, performance reached 100 on 55 of 59 pages; four pages scored between 96 and 98.

Here are the full results from local Lighthouse 13.5 runs on October 12, 2026:

Profile Performance Accessibility and best practices SEO
Desktop 100 on all 59 pages 100 on all 59 pages 100 on every page meant for search
Phone 100 on 55 of 59 pages 100 on every page meant for search 100 on every page meant for search

Agentic Browsing scored 3/3 on every page, on both the phone and desktop profiles. Pages we deliberately mark noindex, such as internal and utility pages, score lower on SEO because Lighthouse flags noindex. That’s by design.

Of the four phone pages at 96 to 98, two have native dropdowns (<select>), one of them with 11, and one is a very long article. On our Windows test machine, the first layout of a native <select> cost about 90 ms, even when empty, and text laid out before the web font arrives costs extra too. We haven’t confirmed how much of this shows up on PageSpeed Insights’ Linux machines.

Our take: A 97 with working native dropdowns and a readable web font beats a 100 without them. Taking those out would make the pages worse for people to gain a point or two, and Google’s own page experience guidance says that trying to get a perfect score just for SEO reasons “may not be the best use of your time.”

How to improve website speed on your own site

None of this needs a static site. The same ideas work on WordPress, Shopify and most builders, usually through settings, a theme fix or a plugin rather than a rebuild. Work through them in this order, because the first steps usually pay the most.

Step 1: Measure with real-visitor data first

Open PageSpeed Insights, enter your homepage and your busiest page, and look at the field data at the top before the lab score. If it’s missing, your site doesn’t have enough Chrome traffic yet, so rely on the lab test. Run Lighthouse five times and use the median. This takes about 15 minutes and costs nothing.

Step 2: Get your LCP element loading first

Find the LCP element in the Lighthouse report. If it’s an image, it must not be lazy-loaded; Google’s lazy-loading guide is blunt about that. Add fetchpriority="high" to it, which current Chrome, Edge, Firefox and Safari all support; Google cites a Google Flights test where it improved LCP from 2.6 s to 1.9 s.

  • WordPress: since 6.3, WordPress adds fetchpriority="high" to the image it judges most likely to be the LCP and lazy-loads images further down. Check that a slider or page builder hasn’t overridden it.
  • Shopify: the image_tag filter loads images eagerly in sections 1 to 3. Shopify’s theme guidance says to never lazy-load the LCP image, and that includes JavaScript lazy loaders.

Step 3: Lazy-load everything below the first screen

Add loading="lazy" to images further down the page. Watch for images hidden on phones, such as desktop-only cards: hidden doesn’t mean skipped, and ours were still downloading.

Step 4: Serve AVIF or WebP at the size the screen needs

According to MDN, lossy AVIF files are around 50% smaller than JPEGs and lossy WebP 25 to 35% smaller at similar quality. Size matters as much as format, so phones should get a smaller copy.

  • WordPress: since 6.5 you can upload AVIF if your server’s image library supports it; check under Tools > Site Health > Info > Media Handling. Core doesn’t convert existing images or pick a format per browser, so use a plugin or image CDN for that. The WordPress Performance Team’s Performance Lab includes a Modern Image Formats feature, though the team calls it a beta-testing plugin.
  • Shopify: the CDN picks the format each browser supports, as long as your theme builds image links with the image_url filter. Hand-built image URLs skip that.

Step 5: Reserve space so nothing jumps

Give every image and video width and height attributes, reserve space for embeds and ads, and keep late banners from pushing content down. Google’s CLS guide also covers web fonts: a fallback font with matching metrics stops text from reflowing when the real font arrives.

Step 6: Keep scripts from blocking the page

Chat widgets, sliders, trackers and tag managers are the usual culprits. Remove what you don’t use and load the rest after the page appears. Chrome DevTools’ Performance panel has a Forced reflow insight that names the functions measuring the page too early. On a phone profile, Lighthouse counts 0 to 200 ms of Total Blocking Time as fast.

Step 7: Cache static files for a year

Open DevTools, go to the Network tab, click a script or image, and read its Cache-Control header. Files with a version or hash in the name can be cached for a year with immutable; HTML should use no-cache so visitors get updates. Don’t assume a caching rule works because it’s in the config; ours didn’t match until we checked the headers. A good host, or a plugin on WordPress, can set these for you.

Step 8: Let the browser skip work on long pages

For long articles and guides, content-visibility: auto with a contain-intrinsic-size lets the browser skip rendering what’s far off-screen. Google’s content-visibility article notes it reached all three major browser engines in September 2025.

What to do this week

  1. Run PageSpeed Insights on your homepage and busiest page, and write down the field data and the LCP element.
  2. Make sure your LCP image isn’t lazy-loaded and has fetchpriority="high".
  3. Lazy-load everything below the first screen, including images hidden on phones.
  4. Check the caching headers on your scripts and images in DevTools.
  5. List every third-party script on the site and remove one you don’t need.

Speed sits alongside the other basics we covered in our website accessibility checklist and our guide to what a small business website costs. If you’re choosing a store platform, our Shopify vs WooCommerce comparison covers speed too. If you’d rather hand it off, our web development team builds and tunes sites, and our web hosting page lists the plans we run.

Frequently asked questions

Does a 100 Lighthouse score improve Google rankings?

Not directly. Google says Core Web Vitals, measured from real visitors, are used by its ranking systems, but it also says Search always seeks to show the most relevant content, even if the page experience is sub-par. Lighthouse is a lab diagnostic: use it to find what slows people down, not as a ranking target.

Why does PageSpeed Insights give a different score from Lighthouse in my browser?

PageSpeed Insights runs Lighthouse on Google's hardware in a data center in North America, Europe or Asia, while a local run uses your computer, network, extensions and antivirus. Lighthouse's documentation lists all of these as sources of variability and suggests treating performance as a distribution of scores rather than one number.

Is AVIF better than WebP?

For photos it usually compresses better: MDN cites a median of about 50% savings for AVIF versus about 30% for WebP on the same set of JPEGs. AVIF doesn't render progressively and has less history in browsers, so serve it with a WebP or JPEG fallback inside a picture element.

What's the difference between Total Blocking Time and INP?

Total Blocking Time is a lab metric: Lighthouse adds up the part of every task longer than 50 ms between First Contentful Paint and Time to Interactive. Interaction to Next Paint is measured from real visitors' clicks, taps and key presses, and Google counts 200 ms or less as good. Cutting long JavaScript tasks helps both.

What is the Agentic Browsing category in Lighthouse 13?

It's a newer Lighthouse category scored as a fraction of the checks that apply to the page, such as whether an AI agent can use the page's accessibility tree, whether the layout stays stable, and whether the site has an llms.txt file. Our pages scored 3 out of 3 on both the phone and desktop profiles.

Sources

Every figure in this article comes from these pages; we checked each one on the date shown.

  1. Lighthouse performance scoring. Chrome for Developers. Checked .
  2. Total Blocking Time. Chrome for Developers. Checked .
  3. Web Vitals. web.dev (Google). Checked .
  4. About PageSpeed Insights. Google for Developers. Checked .
  5. Lighthouse variability. GoogleChrome/lighthouse on GitHub. Checked .
  6. Network throttling and CPU throttling. GoogleChrome/lighthouse on GitHub. Checked .
  7. Image file type and format guide. MDN Web Docs. Checked .
  8. Browser-level image lazy loading for the web. web.dev (Google). Checked .
  9. Optimize resource loading with the Fetch Priority API. web.dev (Google). Checked .
  10. content-visibility: the new CSS property that boosts your rendering performance. web.dev (Google). Checked .
  11. Avoid large, complex layouts and layout thrashing. web.dev (Google). Checked .
  12. Optimize Cumulative Layout Shift. web.dev (Google). Checked .
  13. Prevent unnecessary network requests with the HTTP Cache. web.dev (Google). Checked .
  14. Apache Core Features (Files, FilesMatch). Apache HTTP Server Project. Checked .
  15. Image performance enhancements in WordPress 6.3. Make WordPress Core. Checked .
  16. WordPress 6.5 adds AVIF support. Make WordPress Core. Checked .
  17. Performance Lab. WordPress.org Plugins. Checked .
  18. image_url filter. Shopify.dev. Checked .
  19. Never lazy load the LCP image. Shopify.dev. Checked .
  20. Understanding page experience in Google Search results. Google Search Central. Checked .

Question about this article?

Send it to our team and we’ll reply by email within one business day. Questions aren’t published on this page.

We use your email only to reply. See our Privacy Policy.

Fast, mobile-first websites on WordPress, Shopify or custom code, built to turn visitors into calls and enquiries.

WordPress and cPanel hosting with one-click WordPress installs and an easy cPanel dashboard.

Tell us what you need

Send a short note about your business and what you want to achieve.

Mon–Sat, 9:00 AM – 6:00 PM ET · We reply within one business day