skip to content
Jason Worden
Table of Contents

My homepage is about as simple as a page gets: some links, a theme toggle and scroll arrows. Until Halloween, it was also haunted by all of Bootstrap and Font Awesome, a holdover from the first version of this site, which I put up in 2014.

I spent the holiday carving it up 🎃🔪, and the biggest gains came from deleting things. In a local comparison, total transfer dropped 78%, from 144.6 KB to 32.0 KB.

The page was already fast by Lighthouse standards, at 99 on mobile locally, and the cleaned-up build scores 100. The live page scores 100 on mobile and desktop.

The body count

Three changes account for almost all of the 112.6 KB saved:

  • 🔪 Font Awesome, 83.3 KB. The page downloaded a whole icon font and its stylesheet for a few icons. Inline SVGs replaced them.
  • 🔪 Bootstrap, 21.8 KB. The classes and resets the page relied on became a few hand-written rules. Screenshots showed 0 pixels different across 24 captures.
  • 🎃 Nexa Bold, 7.5 KB. The sole survivor. It’s the same display font, carved down and served as WOFF2 with a WOFF fallback.

Bootstrap and Font Awesome were also linked over plain HTTP, so both started with a redirect to HTTPS. Killing them off took the page from five third-party requests to none.

A few smaller changes did little for bytes but improved how the page works:

  • No more scroll script. The CSS 100svh unit now sizes the sections, and the arrows are real anchor links, so they work with a keyboard and without JavaScript. This was also 0 pixels different across 24 screenshots.
  • One favicon download. Adding sizes="32x32" to the PNG icon link stops Chrome from fetching both the PNG and the SVG.
  • Fewer skeletons in the closet. Selectors from an old resume, outdated vendor prefixes, unused CSS and JavaScript files, and 8 unused images are all buried. 🪦

While I was in there, I also added prefers-reduced-motion support and cleaner focus rings. The theme is now saved only when someone actually uses the toggle.

The autopsy 🔬🩻

I ran both builds in one session, taking turns: Lighthouse 13.6.0, median of 5 runs per mode, served locally with gzip and simulated throttling.

Homepage (local, Lighthouse 13.6.0) Before After Change
Total transfer 144.6 KB 32.0 KB -78%
Requests 11 4 -7
Mobile First Contentful Paint 1557 ms 751 ms -52%
Mobile Largest Contentful Paint 1557 ms 751 ms -52%
Desktop First Contentful Paint 461 ms 201 ms -56%
Desktop Largest Contentful Paint 565 ms 201 ms -64%

Fonts went from 107.3 KB to 23.9 KB and CSS from 33.6 KB to 4.1 KB. The HTML grew from 2.4 KB to 3.5 KB, because it now holds proper metadata and the inline icons.

These are local results only. My first live measurement came after most of this work had shipped, so I have no live “before” and can’t claim a 78% drop in production.

The haunted Lighthouse 👻

Lighthouse’s performance score runs from 0 to 100 and is a weighted blend of lab metrics such as First Contentful Paint, Largest Contentful Paint and Total Blocking Time. Mobile went from 99 to 100, and desktop stayed at 100. Here’s the live homepage that evening, on the same Lighthouse version and with the median of 5 runs per mode:

Live homepage, October 31, 2026 (Lighthouse 13.6.0) Mobile Desktop
Score 100 100
First Contentful Paint 834 ms 275 ms
Largest Contentful Paint 834 ms 275 ms
Page weight 44.6 KB 44.6 KB

The About page keeps a dated table of these results, and I refresh it after big homepage changes such as adding or removing a stylesheet, script, font or large image.

The live page weighs more than the local build partly because of a ghost in the machine: the Cloudflare Web Analytics beacon, which Cloudflare injects at the edge. That extra weight is intentional, and the design is a big reason I use it: a lightweight, cookieless script that doesn’t block rendering and needs no analytics code in the site itself. The script is about 10 KB, and it sends a report back to the site’s own domain, so it adds two requests. That’s why the 4 local requests were 6 on the live page, and the page still scores 100 on mobile and desktop with it in place.

Also in this cleanup

SEO. This wasn’t about speed, but it was the same kind of work: fixing things that had quietly gone stale.

  • Social card and feeds: a generated default social card, and RSS items that link to the right place.
  • Metadata: complete homepage metadata and copy, tidier shared head tags and structured data, and article dates that come only from frontmatter.
  • Indexing: noindex for thin tag pages, and a sitemap without them.
  • Upkeep: a regression check against the build output, plus written rules for whoever touches this next.

Astro 7. I upgraded the blog to Astro 7 that evening to keep it current, and page speed stayed about the same. In local Lighthouse 12.2.1 runs, the homepage wasn’t affected and the blog index didn’t change. A post with Mermaid diagrams went from 42 to 56 requests and from 347.9 KB to 350.8 KB, and its mobile scores ranged from 92 to 99 on both builds. Desktop Largest Contentful Paint went from about 563 ms to 650 ms. I didn’t trace those extra requests or measure them on the live site.

Moving the homepage to Astro. Later, I moved the homepage to Astro so it shares metadata and theme logic with the rest of the site. Screenshots showed 0 pixels different across 8 captures. The cost was three small deferred scripts, about 1.9 KB in total, and live requests went from 6 to 9. The live figures above include this change. Locally, Lighthouse 13.6.0 runs ranged from no change to about 300 ms more mobile Largest Contentful Paint. Real throttling, in an earlier session on one machine, showed about 30 ms, so I kept the scripts.