Deploy preview environments for branches and pull requests. Every git push to a non-production branch generates a unique preview URL. Covers CLI-based previews, API-based previews, deployment protection, and comment integration.
vercel-install-auth setupvercel link
# Deploy current directory to a preview URL (default โ not --prod)
vercel
# Output:
# ๐ Linked to your-team/my-app
# ๐ Inspect: https://vercel.com/your-team/my-app/AbCdEfG
# โ
Preview: https://my-app-git-feature-branch-your-team.vercel.app
# Deploy a specific directory
vercel ./dist
# Deploy and wait for build to complete (useful in CI)
vercel --no-wait # returns immediately with deployment URL
# Create a deployment via API โ useful for custom CI pipelines
curl -X POST "https://api.vercel.com/v13/deployments" \
-H "Authorization: Bearer $VERCEL_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "my-app",
"target": "preview",
"gitSource": {
"type": "github",
"repoId": "123456789",
"ref": "feature/new-feature",
"sha": "abc123def456"
}
}'
# Poll deployment status until READY
curl -s -H "Authorization: Bearer $VERCEL_TOKEN" \
"https://api.vercel.com/v13/deployments/dpl_xxxxxxxxxxxx" \
| jq '{state: .state, url: .url, readyState: .readyState}'
# States: QUEUED โ BUILDING โ READY (or ERROR/CANCELED)
// Programmatic polling
async function waitForDeployment(client: VercelClient, deploymentId: string) {
while (true) {
const d = await client.getDeployment(deploymentId);
if (d.state === 'READY') return d;
if (d.state === 'ERROR' || d.state === 'CANCELED') {
throw new Error(`Deployment ${d.state}: ${deploymentId}`);
}
await new Promise(r => setTimeout(r, 5000)); // poll every 5s
}
}
# Add env vars scoped to preview only
vercel env add DATABASE_URL preview
# Enter value when prompted
# Or via API โ scope to preview environment
curl -X POST "https://api.vercel.com/v9/projects/my-app/env" \
-H "Authorization: Bearer $VERCEL_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"key": "DATABASE_URL",
"value": "postgres://preview-db:5432/myapp",
"type": "encrypted",
"target": ["preview"]
}'
Vercel supports password-protecting preview deployments:
// vercel.json โ require authentication for previews
{
"deploymentProtection": {
"preview": "vercel-authentication"
}
}
Options:
"vercel-authentication" โ requires Vercel team login"standard-protection" โ bypass for automation with x-vercel-protection-bypass headerWhen a GitHub repo is connected, Vercel automatically:
To configure in the Vercel dashboard:
# Ignored Build Step โ skip deploy when only docs changed
# vercel.json
{
"ignoreCommand": "git diff HEAD^ HEAD --quiet -- . ':!docs' ':!*.md'"
}
| Branch | URL Pattern |
|---|---|
feature/auth |
my-app-git-feature-auth-team.vercel.app |
fix/bug-123 |
my-app-git-fix-bug-123-team.vercel.app |
| Random deploy | my-app-abc123def.vercel.app |
| Error | Cause | Solution |
|---|---|---|
BUILD_FAILED |
Build command failed | Check build logs: vercel inspect <url> |
FUNCTION_INVOCATION_FAILED |
Runtime error in function | Review function logs: vercel logs <url> |
NO_BUILDS |
No output detected | Verify outputDirectory in vercel.json |
| Preview not updating | Cached old deployment | Force rebuild: vercel --force |
DEPLOYMENT_BLOCKED |
Deployment protection active | Use x-vercel-protection-bypass header |
For edge function development, see vercel-edge-functions.