Astro: SSR in Astro

I mentioned previously how Astro creates a static site.

You can enable server-side rendering (SSR) however, if you need, globally or just for some pages.

Perhaps you want to serve some dynamic data from the database. Or whatever.

And still want to use Astro instead of another framework.

In this case, you enable SSR with:

npx astro add node

This changes the astro.config.mjs file to:

import { defineConfig } from 'astro/config'

import node from '@astrojs/node'

export default defineConfig({
  output: 'server',
  adapter: node({
    mode: 'standalone',

Notice output: 'server'. This makes SSR the default mode, must be disabled on individual pages by setting:

export const prerender = true

in the frontmatter.

You can also use output: 'hybrid' and it makes SSR opt-in on individual pages that should be server-rendered using export const prerender = false.

Now you can do interesting things.

For example we can decide to only show a page if there’s a specific cookie set:

import Layout from '../layouts/Layout.astro'

if (!Astro.cookies.has("test")) {
  return new Response(null, {
    status: 404,
    statusText: 'Not found'

<Layout title='Homepage'>
  <a href="/blog/first" class="underline">See blog post</a>

If the cookie is not set this returns a 404 error:

But if we set the cookie in the DevTools and reload the page, we can see its content:

This unlocks a lot of options, including processing forms, adding authentication, or anything you’d do with a server-side framework.

Lessons in this unit:

0: Introduction
1: Your first Astro site
2: The structure of an Astro site
3: Astro components
4: Adding more pages
5: Dynamic routing
6: Markdown in Astro
7: Images
8: Content collections
9: CSS in Astro
10: JavaScript in Astro
11: Client-side routing and view transitions
12: ▶︎ SSR in Astro
13: API endpoints in Astro