Move the headline sweep onto the compositor, and the chat widget off load

Performancekamo-marketing
Shipped
August 19, 2026 at 6:55 PM UTC
Author
Kamo
Commit
e504993

Two things left over from the last round, both flagged rather than done because each trades something. Doing them now. THE HEADLINE'S LIGHT PASS. It was a second background layer on the type block, moved by animating `background-position` — a paint property, so every frame ran on the main thread, on the page's LCP element. It was also the largest single contributor to Lighthouse's non-composited animation count, and there is no way to slide a gradient across glyphs directly: `background-clip: text` only ever clips an element's own background to its own text, so the gradient and the letters are the same object. So the band moves as an element instead. An overlay repeats the sentence in olive; a static mask cut to the old gradient's shape — same 120°, same 44%–56% stops — slides across it, while the overlay's inner span slides the opposite way by the same percentage of the same width. The two cancel exactly at every instant, because both animations carry the same duration, delay and easing, so the letters never move and only the lit band crosses them. Both are transforms. Non-compositable keyframes are down from 10 to 8. The resting fill is now the only thing painted on the type block itself, which also means the headline's first paint — the LCP paint — involves no animation at all. The repeated sentence is `aria-hidden`, so it stays out of the accessibility tree, and `user-select: none`, so copying the headline yields it once rather than twice. THE CHAT WIDGET. `lazyOnload` was already as far as next/script can defer anything: after the load event. Not far enough. It is 142 KB of JavaScript, 45 KB over the wire, and Lighthouse measured 23 KB of it unused on arrival — all parsed and executed inside the window that decides Total Blocking Time, for a bubble in the corner nobody has asked for yet. It now waits for a sign that someone is actually there: pointerdown, pointermove, keydown, touchstart, scroll or wheel, all passive and `once`, so the listeners can never delay the very scroll that triggers them. A reader who touches nothing still gets it after eight seconds. That eight seconds is the trade, and it is worth being explicit about it: a genuinely passive visitor sees the chat bubble later than they used to. In practice a scroll or a pointer move inside the first second or two is the normal case and loads it immediately — but this is a product decision as much as a performance one, and it is reversible by deleting the gate.

All changes

Like what you see shipping?

Every one of these updates lands in your workspace automatically. Start free and watch it grow week after week.

Start Free ForeverView Pricing