Skip to content
Strata

One codebase, four platforms: how the adapter switch works

How a single astro.config.ts builds for Vercel, Cloudflare Workers, Netlify and a Node server, and what each platform needs from you.

Updated 2 min read

“Where should we host it?” is a question that should never block a project. The template answers it with a build-time switch: set DEPLOY_TARGET, or let the platform be detected, and the correct adapter is loaded. This post walks through the mechanism and the small set of platform differences it hides.

The switch#

config/adapter.ts exports two functions. resolveDeployTarget() reads DEPLOY_TARGET and falls back to the variables each platform sets during a build: VERCEL=1, NETLIFY=true, and WORKERS_CI=1 or CF_PAGES=1 on Cloudflare. When none match, it returns node.

resolveAdapter(target) dynamically imports only the adapter that was chosen, so the other three never load, and returns it with the options that make the template’s features work:

case 'vercel':
  return vercel({ imageService: true, staticHeaders: true });
case 'cloudflare':
  return cloudflare({ prerenderEnvironment: 'node' });
case 'netlify':
  return netlify({ staticHeaders: true });
case 'node':
  return node({ mode: 'standalone', staticHeaders: true });

astro.config.ts awaits the result at the top level and passes it to defineConfig.

What stays the same#

Most of the codebase never knows which platform it is on:

  • Pages are prerendered by default; the auth and account routes, the dashboard, the admin area and the API opt in to server rendering.
  • The libSQL client picks its HTTP build on Workers and edge runtimes automatically, so database code is identical everywhere.
  • Better Auth runs on standard Request and Response objects.
  • The Content Security Policy is generated by Astro and either injected as a <meta> element or delivered as a header when the adapter supports staticHeaders.

What differs, and where it lives#

Zero configuration. The engines.node field selects Node 24, staticHeaders delivers the CSP, and a small integration adds the remaining security headers to the Build Output config.

Proving it every time#

The CI workflow builds all four targets on every pull request. It is the cheapest insurance against a dependency update that works on one runtime and breaks another.

Read the per-platform pages under Deploy for the exact dashboard settings and environment variables.