Skip to content

Performance

Astro Components Without the Hydration Tax — Stop Shipping React for a Marquee

Zero-JS by Default, an Island Only When the Component Earns It
Written by Aiden Wood Founder and Lead Design Engineer
🚀 🏝️ 0️⃣

Search "Astro component library" and you'll mostly find React libraries wearing a trench coat: every component a client:load island, every page paying React's runtime for a card that never re-renders. That's not an Astro library. That's a React app with extra build steps.

The maths is blunt. A hydrated island carries the component's JS, its share of the framework runtime, and a hydration pass on the main thread. For a hero, a pricing table, a logo ticker — things that render once and sit there — that cost buys you nothing.

The Setup

Velocity X ships both species and labels them honestly: .astro components that compile to pure HTML and CSS, and React components for the surfaces that genuinely need client state. The framework is stated on every component page, so you know the bill before you install.

velocityx add logo-ticker        # .astro — zero client JS
velocityx add standard-command-palette  # react — earns its island

(CLI in preview, not on npm yet — the free tier's source is public on GitHub meanwhile.)

The Money Pattern

The trick most ports miss: animation doesn't require hydration. A marquee, an accordion, a carousel snap — CSS owns all of it. An infinite logo ticker is a keyframe and a duplicated track, not a useEffect:

<div class="overflow-hidden">
  <div class="flex gap-12 animate-[ticker_30s_linear_infinite]">
    <slot />
    <slot /> <!-- duplicate track = seamless loop -->
  </div>
</div>

@keyframes ticker {
  to { transform: translateX(-50%); }
}

Rendered once at build time. Zero JavaScript shipped. The browser's compositor runs the animation off the main thread — smoother than the React version, not just lighter.

The Catch

Some components do earn an island: a command palette needs keyboard state, a bottom sheet needs drag physics, a data table needs sorting. The failure mode isn't "using React" — it's using React by default, so the 90% of components that are static pay for the 10% that aren't.

The other trap is client:load when client:visible or client:idle would do. If an island is below the fold, hydrating it before first paint is self-sabotage.

The Verdict

Astro's whole bet is that most of a page is static — and most of a page is. A component library that respects that ships .astro when it can and an island when it must. That's the split across Velocity X's 400+ components, framework declared per component, 40 of them free to try: the full index is even readable by your AI assistant.

Let us make some quick suggestions?

Please provide your full name.
Please provide your phone number.
Please provide a valid phone number.
Please provide your email address.
Please provide a valid email address.
Please provide your brand name or website.
Please provide your brand name or website.