Skip to content

Static vs SSR

Next.js gives you three rendering modes per page: static (SSG), server-side rendering (SSR), and incremental static regeneration (ISR). Astro starts from the opposite end — static by default, opt into SSR per route — using a simpler two-switch model: the global output option plus the per-page prerender export.

astro.config.mjs
import { defineConfig } from 'astro/config';
export default defineConfig({
// 'static' — default; build-time HTML for every page
// 'server' — every page is server-rendered unless prerender=true
output: 'static',
});

When output is 'static' (the default) Astro pre-renders every page at build time and writes static HTML files to dist/. No server process is needed — you can deploy to any CDN or static host.

To use output: 'server' you must install an adapter that tells Astro how to run server-side code in your target environment.

Terminal window
# Choose one:
npx astro add vercel # Vercel serverless functions
npx astro add netlify # Netlify Edge Functions
npx astro add node # Self-hosted Node.js (express/standalone)
npx astro add cloudflare # Cloudflare Workers / Pages
// astro.config.mjs — SSR with Vercel adapter
import { defineConfig } from 'astro/config';
import vercel from '@astrojs/vercel/serverless';
export default defineConfig({
output: 'server',
adapter: vercel(),
});

With output: 'server', every page is server-rendered by default. Opt individual pages back to static HTML by exporting prerender = true.

src/pages/about.astro
---
// This page is still pre-rendered even though output: 'server'
export const prerender = true;
const title = "About us";
---
<h1>{title}</h1>

The reverse also works: with output: 'static', mark a page as server-only with export const prerender = false.

Next.js (App Router)
// Next.js rendering modes (App Router)
// Static (SSG) — default for Server Components
// No special export needed; just write a Server Component.
// next build pre-renders it to HTML.
// SSR — opt in per route
export const dynamic = 'force-dynamic';
// ISR — revalidate on a schedule
export const revalidate = 60; // seconds
// Client-side only (CSR)
'use client';
import { useEffect, useState } from 'react';
// ...
Astro
// Astro rendering modes
// astro.config.mjs
// output: 'static' → all pages are pre-rendered (default)
// output: 'server' → all pages are SSR by default
// Per-page overrides (works in both modes):
// Pre-render this specific page:
export const prerender = true;
// Server-render this specific page:
export const prerender = false;
// No ISR equivalent in core Astro — use adapter-specific
// options (e.g. Vercel's isr: { expiration: 60 }) in
// astro.config.mjs if your adapter supports it.

When a page depends on request-time data (auth cookies, URL params, POST body), write it as an SSR page:

src/pages/dashboard.astro
---
export const prerender = false; // server-render this page
const session = Astro.cookies.get('session')?.value;
if (!session) return Astro.redirect('/login');
const user = await fetchUser(session);
---
<h1>Welcome, {user.name}</h1>

This is the Astro equivalent of a Next.js getServerSideProps page or a dynamic Server Component that reads cookies.

Astro does not have a built-in ISR equivalent like Next.js revalidate. Adapter-specific options exist:

// astro.config.mjs — Vercel ISR via adapter config
import { defineConfig } from 'astro/config';
import vercel from '@astrojs/vercel/serverless';
export default defineConfig({
output: 'server',
adapter: vercel({
isr: {
expiration: 60, // re-generate after 60 seconds
},
}),
});
What is Astro's default rendering mode?
What must you install before setting `output: 'server'` in `astro.config.mjs`?
How do you pre-render one specific page when `output: 'server'` is set globally?
Which Next.js export is closest in concept to Astro's `export const prerender = false`?