---
name: vercel
description: Deploys applications to Vercel including serverless functions, edge functions, environment variables, and CI/CD. Use when deploying Next.js applications, frontend projects, or serverless APIs.
---
# Vercel
The frontend cloud platform for deploying web applications.
## Quick Start
**Install CLI:**
```bash
npm i -g vercel
```
**Deploy:**
```bash
vercel
```
**Deploy to production:**
```bash
vercel --prod
```
## Project Setup
### Connect Git Repository
1. Go to vercel.com/new
2. Import repository from GitHub/GitLab/Bitbucket
3. Configure build settings (auto-detected for most frameworks)
4. Deploy
### vercel.json Configuration
```json
{
"buildCommand": "npm run build",
"outputDirectory": "dist",
"installCommand": "npm install",
"framework": "nextjs",
"regions": ["iad1"],
"functions": {
"api/**/*.ts": {
"memory": 1024,
"maxDuration": 10
}
},
"rewrites": [
{ "source": "/api/:path*", "destination": "/api/:path*" }
],
"redirects": [
{ "source": "/old", "destination": "/new", "permanent": true }
],
"headers": [
{
"source": "/(.*)",
"headers": [
{ "key": "X-Frame-Options", "value": "DENY" }
]
}
]
}
```
## Environment Variables
### Setting Variables
**Via Dashboard:**
1. Project Settings > Environment Variables
2. Add key-value pairs
3. Select environments (Production, Preview, Development)
**Via CLI:**
```bash
vercel env add MY_VAR
vercel env ls
vercel env pull .env.local
```
### Environment Types
```typescript
// Production only
NEXT_PUBLIC_API_URL=https://api.example.com
// Preview (PR deployments)
NEXT_PUBLIC_API_URL=https://staging-api.example.com
// Development
NEXT_PUBLIC_API_URL=http://localhost:3001
```
### Using Variables
```typescript
// Next.js - server side
const apiKey = process.env.API_KEY;
// Next.js - client side (must be prefixed)
const publicUrl = process.env.NEXT_PUBLIC_API_URL;
```
## Serverless Functions
### API Routes (Next.js App Router)
```typescript
// app/api/users/route.ts
import { NextRequest, NextResponse } from 'next/server';
export async function GET(request: NextRequest) {
const users = await getUsers();
return NextResponse.json(users);
}
export async function POST(request: NextRequest) {
const body = await request.json();
const user = await createUser(body);
return NextResponse.json(user, { status: 201 });
}
```
### API Routes (Pages Router)
```typescript
// pages/api/users.ts
import type { NextApiRequest, NextApiResponse } from 'next';
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
if (req.method === 'GET') {
const users = await getUsers();
return res.json(users);
}
if (req.method === 'POST') {
const user = await createUser(req.body);
return res.status(201).json(user);
}
res.setHeader('Allow', ['GET', 'POST']);
res.status(405).end(`Method ${req.method} Not Allowed`);
}
```
### Standalone Functions
```typescript
// api/hello.ts
import type { VercelRequest, VercelResponse } from '@vercel/node';
export default function handler(req: VercelRequest, res: VercelResponse) {
return res.json({ message: 'Hello from Vercel!' });
}
```
### Function Configuration
```typescript
// app/api/heavy/route.ts
export const runtime = 'nodejs';
export const maxDuration = 60; // seconds
export const dynamic = 'force-dynamic';
export async function GET() {
// Long-running operation
}
```
## Edge Functions
### Edge Runtime
```typescript
// app/api/geo/route.ts
import { NextRequest, NextResponse } from 'next/server';
export const runtime = 'edge';
export async function GET(request: NextRequest) {
const country = request.geo?.country ?? 'Unknown';
const city = request.geo?.city ?? 'Unknown';
return NextResponse.json({
country,
city,
message: `Hello from ${city}, ${country}!`,
});
}
```
### Middleware
```typescript
// middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
export function middleware(request: NextRequest) {
// Check auth
const token = request.cookies.get('token');
if (!token && request.nextUrl.pathname.startsWith('/dashboard')) {
return NextResponse.redirect(new URL('/login', request.url));
}
// Add headers
const response = NextResponse.next();
response.headers.set('x-custom-header', 'value');
return response;
}
export const config = {
matcher: ['/dashboard/:path*', '/api/:path*'],
};
```
## Caching & ISR
### Static Generation with Revalidation
```typescript
// app/posts/page.tsx
export const revalidate = 3600; // Revalidate every hour
async function getPosts() {
const res = await fetch('https://api.example.com/posts', {
next: { revalidate: 3600 },
});
return res.json();
}
export default async function PostsPage() {
const posts = await getPosts();
return