Skip to content

SSR & Adapters

On-demand rendering runs your component script per request, so you can read request-time data. To run server code you install an adapter for your target platform and add it to the config:

astro.config.mjs
import { defineConfig } from 'astro/config';
import node from '@astrojs/node';
export default defineConfig({
adapter: node({ mode: 'standalone' }), // or cloudflare(), vercel(), netlify()
});

With an adapter present, routes render on demand where they need to (or when you set export const prerender = false on a route). Without one, any on-demand feature fails to build with “an adapter is required.”

sequenceDiagram
  participant B as Browser
  participant S as Astro server (adapter)
  participant C as Component script
  B->>S: GET /dashboard
  S->>C: run script with request context
  C->>C: read cookies, user, query params
  C-->>S: HTML + response settings
  S-->>B: Response (status, headers, body)
A request flows through render to a response

Inside an on-demand page or endpoint, the global Astro object exposes the request:

---
export const prerender = false;
const url = Astro.url; // a URL object
const q = url.searchParams.get('q'); // query params
const method = Astro.request.method; // the raw Request
const token = Astro.cookies.get('session')?.value; // typed cookie access
const { id } = Astro.params; // dynamic route params
---
<p>Searching for {q}</p>
  • Astro.request is the standard Request — headers, method, and await Astro.request.formData() or .json() for the body.
  • Astro.url is a parsed URL — the pathname and searchParams.
  • Astro.params holds dynamic segments ([id]).
  • Astro.cookies reads and writes cookies with a typed API (.get, .set, .delete, .has).

By default a page returns its HTML with a 200 status. You control the response through Astro.response (set status and headers) or by returning a Response directly:

---
export const prerender = false;
const user = Astro.cookies.get('session')?.value;
// Not logged in? Redirect.
if (!user) return Astro.redirect('/login');
// Set a custom header on the HTML response.
Astro.response.headers.set('Cache-Control', 'private, max-age=0');
---
<h1>Your dashboard</h1>

Astro.redirect('/login') returns a redirect Response; Astro.response.headers mutates the outgoing headers; and you can return new Response(...) to take full control (a 404 page, a custom status). This is the same Request/Response model the whole web platform uses — Astro doesn’t invent its own.

What must be configured for on-demand rendering to work?
How do you read the query string in an on-demand page?
How do you redirect an unauthenticated user from a server page?
What is `Astro.request`?