Astro is the best default for content-heavy sites in 2026, but it is not a universal answer. Pick the wrong project shape and you fight the framework on every feature. This guide is built on Astro 6 (stable March 10, 2026) and shows exactly where Astro wins, where Next.js or Hugo win instead, and a one-day spike that settles the question before you commit.
TL;DR
- Pick Astro when content is the product — blog, docs, marketing, a small catalog. You get near-zero shipped JavaScript by default and excellent Core Web Vitals with little tuning.
- Pick Next.js when interactivity is the product — dashboards, multi-step app flows, deep client-side routing and shared state.
- Pick Hugo or plain HTML when even Astro is overkill — a thousand-page docs site that rebuilds in seconds, or a five-page brochure.
- Astro 6 needs Node 22.12+, uses Vite 7 and Zod 4, and moved content config to
src/content.config.ts. If you are on Astro 4 tutorials, several APIs below have changed.
What changed in 2026 (so old guides mislead you)
Two things reset the landscape this year. First, Cloudflare acquired The Astro Technology Company on January 16, 2026, and the whole core team joined Cloudflare. The framework stays open source (MIT), but the Cloudflare adapter is now first-class: Astro 6’s dev server runs on workerd, the same runtime that serves production on Cloudflare Workers, so KV, D1, R2, and Durable Objects bindings work in local dev without a simulation layer.
Second, Astro 6 shipped stable on March 10, 2026 with breaking changes that invalidate a lot of older copy-paste:
output: 'hybrid'is gone. There are now only two modes:static(the default; pages are prerendered) andserver. Mixed sites usestaticplus per-pageexport const prerender = false.- Content config moved from
src/content/config.tstosrc/content.config.ts, and the v5 grace period is over. - Collections must declare a loader (
globorfile) — the legacy auto-collections API was removed. - The schema helper moved: import
zfromastro/zod, notastro:content.
If a tutorial still shows output: 'hybrid' or z from astro:content, it predates Astro 6.
The fit test: is your site Astro-shaped?
Astro is a strong default when most of these are true:
- Your site is mostly static content — blog, documentation, marketing pages, a small store.
- You want top Core Web Vitals (LCP, INP, CLS) without hand-tuning a bundler.
- You don’t need to share complex client-side state across many routes.
- You are comfortable authoring pages in
.astroor.mdx. - Your team is small and doesn’t need an opinionated full-stack app framework.
The single deciding question: list every page type your site needs (marketing, blog, docs, dashboard, checkout) and mark each “static” or “interactive.” If 70% or more are static, Astro is the right default. If most pages are interactive app surfaces, you will spend more time routing around Astro than using it.
Astro vs the alternatives (June 2026)
| Astro 6 | Next.js 15 | Hugo | Plain HTML | |
|---|---|---|---|---|
| Default JS shipped | ~0 KB on content pages | Hydrates the route by default | 0 KB | 0 KB |
| Best for | Content + a few islands | App-style, heavy interactivity | Huge static sites | Tiny brochure sites |
| Markdown/MDX | Native, typed via content layer | Via MDX plugins | Native (no MDX) | Manual |
| UI components | React, Vue, Svelte, Solid, Preact | React only | Go templates | None |
| Build speed (large sites) | Fast; content layer cut build memory 25-50% in v5 | Moderate | Fastest | Instant |
| SSR / dynamic | output: 'server' + adapter | Built-in, first-class | None (static only) | None |
| Hosting | Static anywhere; SSR via adapter | Best on Vercel-class hosts | Static anywhere | Anywhere |
Note: “near-zero JS” applies to content-only pages. Each interactive island you add (client:load, client:visible) ships exactly its own component and runtime — that is the cost you pay only where you opt in.
The one-day spike: prove it before you commit
Framework swaps mid-build are expensive. Spend a day validating Astro against your real content before deciding.
1. Scaffold the official starter. Starlight is the docs template; use --template basics for a blank site.
npm create astro@latest -- --template starlight my-spike
cd my-spike
npm install
npm run dev # http://localhost:4321
2. Wire up a content collection — this is Astro’s strongest feature and the one thing you must try before deciding. Note the Astro 6 syntax: file is src/content.config.ts, you pass a glob loader, and z comes from astro/zod.
// src/content.config.ts (Astro 6)
import { defineCollection } from 'astro:content';
import { glob } from 'astro/loaders';
import { z } from 'astro/zod';
const articles = defineCollection({
loader: glob({ pattern: '**/*.{md,mdx}', base: './src/content/articles' }),
schema: z.object({
title: z.string(),
publishedAt: z.coerce.date(),
tags: z.array(z.string()).default([]),
draft: z.boolean().default(false),
}),
});
export const collections = { articles };
Drop a sample file in src/content/articles/hello.mdx, then render it with getCollection('articles'). If this typed-front-matter workflow feels natural, you have your answer.
3. Add only the one UI framework you actually need. Don’t mix three.
npx astro add react # or vue, svelte, solid, preact
---
// src/pages/index.astro
import Counter from '../components/Counter.tsx';
---
<html>
<body>
<h1>Static heading</h1>
<Counter client:load /> <!-- only this island hydrates -->
</body>
</html>
4. Build and inspect the payload. A content-only page with no islands should ship essentially no JavaScript.
npm run build
ls -lh dist/_astro/*.js 2>/dev/null | head
# a content page with no islands ships ~0 KB of JS
5. Confirm your hosting target. Static output runs on any host. If you need SSR, set output: 'server' and add an adapter — remember hybrid no longer exists.
// astro.config.mjs — SSR example (Astro 6)
import { defineConfig } from 'astro/config';
import cloudflare from '@astrojs/cloudflare';
export default defineConfig({
output: 'server',
adapter: cloudflare(),
});
For a mostly static site that needs a few dynamic routes, keep the default static output and opt those pages out individually:
---
// src/pages/preview/[id].astro
export const prerender = false; // this route renders on the server
---
Common pitfalls
- Choosing Astro for an app-style project, then hitting friction on every interactive feature. Run the 70%-static test first.
- Mixing multiple UI integrations (React + Vue + Svelte). Each adds its own runtime; pick one.
- Storing data ad-hoc instead of using content collections — you throw away typed front matter and build-time validation.
- Copy-pasting an Astro 4/5 config:
output: 'hybrid',src/content/config.ts, orzfromastro:contentwill break on Astro 6. - Assuming Astro replaces a CMS. For non-technical editors you still need a CMS (Astro 6’s stable live content collections can pull from Contentful, Sanity, or WordPress at request time).
- Deploying static content to a server-heavy platform when a static CDN would be cheaper and faster.
Who this is for
Indie builders shipping content sites, documentation, marketing pages, or small portfolios — and anyone weighing Astro against Next.js for a content-first project.
When to skip Astro
Teams building dashboards, complex SaaS apps, or products with deep client-side state and routing. There, Next.js 15’s app-first model and React-everywhere defaults fit the work better.
FAQ
- Is Astro production-ready in June 2026?: Yes. Astro 6 has been stable since March 10, 2026, runs on Vite 7 and Node 22.12+, and powers many production content sites. The Cloudflare acquisition (Jan 2026) kept it open source under MIT.
- Should I start a new project on Astro 5 or 6?: Start on Astro 6. Most breaking changes are config-level (
src/content.config.ts, theglobloader,zfromastro/zod), so building fresh on 6 is easier than migrating later. - Can I use React inside Astro?: Yes, via the React integration. Islands hydrate React only where you opt in with directives like
client:load, keeping the rest of the page JS-free. Vue, Svelte, Solid, and Preact work the same way. - How does Astro compare to Hugo or Eleventy?: Astro is more flexible if you want JS components anywhere and native MDX; Hugo wins on raw build speed for very large static sites; Eleventy is the most minimal. Choose by ecosystem and authoring fit.
- Do I still need an adapter for a static site?: No. The default
staticoutput prerenders everything and deploys to any CDN with no adapter. You only add an adapter when you switch tooutput: 'server'or opt specific routes out of prerendering. - What replaced the old
hybridoutput mode?: It was removed. Usestatic(the default) for the whole site and addexport const prerender = falseto the individual routes that must render on the server.
Related
- Astro vs Next.js: how to choose for a content site
- Building a Markdown / MDX content site that scales
- Astro Content Collections — a 30-minute getting-started
- Use AI to Audit Astro Sites
- Using AI to Build Content Websites
- Astro Image Optimization in 2026: AVIF, WebP, Lazy
- Astro Incremental Content Update Without Full Rebuild
External references: Astro 6.0 release notes and the official content collections guide.