We preach small software, so it was awkward to notice that our own homepage had quietly become
the opposite. The page looked light — a headline, two product cards, some cartoon trolls — but
under the hood it was shipping 312KB of JavaScript, and the very first thing that JavaScript
did was reveal the page. Until it loaded, parsed, and ran, the headline sat in the
HTML at opacity: 0. Twenty-three elements, including the biggest one on the
screen, invisible by default.
Turn off JavaScript and our homepage was a beige void with a navigation bar. On a slow connection it was that same void, just temporarily. We had built a fast static site and then hidden it behind the slowest thing on the page.
How sites end up like this
Nobody decides to hide their headline. It happens one reasonable choice at a time. You want a little polish, so you reach for an animation library. The library animates things in, which means everything starts out — opacity zero, twenty pixels low. The animation runs in JavaScript, so the starting state ships in the HTML and the finished state only exists after hydration. Each section copies the pattern from the last one. Every individual step made sense; the sum was a page that didn’t exist until the framework said so.
The cost isn’t hypothetical. The headline is the page’s largest paint, the thing performance tools measure everything by. Search crawlers that don’t run scripts saw the void. Readers on hotel Wi-Fi saw it too, for seconds at a time. And all of it bought us nothing — the finished page looked identical to one that could have just… been there.
The rebuild: same motion, no dependency
So we rebuilt the homepage with one rule: the finished page is the default, and motion is a courtesy on top. Everything else followed from that.
The hero’s staggered entrance is now pure CSS — a keyframe and four animation delays. The
scroll reveals further down the page are driven by about twenty lines of inline script and an
IntersectionObserver. Crucially, the “hidden” starting states only apply when a
tiny inline script has flagged that JavaScript is actually running. No script, no hiding:
crawlers, readers with scripts disabled, and anyone who prefers reduced motion get the complete
page in the raw HTML. The little Gantt chart still draws its bars when it scrolls into view;
the trolls still wiggle when you poke them. The contact form is a plain HTML form that posts
without JavaScript and gets politely upgraded when it’s available.
Client-side JavaScript on the homepage after the rebuild: zero bytes. Not “less.” Zero. The animation library, the UI framework, the hydration step — all of it turned out to be scaffolding we could take down once we asked what the page actually needed.
What we gave up
Honestly? Almost nothing. The one real trade is that the CSS animations are simpler than the physics-based ones the library offered — an ease-out curve instead of a spring. We looked at the two side by side and couldn’t defend the difference costing what it cost. If a future feature genuinely needs client-side state, we’ll pay for JavaScript where it earns its keep, on that feature, and nowhere else.
Why a two-product studio bothers
This is the same argument we make in defense of small software, pointed at ourselves. A tool should be judged by how quickly it lets you leave with what you came for — and for a studio homepage, what you came for is to find out what we make and whether we’re any good. Every kilobyte between you and that answer is scope we added for us, not for you.
The fastest page isn’t the one with the cleverest loading strategy. It’s the one that’s already there when you arrive.