/ astro-integrations / How to Use Vercel with Astro: Complete Guide
astro-integrations 9 min read

How to Use Vercel with Astro: Complete Guide

Step-by-step guide to integrating Vercel with your Astro website. Installation, configuration, and best practices.

How to Use Vercel with Astro: Complete Guide

Vercel is one of the best places to deploy an Astro site, especially when you need on-demand rendering alongside static pages. Astro has an official Vercel adapter that handles everything from serverless functions to edge middleware. The deploy experience is basically zero-config once the adapter is set up.

This guide was checked against the official docs on 2026-05-30 and reflects Astro 6 and @astrojs/vercel 10. If you are following older tutorials, note that two things have changed: output: 'hybrid' no longer exists (it was merged into static in Astro 5), and the adapter's edgeMiddleware option was deprecated in @astrojs/vercel v10 in favor of middlewareMode.

Prerequisites

  • Node.js 22.12.0 or newer. Astro 6 sets this as the minimum in its engines field, and npx astro add will refuse older runtimes.
  • An Astro project (npm create astro@latest)
  • A Vercel account (free tier at vercel.com)
  • Your project in a Git repository (GitHub, GitLab, or Bitbucket)

Installation

Add the official Vercel adapter:

npx astro add vercel

This command installs @astrojs/vercel (currently 10.0.8, peer-depends on astro ^6.0.0) and updates your Astro config automatically. If you prefer to install by hand, run npm install @astrojs/vercel and then wire the adapter into your config as shown below.

A note on import paths: in @astrojs/vercel v10 the old @astrojs/vercel/serverless and @astrojs/vercel/static subpath exports were removed (they were deprecated back in adapter v8). Import from the package root (@astrojs/vercel) only. Older guides that show import vercel from '@astrojs/vercel/serverless' will fail to resolve.

Configuration

After running the add command, your config should look like this:

// astro.config.mjs
import { defineConfig } from "astro/config";
import vercel from "@astrojs/vercel";

export default defineConfig({
  adapter: vercel(),
});

There is no output: 'hybrid' line anymore. In Astro 5 the hybrid and static output modes were merged into a single static mode, which is the default and does not need to be declared. A static-by-default site lets you opt individual pages into on-demand rendering with export const prerender = false. The adapter is what makes those on-demand routes runnable on Vercel.

If you want the inverse, where every page renders on demand and you opt specific routes back into prerendering, set output: 'server' and use export const prerender = true on the pages you want built ahead of time. The Astro docs recommend staying on the default static mode until you are sure most of your pages need to render on demand.

For a fully static site with no on-demand routes at all, you do not strictly need the adapter. Push to Vercel and it will build and serve your static files. The adapter earns its place the moment you add a single server-rendered route, an API endpoint, ISR, image optimization, or middleware.

Basic Usage

With the adapter in place, you can mix static and dynamic pages. Static pages get pre-rendered at build time (the default), and on-demand pages run as Vercel Functions.

---
// src/pages/dashboard.astro
// This page renders on every request
export const prerender = false;

const user = await getUser(Astro.cookies.get("token")?.value);
---

<html>
  <body>
    <h1>Welcome, {user?.name || "Guest"}</h1>
  </body>
</html>

Static pages (the default) just work normally:

---
// src/pages/about.astro
// This page is pre-rendered at build time (default behavior)
---

<html>
  <body>
    <h1>About Us</h1>
    <p>This page is static and loads instantly.</p>
  </body>
</html>

Environment Variables

Set your environment variables in the Vercel dashboard under Settings > Environment Variables. In your Astro code, access them with import.meta.env:

// Server-side only (API routes, SSR pages)
const apiKey = import.meta.env.API_SECRET_KEY;

// Client-side accessible (prefix with PUBLIC_)
const siteUrl = import.meta.env.PUBLIC_SITE_URL;

API Routes

Vercel turns on-demand Astro API endpoints into Vercel Functions:

// src/pages/api/hello.ts
import type { APIRoute } from "astro";

export const prerender = false;

export const GET: APIRoute = async () => {
  return new Response(JSON.stringify({ message: "Hello from Vercel!" }), {
    status: 200,
    headers: { "Content-Type": "application/json" },
  });
};

The export const prerender = false line is what marks the endpoint as on-demand in the default static output mode. Without it, Astro tries to build the endpoint at build time.

Edge Middleware

If you want your Astro middleware to run at the edge (lower latency, closer to users, executed for every request including static assets), enable edge middleware on the adapter. In @astrojs/vercel v10 this is the middlewareMode option:

// astro.config.mjs
import { defineConfig } from "astro/config";
import vercel from "@astrojs/vercel";

export default defineConfig({
  adapter: vercel({
    middlewareMode: "edge",
  }),
});

The older boolean form, edgeMiddleware: true, still works for now but was deprecated in @astrojs/vercel v10 and is slated for removal in a future release. Migrate to middlewareMode: 'edge'.

Incremental Static Regeneration

ISR serves cached pages like static files, then revalidates them in the background after an expiration window. Enable it on the adapter:

// astro.config.mjs
import { defineConfig } from "astro/config";
import vercel from "@astrojs/vercel";

export default defineConfig({
  adapter: vercel({
    isr: {
      // cache on first request, revalidate after one day
      expiration: 60 * 60 * 24,
    },
  }),
});

This is ideal for content that changes occasionally, such as blog posts or product pages, where a fully dynamic render on every request would be wasteful.

Image Optimization

The adapter can route Astro's <Image /> component through Vercel's Image Optimization API in production:

// astro.config.mjs
import { defineConfig } from "astro/config";
import vercel from "@astrojs/vercel";

export default defineConfig({
  adapter: vercel({
    imageService: true,
  }),
});

With this enabled, optimized images are served from Vercel's /_vercel/image endpoint rather than being processed at build time.

Web Analytics

The adapter can inject Vercel Web Analytics:

// astro.config.mjs
import { defineConfig } from "astro/config";
import vercel from "@astrojs/vercel";

export default defineConfig({
  adapter: vercel({
    webAnalytics: { enabled: true },
  }),
});

Note the version split called out in the docs. The webAnalytics: { enabled: true } adapter option targets @vercel/analytics@1.3.x and earlier. For @vercel/analytics@1.4.0 and later, drop the adapter option and use Vercel's Analytics component directly instead.

Production Tips

  1. Reach for ISR before full on-demand rendering. Incremental Static Regeneration lets you serve cached pages while revalidating in the background. For content that updates occasionally it is far cheaper than rendering on every request.

  • Set proper cache headers. For on-demand endpoints, set Cache-Control headers. Vercel's Edge Network respects these and will cache responses accordingly.

  • Enable Web Analytics and Speed Insights. You get free Core Web Vitals monitoring from the Vercel dashboard. Wire analytics through the adapter option or Vercel's component depending on your @vercel/analytics version.

  • Preview deployments for every PR. Vercel creates a unique preview URL for every pull request. Use this to test changes before merging to production.

  • Keep functions small. Each on-demand route becomes a Vercel Function. Avoid importing heavy dependencies in on-demand pages to keep cold starts fast.

  • Common Errors and Fixes

    Cannot find module '@astrojs/vercel/serverless' (or /static). Those subpath exports were removed in @astrojs/vercel v10. Change your import to the package root: import vercel from '@astrojs/vercel'.

    output: 'hybrid' throws a config error. The hybrid value was removed in Astro 5 when it was merged into static. Delete the output line entirely (static is the default) and use export const prerender = false per page to opt into on-demand rendering. Use output: 'server' only if you want on-demand by default.

    npx astro add aborts complaining about Node version. Astro 6 requires Node >=22.12.0 in its engines field. Upgrade your local Node, and in the Vercel project settings confirm the Node.js Version is set to a supported release before deploying.

    Edge middleware deprecation warning. If the build warns about edgeMiddleware, switch the adapter option from edgeMiddleware: true to middlewareMode: 'edge'. The boolean form was deprecated in v10 and will be removed.

    Pages that should be dynamic are served stale or 404. In the default static output, a page is prerendered unless you add export const prerender = false. Forgetting that line is the most common reason an SSR route behaves like a static one. Conversely, in output: 'server' you need export const prerender = true on the routes you want built ahead of time.

    Optimized images break in production but work locally. Vercel's Image Optimization only kicks in when imageService: true is set on the adapter. Without it, Astro's default image processing runs at build time, which is not what the /_vercel/image URLs expect.

    Official Docs and Examples

    Alternatives to Consider

    • Cloudflare Pages if you want unlimited bandwidth on the free tier and a global edge network. Also has an official Astro adapter.
    • Netlify if you prefer their form handling, identity, and build plugin ecosystem. Very similar to Vercel for Astro.
    • AWS Amplify if you are already invested in the AWS ecosystem and need deeper integration with AWS services.

    Wrapping Up

    Vercel and Astro are a natural fit. The official adapter handles the deployment plumbing, static-by-default rendering with per-page prerender = false gives you the flexibility to mix static and on-demand, and Vercel's infrastructure handles the rest. Push your code and it just works.

    Sources

    All versions and configuration facts in this guide were verified against the following sources on 2026-05-30: