Vercel
Preset: vercel
Getting started
Deploying to Vercel comes with the following features:
And much more. Learn more in the Vercel documentation.
Deploy with Git
Vercel supports Nitro with zero-configuration. Deploy Nitro to Vercel now.
API routes
Nitro /api directory isn't compatible with Vercel. Instead, you should use:
routes/api/for standalone usage
Bun runtime
You can use Bun instead of Node.js by specifying the runtime using the vercel.functions key inside nitro.config:
export default defineNitroConfig({
vercel: {
functions: {
runtime: "bun1.x"
}
}
})
Alternatively, Nitro also detects Bun automatically if you specify a bunVersion property in your vercel.json:
{
"$schema": "https://openapi.vercel.sh/vercel.json",
"bunVersion": "1.x"
}
Proxy route rules
Nitro automatically optimizes proxy route rules on Vercel by generating CDN-level rewrites at build time. This means matching requests are proxied at the edge without invoking a serverless function, reducing latency and cost.
export default defineNitroConfig({
routeRules: {
// Proxied at CDN level — no function invocation
"/api/**": {
proxy: "https://api.example.com/**",
},
},
});
When CDN rewrites apply
A proxy rule is offloaded to a Vercel CDN rewrite when all of the following are true:
- The target is an external URL (starts with
http://orhttps://). - No advanced
ProxyOptionsare set on the rule.
Fallback to runtime proxy
When the proxy rule uses any of the following ProxyOptions, Nitro keeps it as a runtime proxy handled by the serverless function:
headers— custom headers on the outgoing request to the upstreamforwardHeaders/filterHeaders— header filteringfetchOptions— custom fetch optionscookieDomainRewrite/cookiePathRewrite— cookie manipulationonResponse— response callback
headers option are still applied to CDN-level rewrites. Only request-level ProxyOptions.headers (sent to the upstream) require a runtime proxy.Custom build output configuration
You can provide additional build output configuration using vercel.config key inside nitro.config. It will be merged with built-in auto-generated config.
On-Demand incremental static regeneration (ISR)
On-demand revalidation allows you to purge the cache for an ISR route whenever you want, foregoing the time interval required with background revalidation.
To revalidate a page on demand:
Create an Environment Variable which will store a revalidation secret- You can use the command
openssl rand -base64 32 or Generate a Secret to generate a random value.
openssl rand -base64 32 or Generate a Secret to generate a random value.Update your configuration:nitro.config.tsimport { defineNitroConfig } from "nitro/config";
export default defineNitroConfig({
vercel: {
config: {
bypassToken: process.env.VERCEL_BYPASS_TOKEN
}
}
})
import { defineNitroConfig } from "nitro/config";
export default defineNitroConfig({
vercel: {
config: {
bypassToken: process.env.VERCEL_BYPASS_TOKEN
}
}
})
To trigger "On-Demand Incremental Static Regeneration (ISR)" and revalidate a path to a Prerender Function, make a GET or HEAD request to that path with a header of x-prerender-revalidate: bypassToken. When that Prerender Function endpoint is accessed with this header set, the cache will be revalidated. The next request to that function should return a fresh response.
Fine-grained ISR config via route rules
By default, query params affect cache keys but are not passed to the route handler unless specified.
You can pass an options object to isr route rule to configure caching behavior.
expiration: Expiration time (in seconds) before the cached asset will be re-generated by invoking the Serverless Function. Setting the value tofalse(orisr: trueroute rule) means it will never expire.group: Group number of the asset. Prerender assets with the same group number will all be re-validated at the same time.allowQuery: List of query string parameter names that will be cached independently.- If an empty array, query values are not considered for caching.
- If
undefinedeach unique query value is cached independently. - For wildcard
/**route rules,urlis always added
passQuery: Whentrue, the query string will be present on therequestargument passed to the invoked function. TheallowQueryfilter still applies.
export default defineNitroConfig({
routeRules: {
"/products/**": {
isr: {
allowQuery: ["q"],
passQuery: true,
},
},
},
});