Astro
Astro is a web framework built on a contrarian premise: most websites ship far too much JavaScript. Astro renders everything to plain HTML at build time (or on the server) and ships zero JS by default — then lets you opt individual components back into interactivity as islands, each hydrating independently.
The result dominates its niche: content-heavy sites — marketing pages, blogs, documentation, e-commerce landing pages — where Astro sites routinely post near-perfect Core Web Vitals scores that SPA-based stacks struggle to match. Its second trick is framework-agnosticism: the same Astro site can render React, Vue, and Svelte components side by side.
TL;DR
- Zero JS by default: components render to HTML; the browser gets markup, not a framework runtime.
- Islands architecture:
client:load/client:visible/client:idledirectives hydrate only the components that need interactivity, independently. .astrocomponents = JSX-like templates with a frontmatter script that runs at build/server time —awaityour CMS fetch right in the component.- Content collections turn folders of Markdown/MDX into type-checked, queryable data — the best-in-class blog/docs workflow.
- Bring your framework: React, Vue, Svelte, Solid, Preact components all work, even mixed on one page.
- Static by default; SSR adapters (Vercel, Netlify, Node, Cloudflare) add server rendering per route when needed.
Quick Example
An .astro page — server-side data fetching in frontmatter, one interactive island:
Everything renders to HTML; the only JavaScript shipped is the cart widget's — and only when it scrolls into view.
Core Concepts
Islands Architecture
A traditional SPA hydrates the whole page; Astro inverts it — static HTML sea, interactive islands:
The client:* directive controls when each island's JS loads:
No directive → the component renders to HTML and ships no JavaScript at all, even if written in React.
.astro Components
The frontmatter (between --- fences) is server-only JavaScript/TypeScript: fetch data, read files, query a database — with top-level await and zero client cost. The template below is HTML-plus-expressions (JSX-ish, but closer to HTML: class not className), with automatically scoped <style> blocks and named <slot>s for composition.
Content Collections
Astro's flagship feature for content sites — Markdown with a schema:
Frontmatter is validated at build time (a typo'd date fails the build, not production), queries are type-safe, and loaders can pull from CMSes and APIs, not just local files.
Rendering Modes
- Static (default) — every page prerendered at build; deploy to any CDN. Right for most content.
- Server (SSR) — an adapter (Node, Vercel, Netlify, Cloudflare) renders per request; opt pages out with
export const prerender = true, mixing static and dynamic in one site. - Actions & endpoints — type-safe server functions and API routes for forms and JSON, so a mostly-static site can still handle submissions without a separate backend.
Astro vs Next.js (and Friends)
The honest split: if the product is an application (dashboards, auth'd flows, heavy client state), Next/Remix/SvelteKit fit better. If it's a site — where content dominates and interactivity is islands, not oceans — Astro's defaults are simply correct, and the performance gap is structural, not tuning.
Common Mistakes
client:load on Everything
Sprinkling client:load on every component rebuilds the SPA you were escaping. Default to no directive; add the laziest directive that works (client:visible for anything below the fold).
Expecting Frontmatter to Run in the Browser
Frontmatter executes at build/server time only. onClick handlers in an .astro template don't hydrate — interactivity needs a framework island or a plain <script> tag (which Astro bundles but doesn't scope to a component lifecycle).
Sharing State Across Islands the Hard Way
Islands are independent — no shared React tree, so no context between them. The idiomatic bridge is nano stores (tiny framework-agnostic atoms) — a React island and a Svelte island can subscribe to the same store.
Treating Astro as a React Framework
Astro renders React components, but hooks/context/portals only exist within an island. Architect the page as HTML-first with islands, not as a React app hosted in Astro.
FAQ
Is Astro only for static blogs?
No — SSR adapters, middleware, actions, and API routes make full dynamic sites (storefronts, docs with auth, dashboards-lite) practical. But its advantage is largest where content dominates; for heavily stateful apps, an app framework fits better.
Which UI framework should I use inside Astro?
Whichever you know — or none: .astro components plus a sprinkle of vanilla <script> covers a surprising amount. Mixing is genuinely supported (e.g. keep legacy React widgets while writing new islands in Svelte), which also makes Astro a pleasant migration vehicle.
How does Astro compare to Eleventy or Hugo?
Same zero-JS output philosophy, but with a component model, TypeScript, scoped styles, and the option of islands/SSR when you outgrow pure static. Hugo still wins on raw build speed for huge sites; Astro wins on developer experience and an escape hatch to interactivity.
Does Astro do image optimization and SEO?
Yes — the built-in <Image />/<Picture /> components handle resizing, modern formats, and layout-shift prevention, and full control of the HTML head makes meta tags and structured data straightforward.
What's the deployment story?
Static output deploys anywhere (Netlify, Vercel, GitHub Pages, any CDN). SSR needs the matching adapter — one npm package and a config line per platform, including Cloudflare Workers.
Related Topics
- Next.js — The React app-framework alternative
- React — The most common island framework
- Svelte / Vue — Equally first-class in Astro
- Web Performance — Why zero-JS-by-default wins
- Core Web Vitals — The scores Astro optimizes for
- Vite — Astro's underlying build tool
- SEO for SPAs — The problem Astro sidesteps entirely