How to ship a Nitro app on Vercel
Deploy a Nitro app to Vercel with zero configuration. Learn how to ship from a template, the Vercel CLI, or Git, and configure ISR, cron jobs, Vercel Queues, per-route function settings, and Observability.
Prerequisites
On Vercel, you can deploy a Nitro app with zero configuration: your server routes become Vercel Functions running on Fluid compute, and you get preview deployments, observability, and Vercel Firewall without extra setup.
7 min read
7 Jun 2026
Before you begin, make sure you have:
This guide walks you through deploying a Nitro app to Vercel from a template, the Vercel CLI, or a Git repository, and configuring features such as Incremental Static Regeneration, cron jobs, queues, and observability.
- A Vercel account
- Node.js 20+ and a package manager (e.g., npm)
- An existing Nitro project, or a new one created from a Nitro template
- A Git repository on GitHub, GitLab, or Bitbucket (if you want Git-based deployments)
- Vercel CLI installed ( npm i -g vercel)
How it works
When you deploy a Nitro app, Vercel detects the framework and builds it for the Vercel runtime. Nitro compiles your server routes into Vercel Functions, which run on Fluid compute by default. Your app scales with traffic, and you pay only for the compute your functions use, not for idle time.
Because Vercel ships zero-configuration detection for Nitro, you don't set a build command or output directory. Vercel reads your project, identifies the framework, and applies the correct build settings.
Deploy your Nitro app
You can ship a Nitro app to Vercel in three ways. Choose the one that fits where your code lives today.
Option 1: Deploy from a template
The fastest way to ship a Nitro app is to start from a template. Browse the Nitro templates gallery, pick a starter, and deploy it. Vercel clones the template to your Git provider, creates a project, and deploys it with zero configuration.
Templates to start from include:
- Nitro Starter: Deploy an API on Vercel with Nitro
- Nitro - Route Rules: A Nitro app that uses route rules
- Nitro - Plugins: A Nitro app that uses plugins
- Slack Bolt with Nitro: A Slack app built with Bolt for JavaScript and Nitro
- Durable iMessage AI Agent: A durable iMessage agent built with Chat SDK
Option 2: Start a new project with the Vercel CLI
To scaffold a new Nitro project locally, use the Vercel CLI init command. It clones Vercel's Nitro example into a folder named nitro.
- Create the project:
vercel init nitro
- Install dependencies:
cd nitro
npminstall
- Develop locally at
http://localhost:3000:
npm run dev
- Create a
preview deployment. The first run creates a Vercel project link:
vercel
- Promote your changes to production:
vercel --prod
Option 3: Deploy an existing Nitro app
If you already have a Nitro app, deploy it from Git or from the command line.
From Git: Push your project to GitHub, GitLab, or Bitbucket, then import it at vercel.com/new. Vercel detects Nitro automatically and deploys it with zero configuration.
From the CLI: From your project's root directory, run vercel to create a preview deployment, then vercel --prod to go live. To pull project settings and environment variables for local development, run:
vercel link
vercel env pull
nitro package, which replaced
nitropack). New projects from a template or the Vercel CLI already use v3. If you're bringing an existing app, upgrade to v3 first using the
migration guide, or adjust the imports to
nitropack/config for nitropack v2.
Use Vercel features with Nitro
After your app is deployed, you can configure Vercel features directly from your Nitro config. The examples below import defineNitroConfig from nitro/config; import { defineConfig } from "nitro" works too.
Server routes run as Vercel Functions
Each Nitro server route automatically becomes a Vercel Function. These functions use Fluid compute by default, which runs multiple requests concurrently within a single instance to reduce cold starts and I/O-bound work costs, such as API calls and database queries. You don't configure anything to get this behavior.
Cache responses with Incremental Static Regeneration (ISR)
ISR serves cached responses and regenerates them in the background, so you get static performance for dynamic content. Enable it per route with the isr route rule:
isr:{
routeRules:{
"/products/**":{
allowQuery:["q"],
import{ defineNitroConfig }from"nitro/config";
},
});
},
expiration:60,
exportdefaultdefineNitroConfig({
passQuery:true,
By default, each unique query value is cached separately. Set allowQuery to an empty array to ignore query parameters for caching, or list specific parameters to cache only those. Query parameters aren't passed to your route handler unless you set passQuery: true. The isr rule accepts these options:
Option
expiration
number | false
number
Description
Default
Type
string[]
allowQuery
Expose the response body for error status codes.
—
false
undefined
exposeErrBody
passQuery
Group number for the asset. Assets in the same group revalidate together.
boolean
false
false
boolean
To purge the cache for a route on demand, set a bypass token and send a revalidation request:
- Generate a secret and store it as an
environment variable such as
VERCEL_BYPASS_TOKEN:
openssl rand -base6432
- Reference the secret in your config:
import{ defineNitroConfig }from"nitro/config";
exportdefaultdefineNitroConfig({
vercel:{
config:{
bypassToken: process.env.VERCEL_BYPASS_TOKEN,},
},
}); - Send a
GET or
HEAD request to the route with the header
x-prerender-revalidate:
. Vercel revalidates the cache, and the next request returns a fresh response.
Run scheduled tasks as cron jobs
Nitro converts its scheduledTasks configuration into Vercel Cron Jobs at build time, so you don't write any vercel.json cron configuration. Enable tasks and define your schedules:
exportdefaultdefineNitroConfig({
tasks:true,
experimental:{
import{ defineNitroConfig }from"nitro/config";
We collaborate with trusted, high-quality partners to bring you reliable and top-notch products and services.
},
});
scheduledTasks:{
},
"0 * * * *":["cms:update"],// every hour
"0 0 * * *":["db:cleanup"],// every day at midnight
Process messages with Vercel Queues
To prevent unauthorized access to the cron handler, set a CRON_SECRET environment variable in your project settings. When it's set, Nitro validates the Authorization header on every cron invocation.
Nitro integrates with Vercel Queues to process messages asynchronously. Define your topics in the config, then handle incoming messages with the vercel:queue hook in a Nitro plugin.
Define the topics:
vercel:{
queues:{
triggers:[
exportdefaultdefineNitroConfig({
{ topic:"notifications"},
},
});
],
},
{ topic:"orders", retryAfterSeconds:60, initialDelaySeconds:5},
import{ defineNitroConfig }from"nitro/config";
Send messages with the @vercel/queue package:
});
});
console.log(`[${metadata.topicName}] ${metadata.messageId}:`, message);
exportdefaultdefineEventHandler(async(event)=>{
exportdefaultdefineNitroPlugin((nitro)=>{
nitro.hooks.hook("vercel:queue",({ message, metadata, send })=>{
});
const order =await event.req.json();
return{ messageId };
import{ send }from"@vercel/queue";
const{ messageId }=awaitsend("orders", order);
Proxy requests at the CDN
Queues also work in nitro dev: send() delivers messages straight to your hook, so you can iterate without deploying. Run vercel link and vercel env pull first so the SDK can authenticate.
Nitro optimizes proxy route rules by generating CDN-level rewrites at build time. Matching requests are proxied through Vercel's CDN without invoking a function, thereby reducing latency and costs.
routeRules:{
"/api/**":{
exportdefaultdefineNitroConfig({
});
},
proxy:"https://api.example.com/**",
},
A proxy rule moves to a CDN rewrite when the target is an external URL (starting with http:// or https://) and the rule sets no advanced ProxyOptions. If you use options such as headers, forwardHeaders, fetchOptions, cookie rewriting, or onResponse, Nitro keeps the proxy at runtime inside the function instead.
Set per-route function configuration
Use vercel.functionRules to override function settings for specific routes. Each key is a route pattern, and its value merges with your base vercel.functions config. Array values like regions replace the base array rather than merging with it.
vercel:{
functionRules:{
},
maxDuration:800,
memory:4096,
"/api/heavy-computation":{
import{ defineNitroConfig }from"nitro/config";
},
});
},
"/api/regional":{
exportdefaultdefineNitroConfig({
regions:["lhr1","cdg1"],
Use the Bun runtime
Route patterns support wildcards, so /api/slow/** matches every route under /api/slow/. This is useful when certain routes need different resource limits, regions, or features like Vercel Queues triggers.
Nitro runs your functions on Node.js by default. To use Bun instead, set the runtime in vercel.functions:
vercel:{
},
});
functions:{
},
runtime:"bun1.x",
import{ defineNitroConfig }from"nitro/config";
{
}
"bunVersion":"1.x"
exportdefaultdefineNitroConfig({
"$schema":"https://openapi.vercel.sh/vercel.json",
Best practices
Monitor performance with Observability
});
exportdefaultdefineNitroConfig({
Vercel Observability breaks down function performance by route, so you can find slow paths and optimization opportunities. Nitro generates the routing hints these insights need. Set a compatibility date of 2025-07-15 or later to turn this on:
import{ defineNitroConfig }from"nitro/config";
compatibilityDate:"2025-07-15",// or "latest"
Put API routes in routes/api
Nitro's top-level /api directory isn't compatible with Vercel. Put your API handlers in routes/api/ instead so they deploy correctly.
Configure Nuxt under the nitro key
Nuxt is built on Nitro, so if you're using Nuxt, place these options under the nitro key in nuxt.config.ts:
},
nitro:{
routeRules:{
isr:{ expiration:60},
"/products/**":{
},
});
},
Resources and next steps
exportdefaultdefineNuxtConfig({
- Read the full Nitro on Vercel documentation
- Configure Vercel-specific features through the Deploy Nitro to Vercel provider docs
- Learn how Vercel Functions run your server code
- Understand pricing and scaling with Fluid compute
- Cache and revalidate content with Incremental Static Regeneration
- Explore Nitro templates you can deploy in one step
