Most marketing sites ship a full JavaScript framework runtime to the browser so it can rebuild, in memory, the exact HTML the server already sent. That step is called hydration, and visitors pay for it on the main thread of a phone that did nothing to deserve it.
Our marketing sites skip almost all of it. Pages render as server components by default, and the interactive layer is one small island of plain JavaScript. On the build where we settled this architecture, total blocking time went from 2,610 milliseconds to zero.
Server components by default
Every page renders on the server and is prerendered at build time wherever the content allows, which for a marketing site is essentially everywhere. Our builds prerender anywhere from 12 to 492 pages depending on the size of the catalog, and a prerendered page costs the visitor nothing but the HTML. Dynamic rendering exists only where something genuinely live demands it, like a product page overlaying rows from a client-edited catalog.
Client-side rendering is the exception, and it has to argue for itself. A multi-step form wizard is a fair argument. A paragraph of text is not, and neither is a card grid, a footer, or a hero.
One small island of vanilla JavaScript
Interactivity still exists, it just is not a framework concern. One island of roughly 130 to 180 lines of plain JavaScript wires the whole animation layer onto the server-rendered DOM: scroll reveals, card tilt, magnetic hovers, number count-ups. It re-initializes on every route change and touches nothing else.
Because the DOM arrives finished from the server, there is nothing to hydrate. The island observes elements and adds classes. CSS does the actual animating, on the compositor, where it belongs.
Why marketing sites rarely need an animation library
Strip away the branding and most marketing-site motion is three things: elements revealing on scroll, hover states, and small entrances. That is an IntersectionObserver and CSS transitions, both of which the browser gives you for free. An animation library re-implements what the platform already does, and bills the main thread for the privilege on every page load.
The discipline that keeps the hand-rolled version fast is specific:
- Animate compositor properties only, meaning transform and opacity. We once watched an infinite background-position loop drive total blocking time to 4,450 milliseconds by itself.
- Use one-shot observers that stop observing after they fire, so settled sections cost nothing for the rest of the visit.
- Route any scroll work through requestAnimationFrame with passive listeners, so scrolling never waits on script.
- Mark above-the-fold elements visible synchronously, so nothing flashes hidden on load.
The platform keeps absorbing more of this work. On Kwaan Bear Technology, photos settle into place using native CSS scroll timelines behind a feature-support gate: zero JavaScript runs, and the effect never activates for visitors who prefer reduced motion.
The safety contract
Hand-rolled motion earns its keep only if it fails gracefully, so every build honors the same three-part contract.
First, the site works with JavaScript disabled: reveal classes are added by the script itself, so without it everything simply renders visible. Second, reduced-motion preferences are honored in both the CSS and the JavaScript. Third, every hover effect has a defined touch-device twin, because phones have no hover.
That last one deserves an example. On Kwaan Bear Technology, cards light up as they cross the middle of the viewport, so a visitor on a phone gets the same treatment a desktop visitor gets from a mouse, instead of silently losing it.
When we do ship heavy JavaScript
Some pages earn real JavaScript: a 3D hero, an interactive map, a search palette. Those ship under strict rules. They load lazily, they gate themselves behind interaction or visibility, they clean up completely when they leave, and they never instantiate for visitors who prefer reduced motion.
On Polymer Nation, the homepage's animated hero canvas is never even downloaded by phones, low-core devices, or visitors with data saver or reduced motion enabled. The heaviest chunk on the site costs nothing to the visitors least equipped to pay for it.
What this buys
Main-thread blocking time measured at zero. Marketing builds that run on 4 to 7 runtime dependencies total. And a page that is interactive the moment it is visible, because there was never a boot phase between the two.
None of this reads as austerity, and that is the point. The sites still tilt, glow, reveal, and count up. The motion just runs where the browser is fast instead of where it is slow.
Everything heavier waits for intent. The search index loads the first time someone opens search, so visitors who never search pay zero bytes for it. The accessibility widget and cookie banner mount when the browser goes idle, after the page a visitor came for is already on screen. The phone in their hand does almost no work, which was the whole point.
