vercel#
What it is#
vercel is the official command-line tool for Vercel’s frontend cloud — the platform that hosts Next.js and many other framework deployments (SvelteKit, Astro, Nuxt, Remix, Vue, Vite, plain static). It wraps the Vercel REST API and handles project linking, deploys (preview + production), environment variables, log tailing, alias management, custom domains, certificates, and the Vercel Functions / Edge runtimes. A single vercel invocation in a project directory uploads the source, runs the same build that runs in the cloud, and returns a URL.
Reach for vercel whenever you target Vercel directly without a Git integration — local one-shot deploys, CI promotions, env-var sync, log streaming after an incident. If you only ever use the GitHub-connected auto-deploy, you may not need it day-to-day; most teams still install it for vercel env pull, vercel link, and rollback.
Install#
The CLI is published as the vercel npm package. The team recommends global install because it isn’t tied to a single project’s lockfile and is most often used outside node_modules (e.g. clean clones, CI runners).
npm install -g vercel
Output: added 1 package; vercel on PATH
pnpm add -g vercel
Output: added vercel globally
yarn global add vercel
Output: added vercel globally
bun add -g vercel
Output: installed vercel as a global tool
Per-project install (pins the version alongside your code, especially useful in CI):
npm install -D vercel
Output: added vercel to devDependencies
One-off without install:
npx vercel --version
Output: prints installed vercel version
Verify:
vercel --version
Output: prints CLI version (currently the 47.x line, hedge against minor drift)
Versioning & Node support#
Current line is vercel@47.x (mid-2026). Vercel ships a new minor roughly every 1–2 weeks, tracking platform features and runtime changes.
- Node 20+ required on the
47.xline. Earlier majors supported Node 16/18; check the changelog before upgrading old projects. - The CLI is a Node application — distributed as platform-neutral JS plus optional native deps for build acceleration.
- TypeScript types are NOT published for programmatic use — the CLI is the interface. For programmatic integrations use the Vercel REST API directly or the
@vercel/sdkpackage. - Semver is followed but the API surface (subcommand flags, output formats) shifts more often than the npm package’s major number suggests. Pin in CI.
Package metadata#
- Maintainer: Vercel (
vercel/vercelmono-repo on GitHub) - Project home: github.com/vercel/vercel
- Docs: vercel.com/docs/cli
- npm: npmjs.com/package/vercel
- License: Apache-2.0
- First released: 2017 (as
now, renamed tovercelin 2020 alongside the company rename) - Downloads: ~2 million weekly — one of the most-installed deploy CLIs on npm.
Peer dependencies & extras#
vercel declares no peer dependencies — it is a self-contained CLI. The package ships a large bundle (~50–80 MB after install) because it embeds the Vercel build runtime for local-parity builds (vercel build), the Next.js compatibility shim, and helpers for many framework adapters.
Companion packages from the same monorepo (use directly only in advanced workflows):
@vercel/node— Node Function runtime@vercel/edge— Edge Function runtime@vercel/static-build— static-build framework adapter@vercel/next— Next.js builder@vercel/blob,@vercel/kv,@vercel/postgres,@vercel/redis— storage SDKs paired with Vercel Marketplace integrations@vercel/sdk— JavaScript SDK for the REST API (programmatic alternative to shelling out to the CLI)@vercel/og— Open Graph image generation for Vercel runtimes@vercel/analytics,@vercel/speed-insights— drop-in client SDKs
Most apps never install these directly — Vercel-aware frameworks (Next.js, SvelteKit, Astro, Nuxt) handle the integration through their own adapter packages.
Alternatives#
vercel is the deploy CLI for Vercel. There is no second-party alternative. For other platforms:
| Tool | Platform |
|---|---|
wrangler | Cloudflare Workers / Pages |
netlify-cli | Netlify — Functions, Edge Functions, Forms |
flyctl | Fly.io — full VMs + edge regions |
aws-cdk / sst / sam | AWS Lambda + edge via CloudFront |
firebase | Firebase Hosting + Functions |
gcloud run deploy | Google Cloud Run |
azure functions core tools | Azure Functions |
deno deploy | Deno Deploy — Deno-native edge runtime |
render (web UI + Git integration) | Render — full apps + static |
For multi-cloud setups, frameworks like Astro, SvelteKit, and Next.js (via OpenNext / open-next.js.org) publish adapters that retarget the same source onto a competitor’s CLI.
Common gotchas#
- Project linking is per-directory, not per-repo.
.vercel/project.jsonis written into the current working directory. A monorepo with multiple deployable apps needsvercel linkrun once per app folder; otherwise deploys go to whichever project the root was linked to last. vercel deployandvercel --prodare NOT the same. Without--prodyou get a preview deploy with a unique URL; with--prod, the active deployment alias updates. Many teams have leaked staging features to prod by passing--prodreflexively in CI.vercel env pulloverwrites your.env.local. It writes the file without confirmation. Back up local-only overrides before pulling, or use--environment=development/--environment=preview/--environment=productionexplicitly to scope.- Git-integrated auto-deploys race with manual
vercel deploy --prod. A push and a manual deploy can complete in either order. Either disable the Git integration’s production branch deploy, or stop usingvercel --prodfrom local machines. vercel.jsonprecedence vs framework config. Settings invercel.jsonoverride framework defaults silently. Customheaders,redirects,rewritesin framework config (next.config.js,astro.config.mjs) plusvercel.jsonproduce a merged result that’s hard to predict — keep them in one place.vercel devis NOT the same asnext dev.vercel devruns the full Vercel build pipeline locally including Functions routing and rewrites — slower but production-faithful. Frameworks’ own dev servers are faster but skip routing rules fromvercel.json.- Function concurrency is unbounded by default. Serverless / Edge functions scale per request; a misbehaving function can run up surprise bills. Use the
maxDurationandconcurrencyconfig invercel.jsonand watch the dashboard’s spend caps. - Aliases vs domains. A deployment URL (
my-app-abc123.vercel.app) is permanent. The “production” URL is an alias pointed at the latest production deployment. Rollback works by re-aliasing, not by re-deploying.
Real-world recipes#
These recipes target deploy-time setup — environments, aliases, env-var sync, and rollback — rather than framework-internal patterns.
One-shot deploy from a clean clone#
The shortest path to production from a fresh checkout:
vercel login # opens browser for OAuth
vercel link # pick or create a project
vercel deploy # preview deploy (unique URL)
vercel deploy --prod # production deploy
Output: each command prints the deployed URL. The preview URL is permanent and shareable.
Preview vs production deploys#
vercel deploy defaults to a preview environment with a deploy-specific subdomain. Use --prod to promote.
vercel deploy # preview: alice-api-abc123.vercel.app
vercel deploy --prod # production: alice-api.vercel.app
vercel deploy --prebuilt --prod # use a pre-built output (faster, see "vercel build")
Output: deployment URL printed to stdout (single line — pipe to awk to capture).
Env-var management#
Env vars live in the Vercel dashboard, scoped per environment. The CLI mirrors them.
vercel env ls # list all vars across envs
vercel env add DATABASE_URL production # prompts for the value
vercel env add STRIPE_KEY preview development # multiple envs at once
vercel env rm DEBUG production
Output: each command prints the affected variable; add requires the value via stdin or interactive prompt.
For pulling secrets to a local .env.local for next dev / astro dev:
vercel env pull .env.local # development env by default
vercel env pull .env.production --environment=production
Output: writes the file; lists how many vars were pulled.
Link a directory to an existing project#
When you clone a repo on a new machine:
vercel link # interactive — pick from your projects
vercel link --project my-project --yes # non-interactive (good for CI)
Output: writes .vercel/project.json (gitignored) with org + project IDs.
For monorepos with multiple apps, run vercel link once per app folder. Keep .vercel/ in .gitignore.
Custom build settings#
vercel.json at the project root controls build, routing, and runtime config:
{
"$schema": "https://openapi.vercel.sh/vercel.json",
"buildCommand": "pnpm run build",
"outputDirectory": ".vercel/output",
"installCommand": "pnpm install --frozen-lockfile",
"framework": "astro",
"regions": ["iad1", "fra1"],
"headers": [
{
"source": "/static/(.*)",
"headers": [{ "key": "Cache-Control", "value": "public, max-age=31536000, immutable" }]
}
],
"rewrites": [
{ "source": "/api/(.*)", "destination": "https://upstream.example.com/api/$1" }
]
}
Settings in the dashboard win over vercel.json for inputs (build command, install command). Settings in vercel.json win for routing (rewrites, headers, redirects).
Rollback to a previous deployment#
Vercel doesn’t expose vercel rollback (as of mid-2026) — rollback is re-aliasing.
vercel ls # see recent deploys
vercel alias set <previous-deployment-url> <production-domain>
Output: the alias is repointed instantly; the previous code is live within seconds.
You can also promote any preview to production via the dashboard’s three-dot menu — useful when the CLI session is on a different machine.
Promote a preview to production#
vercel promote <preview-deployment-url>
Output: alias of the production domain updates to point at the chosen deployment.
This is the safe way to ship — deploy a preview, exercise it, then promote without rebuilding.
Production deployment#
Vercel is the production target itself; “production deployment” here means the deploy hygiene around the platform.
CI deploy with tokens#
In CI, authenticate with a token (Vercel dashboard → Account Settings → Tokens) instead of vercel login:
- run: npm install --global vercel@latest
- run: vercel pull --yes --environment=production --token=$VERCEL_TOKEN
- run: vercel build --prod --token=$VERCEL_TOKEN
- run: vercel deploy --prebuilt --prod --token=$VERCEL_TOKEN
env:
VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
The pull → build → deploy --prebuilt flow avoids running the build twice (once locally for verification, once on Vercel). The token + org-ID + project-ID triple replaces interactive linking.
Preview deploys per PR#
The official GitHub integration handles this automatically. To do it manually (other Git hosts, custom CI):
- run: vercel deploy --token=$VERCEL_TOKEN --meta git-branch=$BRANCH > url.txt
- run: gh pr comment $PR --body "Preview: $(cat url.txt)"
Regions and edge#
regions: ["iad1"] in vercel.json pins serverless Function execution to a single region. The Vercel Edge runtime always runs at the nearest PoP regardless. For data residency, scope regions carefully — they affect where logs and request bodies are processed.
Custom domains and certificates#
vercel domains add example.com
vercel domains inspect example.com # see DNS instructions
vercel certs ls # certificates
Output: Vercel prints the DNS records you must add at your registrar. After DNS propagates, Vercel issues a Let’s Encrypt cert automatically.
Performance tuning#
vercel build+vercel deploy --prebuiltlets CI build once and upload the output, instead of asking Vercel to build remotely. Cuts deploys to 5–15 seconds.- Region selection. Pin Functions to the region closest to your database. The default (
iad1) is fine if your data lives in AWS us-east-1; otherwise expect 50–200 ms of round-trip on every cold start. - Edge over Node for stateless work. Edge Functions start in single-digit milliseconds; Node Functions start in 100–500 ms cold. Latency-sensitive endpoints prefer Edge unless they need Node-specific APIs.
maxDurationper route. Set invercel.jsonor per-Function. Long requests block other invocations on the same container.- Build caching. Vercel caches
node_modules, framework caches (.next/cache,.svelte-kit/cache), and CDN assets between builds. Don’t accidentally invalidate them — frequentpackage.jsonchurn busts the cache. - ISR / on-demand revalidation. For Next.js, prefer
revalidateover re-deploying for content changes.
Version migration guide#
The CLI ships rapidly and rarely has hard breaking changes — but a few major versions tightened defaults. Check the official changelog at vercel.com/changelog for your specific versions before upgrading.
| From | To | Likely changes (verify against the changelog) |
|---|---|---|
vercel@32 | vercel@33 | Node 18+ floor; legacy now.json removed in favour of vercel.json (deprecated for years but finally rejected). |
vercel@39 | vercel@40 | vercel build output path stabilised; --prebuilt recommended for CI. |
vercel@43 | vercel@44+ | Node 20+ floor; tightened token scopes for deploys. |
Recommended upgrade flow:
- Bump CLI in a branch (locally and in CI):
npm install -g vercel@latest. - Run
vercel deploy --dry-run(if available for your version) or a preview deploy on a throwaway project. - Verify
vercel.jsonparses — schema is occasionally tightened between majors. - Refresh tokens at the same time; old tokens may lack permissions a new CLI expects.
ESM/CJS interop & bundling#
vercel is a CLI; the interop concerns are about the Functions it deploys, not the CLI binary.
| Concern | Pattern |
|---|---|
| Function module format | Node Functions on the nodejs20.x / nodejs22.x runtime support both ESM and CJS. package.json "type" controls the default. |
| Edge Function format | ESM only, with a runtime: "edge" export. No Node built-ins; restricted Web-API surface. |
| Next.js App Router | Server Components are ESM. Route Handlers detect ESM/CJS automatically. |
| Native modules | Functions cannot ship native bindings beyond what’s on the AWS Lambda base image. Audit any node-gyp deps before deploying. |
| Bundle size limit | 50 MB unzipped per Function (and 250 MB unzipped including layers). Vercel reports size at deploy; over-limit fails the upload. |
| Tree-shaking | Vercel’s builder uses nft (node-file-trace) to ship only the files a Function actually reads. ESM imports tree-shake automatically; dynamic require() is conservative. |
Plugin & ecosystem coverage#
Vercel’s “ecosystem” is the Marketplace (storage, auth, CMS, monitoring) plus framework adapters.
| Service | Purpose |
|---|---|
| Vercel Blob | S3-style object storage with edge CDN. Pairs with @vercel/blob. |
| Vercel KV | Redis-compatible KV (powered by Upstash). @vercel/kv. |
| Vercel Postgres | Neon-backed serverless Postgres. @vercel/postgres. |
| Vercel Edge Config | Read-only config replicated globally with sub-ms reads. |
| Marketplace integrations | Supabase, Neon, Upstash, MongoDB, Clerk, Auth0, Sentry, Resend, Stripe (provisioned via the Marketplace; env vars injected automatically). |
| Vercel Analytics | First-party RUM (@vercel/analytics). |
| Speed Insights | Core Web Vitals tracking (@vercel/speed-insights). |
| AI SDK / AI Gateway | ai package + Vercel AI Gateway for model routing. |
| Cron Jobs | Scheduled Function invocations. Declared in vercel.json. |
| Workflows (WDK) | Durable, pause/resume workflows on the Vercel platform. |
| Framework adapter | Notes |
|---|---|
next | First-class — Next.js is Vercel’s framework. |
@astrojs/vercel | Astro SSR / static / edge adapter. |
@sveltejs/adapter-vercel | SvelteKit adapter. |
nuxt (nitro-vercel) | Built into Nitro. |
@remix-run/vercel | Remix adapter. |
vike (formerly vite-plugin-ssr) | Generic Vite SSR adapter. |
Testing & CI integration#
The CLI doesn’t run tests itself; teams pair it with their framework’s test runner (Vitest, Jest, Playwright) and use the CLI only for the deploy step.
Pattern: test, then deploy, then smoke-test#
jobs:
ship:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 22 }
- run: npm ci
- run: npm test
- run: npm install --global vercel@latest
- run: vercel pull --yes --environment=production --token=$VERCEL_TOKEN
- run: vercel build --prod --token=$VERCEL_TOKEN
- id: deploy
run: echo "url=$(vercel deploy --prebuilt --prod --token=$VERCEL_TOKEN)" >> $GITHUB_OUTPUT
- run: curl -fsSL "${{ steps.deploy.outputs.url }}/api/health"
env:
VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
Programmatic deploys via the SDK#
For workflows that don’t fit a CLI (e.g. bulk preview from a queue), use @vercel/sdk:
import { Vercel } from "@vercel/sdk";
const client = new Vercel({ bearerToken: process.env.VERCEL_TOKEN });
const deployment = await client.deployments.createDeployment({
requestBody: {
name: "alice-api",
target: "production",
project: process.env.VERCEL_PROJECT_ID,
},
});
console.log(deployment.url);
Output: prints the deployment URL.
Security considerations#
- Tokens scope to the whole account by default. When generating an API token in the Vercel dashboard, scope it to a specific team and rotate every 90 days. Revoke immediately after CI provider migrations.
- Environment variables ≠ secrets. Vercel encrypts env vars at rest, but they’re visible in plaintext to anyone with project access. For high-value secrets, prefer integrations (HashiCorp Vault, AWS Secrets Manager via Marketplace) over plain env vars.
vercel env pullwrites plaintext locally. The resulting.env.localis unencrypted. Add.env*to.gitignoreand to your OS keychain integration if available.vercel.jsonis committed. Don’t put secret values there. Use env vars and reference them:"env": { "DATABASE_URL": "@database-url" }(the@references a vercel secret, not the literal value).vercel logsshows live request data. In some setups this includes auth headers or PII in URLs. Restrict access toteam:readfor production logs.- Public deployments are public. Every preview URL is reachable on the open internet unless you enable Deployment Protection (Vercel Pro+).
- Function input validation. Vercel Functions receive the raw request — there’s no platform-level WAF on the free tier. Use Vercel Firewall (paid) or framework-level middleware for rate limiting, auth, and input sanitisation.
- Domain verification. When adding a custom domain, the DNS proof is required before issuance. Don’t paste the verification record into a public ticket — it allows certificate hijacking until the domain DNS is fully cut over.
Troubleshooting common errors#
Error! Authentication token has expired — run vercel logout and vercel login again, or rotate VERCEL_TOKEN in CI.
Error! No existing credentials found — vercel login not run, or ~/.local/share/com.vercel.cli missing. Re-login.
Error! Could not find any framework configuration — wrong directory (e.g. you ran from the monorepo root instead of an app folder). cd into the app, re-link, redeploy.
Cannot find a project linked to the current directory — vercel link not run. Link and try again.
Deployment exceeds the maximum size limit — Function bundle too large. Inspect vercel build output for offenders (often full puppeteer or prismjs with all languages).
Error! Domain example.com is not assigned to your team — domain belongs to a different org. Move it via the dashboard or transfer ownership.
vercel dev shows different output than production — framework-level routing files (next.config.js middleware) vs vercel.json mismatch. Decide which owns routing and remove the other.
Function exceeded the maximum duration — bumped against maxDuration (default 10s on Hobby, 60s on Pro). Increase in vercel.json or refactor to a shorter Function.
vercel env pull fails silently / overwrites custom vars — it writes the whole file. Move local-only overrides to .env.local.user (not read by frameworks) before pulling.
When NOT to use this#
Skip vercel when:
- You aren’t deploying to Vercel. Single-vendor CLI; for Cloudflare use
wrangler, for Netlify usenetlify-cli, for AWS use CDK/SAM/SST. - You only use the GitHub-connected auto-deploy and never touch env vars or logs from CLI. Most teams still install it for
vercel env pulland rollback, but you can drive the platform entirely from the dashboard. - You’re on a corporate network that blocks Vercel egress. The CLI talks to
api.vercel.com; if outbound HTTPS to Vercel is blocked, every command fails. - You want full IaC. Pulumi and Terraform have community Vercel providers — useful if you want declarative project + env-var + domain management. You’d still use the CLI for
vercel devandvercel logs, but deploys live in IaC. - You self-host Next.js.
next starton your own VM doesn’t need Vercel at all. Some Vercel-specific features (ISR with on-demand revalidation, Edge Functions, Edge Config) only run on Vercel infrastructure.
See also#
- JavaScript: vercel — full command reference, deploy recipes, env management
- JavaScript: wrangler — peer CLI for Cloudflare’s edge platform
- JavaScript: npm — installing the CLI globally vs per-project
- Concept: api — REST API contracts underlying the CLI