Overview
Pick Next.js when the site has auth, user-specific data, server actions, or a serious app surface (dashboard, editor, multi-tenant SaaS). Pick Astro when the site is content-shaped: marketing, blog, docs, e-commerce catalog, or any site that mostly reads from a CMS and stays interactive only in small islands. The dividing line is “does this site have logged-in state on most routes.” If yes, Next.js. If no, Astro. See nextjs and astro for each framework’s rules.
When Next.js wins
Next.js is the right pick for any app where users log in and the server fetches data on every request.
- Server Components and Server Actions handle data fetching, mutations, and revalidation in one model; see react-server-components.
- Built-in auth integration (NextAuth, Clerk, Supabase) and middleware run at the edge before the route renders.
- Streaming SSR with Suspense boundaries delivers the shell fast and fills in personalized data progressively.
- Image, font, and script optimization are framework-native; no plugin chasing.
- Vercel hosting plus ISR (Incremental Static Regeneration) handles “mostly static but personalized” cases that pure SSG cannot.
When Astro wins
Astro is the right pick for content-shaped sites where the JS budget should default to zero.
- Astro components render to HTML at build or on the server; nothing ships to the browser unless you opt in with a
client:*directive. - The island architecture lets a blog ship 0 KB JS for the prose and hydrate a single comment widget or theme toggle.
- Multi-framework support: React, Vue, Svelte, and Solid all run as islands inside the same Astro page. Migrating frameworks does not require rewriting the shell.
- Content Collections give type-safe markdown and MDX with Zod schemas; the DX for blogs and docs is the best in the comparison.
- Build output is static by default; deploy to GitHub Pages, Cloudflare Pages, or any CDN without a Node runtime.
Trade-offs at a glance
| Dimension | Next.js | Astro |
|---|---|---|
| Default JS to client | Server Components ship zero JS; client islands hydrate | Static HTML; islands hydrate only when directed |
| Best fit | Apps with auth and dashboards | Marketing, blog, docs, catalog |
| Runtime required | Node or Edge runtime in prod | Static HTML; optional SSR adapter |
| Data fetching | Server Components, Server Actions | getStaticPaths, content collections, server endpoints |
| Routing | File-based App Router | File-based pages plus collections |
| Component model | React only | React, Vue, Svelte, Solid as islands |
| Hosting | Vercel canonical; self-host harder | Any static host; CDN-friendly |
| Build speed at scale | Slower past 5k routes | Fast incremental builds |
| Image optimization | Built-in <Image> | Built-in <Image> and <Picture> |
Migration cost
Migrating between Next.js and Astro is feasible because both speak React, but the cost is real.
- Next.js to Astro: cheap if the site is mostly content. Move pages one route at a time; reuse the React components as
client:loadislands. Plan one engineer-week per 100 routes for a marketing site; longer if the app has any auth surface. - Astro to Next.js: usually triggered by adding auth or user-specific data. Easiest path is to keep Astro for marketing under a path prefix (
/blog,/docs) and add Next.js for the app under/app. Route at the edge. - Do not migrate a whole site for one new feature; split at the URL boundary.
Recommendation
- Marketing site, blog, docs, or content-led e-commerce: Astro.
- SaaS dashboard, social app, or any product with auth on most routes: Next.js with the App Router.
- Hybrid (marketing plus app): Astro for
/,/blog,/docs; Next.js for/app. Route with Cloudflare Workers or Vercel rewrites. - Static company site under 50 pages: Astro. Next.js is overkill.
- Already on Gatsby or Create React App: jump to Next.js if app-shaped, Astro if content-shaped.