Vercel Adapter
Astro ships static HTML by default, but the moment you need on-request rendering — authenticated dashboards, personalized pages, API routes, or form handling — you need an adapter that maps Astro’s server output to your host’s runtime. The @astrojs/vercel adapter does exactly that for Vercel, compiling your SSR routes into Vercel Functions (Node-based serverless) or Edge Functions (V8 isolates running close to your users). It also wires up Vercel’s image optimization, ISR, and web analytics so you keep Astro’s zero-JS-by-default islands while adding dynamic behavior only where you opt in.
Installing the adapter
The fastest path is astro add, which installs the package, updates astro.config.mjs, and sets the output mode for you.
npx astro add vercel
To do it manually, install the package and register the adapter yourself:
npm install @astrojs/vercel
// astro.config.mjs
import { defineConfig } from 'astro/config';
import vercel from '@astrojs/vercel';
export default defineConfig({
output: 'server',
adapter: vercel(),
});
In Astro 5 the import path is the unified
@astrojs/vercel(the old@astrojs/vercel/serverlessand/staticsubpaths were removed). The single adapter now handles static, serverless, and edge output based on your config and per-route settings.
Output modes
Astro distinguishes how each page is rendered. Pick the mode that matches how much of your site is dynamic.
output value | Behavior | Use when |
|---|---|---|
static | Everything prerendered to HTML at build time | Mostly content; no per-request logic |
server | On-demand rendering by default; opt out per page | Dashboards, auth, APIs |
With output: 'server' you can still prerender individual pages by exporting prerender, which keeps fast static delivery for pages that don’t change per request:
---
// src/pages/about.astro
export const prerender = true;
---
<html>
<body><h1>About us</h1></body>
</html>
Conversely, under static output you opt a single route into on-demand rendering with export const prerender = false.
Serverless functions
By default, dynamic routes deploy as Vercel Functions on the Node.js runtime. You can tune the Node version, included files, and memory through adapter options.
// astro.config.mjs
import { defineConfig } from 'astro/config';
import vercel from '@astrojs/vercel';
export default defineConfig({
output: 'server',
adapter: vercel({
includeFiles: ['./src/data/products.json'],
maxDuration: 60,
}),
});
A server endpoint reads the request and returns a Response exactly like the Web platform:
// src/pages/api/greet.ts
import type { APIRoute } from 'astro';
export const GET: APIRoute = ({ url }) => {
const name = url.searchParams.get('name') ?? 'world';
return new Response(JSON.stringify({ message: `Hello, ${name}!` }), {
headers: { 'Content-Type': 'application/json' },
});
};
Output:
$ curl "https://your-app.vercel.app/api/greet?name=Ada"
{"message":"Hello, Ada!"}
Edge rendering
To run a route on Vercel’s Edge runtime instead of Node, set edgeMiddleware for middleware or move the whole app to the edge. The edge runtime starts faster and runs globally, but only exposes Web-standard APIs — no Node built-ins like fs or crypto’s Node interface.
// astro.config.mjs
import vercel from '@astrojs/vercel';
export default defineConfig({
output: 'server',
adapter: vercel({
edgeMiddleware: true,
}),
});
Gotcha: code that imports Node core modules (
node:fs,node:path) will fail at the edge. Keep database drivers and filesystem access on the serverless runtime, and reserve the edge for lightweight redirects, auth checks, and geo logic.
Image optimization and ISR
The adapter integrates with Vercel’s services so you don’t have to ship your own. Enable the Vercel image service and Incremental Static Regeneration:
// astro.config.mjs
import vercel from '@astrojs/vercel';
export default defineConfig({
output: 'server',
adapter: vercel({
imageService: true,
isr: {
expiration: 60 * 60, // revalidate cached pages hourly
},
webAnalytics: { enabled: true },
}),
});
With imageService: true, Astro’s <Image /> component routes transformations through Vercel’s optimizer at the CDN edge. ISR caches a server-rendered page and refreshes it in the background after the expiration window, giving you static-like speed with periodically fresh data.
Deploying
Connect the Git repository in the Vercel dashboard, or deploy from the CLI. Vercel auto-detects Astro and runs the build for you.
npm install -g vercel
vercel # preview deployment
vercel --prod # production deployment
Output:
Vercel CLI
🔍 Inspect: https://vercel.com/acme/astro-app/3xK9...
✅ Production: https://astro-app.vercel.app [4s]
Best practices
- Use
output: 'server'withexport const prerender = trueon static pages so only truly dynamic routes pay the function cost. - Reserve the edge runtime for lightweight, Web-API-only logic; keep DB and filesystem work on serverless functions.
- Set a realistic
maxDurationfor slow endpoints, but split long tasks into background jobs rather than raising it indefinitely. - Turn on
imageServiceso you keep Astro’s<Image />ergonomics without bundling a separate optimizer. - Apply
isrto pages that change occasionally to combine static speed with periodic freshness. - Store secrets in Vercel environment variables and read them via
import.meta.env, never hardcode them in committed config.