
What is Astro and why is it so fast?
Astro is an open-source web framework for building content-driven websites such as blogs, documentation, marketing sites, portfolios and online shops. It's fast because it renders your pages to plain HTML on the server, either at build time or on request, and sends no JavaScript to the browser by default. When part of a page does need to be interactive, you mark just that component as an "island" and Astro ships the JavaScript for that component alone, while the rest of the page stays as static HTML. Less JavaScript means less to download, parse and execute, which is what usually makes websites feel slow on real phones.
That one design decision explains most of Astro's reputation, but it isn't the whole story. Astro also scopes and bundles your CSS, optimises images, inlines small scripts and gives you a component language that's essentially HTML. In this article you'll learn what Astro is, how a page goes from source code to HTML, why that approach produces fast pages, what changed in Astro 6 and 7, and how the numbers look on a real build.
What Astro Actually Is
Astro describes itself as "the web framework for building content-driven websites". In practice it's three things working together:
- A component language:
.astrofiles, which look like HTML with a block of JavaScript or TypeScript at the top. They render on the server and never run in the browser. - A build tool: Astro runs on Vite (Vite 8 since Astro 7) and turns your project into a folder of HTML, CSS, JavaScript and images that any static host can serve.
- A server framework, when you need one: add an adapter for Node.js, Vercel, Netlify or Cloudflare and individual pages, API endpoints and server islands can render on demand.
Astro is also UI-agnostic. You can write interactive components in React, Preact, Svelte, Vue, Solid or Alpine, or just use web components and plain <script> tags. Most projects use one framework, but you can mix several on a single page if you need to.
The current release at the time of writing is Astro 7.4.2, and the requirements are modest: Node.js 22.23.4 or higher (odd-numbered versions such as v23 aren't supported) and a terminal.
How an Astro Page Is Built
Here's a small but complete page. The block between the --- fences is the component script, and everything below it is the template:
---
// src/pages/static.astro
import Base from '../layouts/Base.astro';
import Counter from '../components/Counter.jsx';
const posts = [
{ title: 'Hello Astro', slug: 'hello-astro' },
{ title: 'Islands explained', slug: 'islands' },
];
---
<Base title="Static page">
<h1>Latest posts</h1>
<ul>
{posts.map((post) => <li><a href={`/blog/${post.slug}`}>{post.title}</a></li>)}
</ul>
<Counter start={5} />
</Base>
Counter is an ordinary React component with a useState hook and an onClick handler. Because it's used without a client:* directive, Astro renders it to HTML on the server and throws the JavaScript away. Running npx astro build produces this file, and nothing else for that page:
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width"><title>Static page</title></head><body><h1>Latest posts</h1><ul><li><a href="/blog/hello-astro">Hello Astro</a></li><li><a href="/blog/islands">Islands explained</a></li></ul><button type="button">Count<!-- -->: <!-- -->5</button></body></html>
That's 354 bytes of HTML with no <script> tag at all. The component script ran once, in Node.js, during the build. The posts.map() loop became a list, the React component became a <button>, and the browser receives the finished result.
The same page can be rendered on each request instead of at build time by adding an adapter and export const prerender = false. The output is still HTML generated on the server; the difference is only when it's generated.
Why Astro Sites Are Fast
Zero JavaScript by Default
Most JavaScript frameworks hydrate the whole page: the server sends HTML, then the browser downloads the framework and every component so it can re-run them and attach event handlers. Astro inverts that. Components are static unless you opt in, so a typical article page ships no framework at all.
This matters because JavaScript is the most expensive resource per byte. An image only has to be decoded, but a script has to be downloaded, parsed, compiled and executed on the main thread, and on a mid-range phone that takes far longer than on a developer laptop. Removing it improves load time and responsiveness at the same time. You can read the details in how Astro ships zero JavaScript by default.
Islands for the Interactive Parts
When you do need interactivity, you add a directive to one component:
<Counter client:load />
<Counter client:visible />
Astro wraps each one in an <astro-island> custom element and loads its JavaScript independently, so a heavy carousel at the bottom of the page never delays a header menu at the top. Directives let you choose the timing:
| Directive | When the component's JavaScript loads |
|---|---|
client:load | Immediately on page load |
client:idle | When the browser is idle (requestIdleCallback) |
client:visible | When the component scrolls into the viewport |
client:media="(max-width: 50em)" | When a media query matches |
client:only="react" | Renders only in the browser, skipping server HTML |
The framework runtime is only sent once per page, however many islands use it. The full mechanics are covered in how Astro's island architecture works.
Server-First Rendering
Astro calls itself server-first. Data fetching, Markdown processing, database queries and template logic all happen on the server, the way PHP or Rails sites have always worked, but using JavaScript or TypeScript. The browser gets the result rather than the work.
Astro sites are also multi-page apps (MPAs) by default: each URL is a real HTML document and navigation is a normal page load. That sounds old-fashioned, but it means the first visit is fast, each page only carries what it needs, and there's no client-side router to download. If you want animated transitions between pages, the optional <ClientRouter /> component from astro:transitions adds them.
Build-Time Optimisations You Get for Free
Several smaller features add up:
- Scoped and bundled CSS:
<style>blocks in a component are scoped automatically, so low-specificity selectors likeh2 {}can't leak. Astro bundles and minifies the result, inlining small stylesheets into the page and linking larger ones. - Script processing: a plain
<script>in a component is bundled, deduplicated if the component appears many times, converted from TypeScript and inlined into the HTML when it's small. - Image optimisation: the
<Image />and<Picture />components fromastro:assetsresize images, convert them to formats such as WebP and addwidth,height,loading="lazy"anddecoding="async"to prevent layout shift. - HTML compression: Astro 7 strips whitespace using JSX-style rules by default (
compressHTML: 'jsx'). - Server islands: slow, personalised parts of a page (an avatar, a basket count) can be rendered separately with
server:defer, so the rest of the page can be cached and served immediately.
Measuring It: Static, Island and Framework Pages
To put numbers on this, I built three versions of the same small page with Astro 7.4.2 and Next.js 16.4.3 and measured what the browser has to download. Sizes are for the JavaScript files referenced by the page, compressed with gzip.
| Build | JavaScript files | JavaScript (gzipped) |
|---|---|---|
| Astro page, React component without a directive | 0 | 0 KB |
Astro page, one React island with client:load | 3 | about 69 KB |
| Next.js static export of the same list (no client component) | 5 (plus a noModule polyfill) | about 135 KB |
Almost all of the 69 KB in the island version is React DOM itself; the Counter component's own file is under 1 KB. Swap React for Preact, Svelte or a small web component and that number drops sharply. The point isn't that other frameworks are badly built, but that Astro lets a page that doesn't need a runtime avoid one entirely. There's a fuller comparison in the difference between Astro and Next.js.
What's New in Astro 6 and 7
If you used Astro a couple of years ago, several things have changed:
- Astro 6 (March 2026) removed the legacy content collections API. Collections are defined in
src/content.config.tswith loaders such asglob()andfile(), entries useentry.idinstead ofentry.slug, and you render them withrender(entry)fromastro:content.<ViewTransitions />became<ClientRouter />,Astro.glob()was removed in favour ofimport.meta.glob(), and Zod is imported fromastro/zod. The fonts API, Content Security Policy support and live content collections became stable. - Astro 7 (June 2026) upgraded to Vite 8 and made the Rust-based compiler the only compiler. It's faster, but stricter: unclosed tags are now build errors and invalid HTML nesting is no longer silently fixed. Markdown is now rendered by Sätteri, a Rust-based Markdown and MDX compiler, instead of remark and rehype (you can opt back into the unified pipeline with
@astrojs/markdown-remark). Route caching withcacheandrouteRulesis stable, and@astrojs/dbhas been removed.
The stricter compiler is worth knowing about on day one. This template built fine in older versions:
<div>
<p>Hello world
</div>
In Astro 7 it fails:
[CompilerError] Expected corresponding JSX closing tag for 'p'.
Closing the <p> fixes it.
Where Astro Fits Best
Astro is strongest when most of a page is content that's the same for everyone, or that can be rendered on the server:
- Blogs and publications, with Markdown or MDX in content collections.
- Documentation, often using Starlight, Astro's documentation theme.
- Marketing and landing pages, where Core Web Vitals and SEO matter.
- E-commerce storefronts, with server islands for personalised pieces.
- Portfolios and small business sites, which can often be fully static.
It's less suited to applications where nearly everything on screen is interactive and shared state is everywhere, such as a design tool or a complex dashboard. You can still build those inside Astro, but you'll end up shipping a large island and gain little from the architecture. When you should not use Astro covers those trade-offs in more depth.
Getting Started in One Command
You can try Astro locally in a minute:
npm create astro@latest
cd my-site
npm run dev
The wizard asks where to create the project, which template to start from (a basic starter, a blog, Starlight docs or a minimal empty project), whether to install dependencies and whether to initialise git. The dev server runs at http://localhost:4321/. The full walkthrough, including flags and manual setup, is in how to create a new Astro project from scratch.
FAQ: What Astro Is
It started as one and still generates static HTML by default, but it's now a full web framework. With an adapter installed, any page or API endpoint can render on demand on a server, and server islands let you mix static and dynamic content on one page.
No. Astro components are written in an HTML-like syntax, and you can add interactivity with plain script tags or web components. React, Vue, Svelte and others are optional integrations you add only if you want them.
Astro components render on the server and don't have a client-side runtime, so their JavaScript is never sent to the browser. Framework components are also rendered to HTML only, unless you add a client directive to make them interactive islands.
Yes. Pages arrive as complete HTML, so search engines don't need to run JavaScript to see your content, and small, fast pages tend to score well on Core Web Vitals. You still need good titles, descriptions, structured data and a sitemap, which Astro makes easy to add.
Astro's installation guide lists Node.js v22.23.4 or higher. Odd-numbered releases such as v23 aren't supported, so use an even-numbered LTS release.
Yes. Add an adapter such as @astrojs/node and set prerender to false on the pages that need it. Those pages can read cookies, check sessions and redirect, while the rest of the site stays static.
Conclusion
Astro is a framework for content-driven websites that renders HTML on the server and treats JavaScript as something you add deliberately, component by component. A React component without a directive becomes a few bytes of HTML; with client:visible it becomes an island that loads only when the visitor scrolls to it. That default, combined with scoped CSS, processed scripts and image optimisation, is why Astro sites are fast without much tuning.
Astro 6 and 7 have tightened the framework further, with the Content Layer, a Rust compiler, Vite 8 and a new Markdown pipeline. If your site is mostly content, Astro is one of the simplest ways to make it fast. Start with a static page, add islands only where users actually interact, and measure what you ship.


