APM

>Agent Skill

@thamjiahe/vercel-deployment

skilldevelopment

Deploy Next.js to Vercel with zero-config, manage environment variables, set up CI/CD pipelines, and optimize production performance. Apply when deploying to Vercel, configuring environments, or setting up CI/CD workflows.

Claude Opus 4.5, Claude Code v2.x
apm::install
$apm install @thamjiahe/vercel-deployment
apm::allowed-tools
ReadWriteEditBash
apm::skill.md
---
name: "Vercel Deployment"
description: "Deploy Next.js to Vercel with zero-config, manage environment variables, set up CI/CD pipelines, and optimize production performance. Apply when deploying to Vercel, configuring environments, or setting up CI/CD workflows."
allowed-tools: Read, Write, Edit, Bash
version: 1.1.0
compatibility: Claude Opus 4.5, Claude Code v2.x
updated: 2026-01-24
---

# Vercel Deployment

Systematic Vercel deployment ensuring fast, scalable, production-ready applications with CI/CD automation.

## Overview

This Skill enforces:
- Zero-config Next.js deployments
- Secure environment variable management
- Automated CI/CD pipelines (GitHub Actions)
- Preview deployments for every PR
- Production deployments on main branch merge
- Performance optimization

Apply when deploying to Vercel, configuring environments, or testing CI/CD workflows.

## Deployment Workflow

**Every deployment follows this process**:

```
Step 1: Connect GitHub repository

Step 2: Configure environment variables

Step 3: Set up CI/CD pipelines

Step 4: Trigger preview deployment (on PR)

Step 5: Merge and deploy production

Step 6: Monitor performance
```

## Step 1: Initial Connection

### Connect GitHub Repository

```bash
# 1. Visit https://vercel.com and login
# 2. Click "New Project"
# 3. Select GitHub repository
# 4. Vercel auto-detects Next.js
# 5. Click "Deploy"
```

**Vercel automatically detects**:
- Framework: Next.js
- Build command: `next build`
- Output directory: `.next`
- Install command: `npm install`

No configuration needed for basic setup.

### Verify Deployment

After deploy:
- Live at: `yourproject.vercel.app`
- Production domain: `yourdomain.com` (if configured)
- Preview URL provided in PR comments

## Step 2: Environment Variables

### Setup Variables

**MUST NOT**: Hardcode secrets in code or commit `.env` files.

### Local Development

Pull dev environment variables:

```bash
vercel env pull
```

This creates `.env.local` with variables from Vercel Development environment.

Add to `.gitignore`:
```
.env.local
.env.*.local
```

### Vercel Dashboard Configuration

1. Go to Project Settings → Environment Variables
2. Add variable for each environment:
   - **Development**: Local development only
   - **Preview**: Pull requests and branches
   - **Production**: Main branch deployments

### Variable Types

```
Regular: Visible in logs and build output
Sensitive: Hidden, only for production/preview
System: Vercel-provided (__VERCEL_*)
```

### Example Configuration

```
DATABASE_URL=postgresql://...        # All environments
NEXT_PUBLIC_API_URL=https://api....  # Public (prefixed with NEXT_PUBLIC_)
STRIPE_SECRET_KEY=sk_live_...        # Sensitive production only
```

### Accessing Variables

**Public variables** (client-side, prefixed `NEXT_PUBLIC_`):

```ts
// Available in browser
const apiUrl = process.env.NEXT_PUBLIC_API_URL;
```

**Secret variables** (server-side only):

```ts
// Only available on server
export async function getServerSideProps() {
  const dbUrl = process.env.DATABASE_URL;  // Server-side only
  return { props: {} };
}
```

**Anti-Pattern**:

```ts
// ❌ BAD: Hardcoded secrets
const apiKey = 'sk-1234567890';

// ❌ BAD: Committing .env
git add .env  // NEVER!

// ❌ BAD: Public secret key
const apiKey = process.env.STRIPE_SECRET_KEY;  // Exposed in browser!
```

## Step 3: CI/CD Pipeline Setup

### MUST NOT: Mention Claude/Anthropic

No automated footers, comments, or attributions to Claude or Anthropic in any generated code or documentation.

### GitHub Actions Workflow

Create `.github/workflows/production.yaml`:

```yaml
name: Vercel Production Deployment

env:
  VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
  VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}

on:
  push:
    branches:
      - main

jobs:
  Deploy-Production:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Install dependencies
        run: npm ci

      - name: Run linting
        run: npm run lint

      - name: Run tests
        run: npm run test

      - name: Build
        run: npm run build

      - name: Install Vercel CLI
        run: npm install -g vercel

      - name: Pull Vercel environment
        run: vercel pull --yes --environment=production --token=${{ secrets.VERCEL_TOKEN }}

      - name: Deploy to Production
        run: vercel deploy --prebuilt --prod --token=${{ secrets.VERCEL_TOKEN }}
```

### Preview Deployment

Create `.github/workflows/preview.yaml`:

```yaml
name: Vercel Preview Deployment

env:
  VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
  VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}

on:
  pull_request:

jobs:
  Deploy-Preview:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Install dependencies
        run: npm ci

      - name: Run linting
        run: npm run lint

      - name: Run tests
        run: npm run test

      - name: Build
        run: npm run build

      - name: Install Vercel CLI
        run: npm install -g vercel

      - name: Pull Vercel environment
        run: vercel pull --yes --environment=preview --token=${{ secrets.VERCEL_TOKEN }}

      - name: Deploy to Preview
        run: vercel deploy --prebuilt --token=${{ secrets.VERCEL_TOKEN }}
```

### Configure GitHub Secrets

Add to GitHub repository → Settings → Secrets and variables → Actions:

```
VERCEL_ORG_ID     # From vercel link command
VERCEL_PROJECT_ID # From vercel link command
VERCEL_TOKEN      # From Vercel account settings
```

### Linking Project

```bash
# Link project to Vercel
vercel link

# Creates .vercel/project.json with project and org IDs
# Copy these to GitHub Secrets
```

## Step 4: Preview Deployments

### Automatic PR Previews

When PR opens:
1. GitHub Actions triggers preview workflow
2. Code is tested, built, deployed
3. Preview URL added to PR comments
4. Team reviews in production-like environment
5. Unique URL for each PR: `project-pr-123.vercel.app`

### Workflow

```
Push to feature branch → GitHub Actions runs tests & builds

Deploy preview to Vercel

PR gets preview URL comment

Team reviews changes

Merge to main triggers production
```

## Step 5: Production Deployment

### Merge to Main

```bash
# After PR approval
git checkout main
git pull origin main
git merge feature-branch
git push origin main

# GitHub Actions automatically:
# 1. Runs linting
# 2. Runs tests
# 3. Builds project
# 4. Deploys to production
```

### Deployment Checklist

Before merging to main:

- [ ] All tests pass locally
- [ ] Linting passes
- [ ] TypeScript compiles
- [ ] Preview deployment tested
- [ ] No sensitive data in code
- [ ] Environment variables configured
- [ ] Performance optimizations applied

## Step 6: Performance Optimization

### Image Optimization

```tsx
// ✅ GOOD: Use next/image
import Image from 'next/image';

export function ProfileImage({ src, alt }) {
  return (
    <Image
      src={src}
      alt={alt}
      width={200}
      height={200}
      priority  // Load immediately
    />
  );
}

// ❌ BAD: Unoptimized HTML img
<img src={imageUrl} alt="profile" />
```

### Static Generation (ISR)

```ts
// ✅ GOOD: Incremental Static Regeneration
export const revalidate = 3600;  // Revalidate every 1 hour

export default async function Page() {
  const data = await fetch('https://api.example.com/data', {
    next: { revalidate: 3600 }
  });
  return <div>{data}</div>;
}
```

### Edge Functions

```ts
// ✅ GOOD: Run at edge (fastest response)
export const config = {
  runtime: 'edge'
};

export default async function middleware(request) {
  if (request.nextUrl.pathname === '/admin') {
    if (!request.headers.get('authorization')) {
      return new Response('Unauthorized', { status: 401 });
    }
  }
  return null;
}
```

### Bundle Analysis

```bash
# Analyze bundle size
npm run build

# Check what contributes to bundle
npm run analyze
```

## Anti-Patterns

```bash
# ❌ BAD: Push to main without tests
git push origin main

# ❌ BAD: Hardcoded API keys
const apiKey = 'sk-1234567890';

# ❌ BAD: No linting in pipeline
# Deploy without checking code quality

# ❌ BAD: Commit .env
git add .env

# ❌ BAD: No preview deployments
# Deploy to production without team review

# ❌ BAD: No environment variables separated
# Use same config for dev/preview/prod
```

## Verification Before Deployment

Before deploying to production:

- [ ] All GitHub Secrets configured (ORG_ID, PROJECT_ID, TOKEN)
- [ ] `.github/workflows/` files created (preview.yaml, production.yaml)
- [ ] Tests pass locally
- [ ] Linting passes
- [ ] Environment variables set in Vercel dashboard
- [ ] No hardcoded secrets in code
- [ ] `.env` files in `.gitignore`
- [ ] Preview deployment tested
- [ ] Performance optimized (images, bundle size)
- [ ] HTTPS enabled (automatic on Vercel)

## Common Commands

```bash
# Pull dev environment variables
vercel env pull

# Link project
vercel link

# Deploy preview
vercel deploy --prebuilt

# Deploy production
vercel deploy --prebuilt --prod

# View logs
vercel logs

# Run locally with production settings
vercel dev
```

## Troubleshooting

### Build Failures

```bash
# Check build logs in Vercel dashboard
# Verify environment variables set
# Run locally: npm run build
# Check for TypeScript errors: npx tsc --noEmit
```

### Environment Variable Not Found

```bash
# Verify variable exists in Vercel dashboard
# Check environment matches deployment (dev/preview/prod)
# For public variables, prefix with NEXT_PUBLIC_
# For server variables, only accessible in API routes or server functions
```

### Preview URL Not Working

```bash
# Verify GitHub Actions workflow passed
# Check workflow logs in GitHub Actions tab
# Confirm Vercel secrets set correctly
# Verify preview.yaml file exists
```

## Integration with Project Standards

Enforces deployment best practices:
- Zero-config Next.js deployment
- Secure secret management (S-5)
- Automated CI/CD pipeline
- Performance optimization
- Production-grade deployment workflow

## Resources

- Vercel Docs: https://vercel.com/docs
- Next.js Deployment: https://nextjs.org/learn/basics/deploying
- GitHub Actions: https://docs.github.com/en/actions
- Environment Variables: https://vercel.com/docs/projects/environment-variables
---

**Last Updated:** January 24, 2026
**Compatibility:** Claude Opus 4.5, Claude Code v2.x
**Status:** Production Ready

> **January 2026 Update:** This skill is compatible with Claude Opus 4.5 and Claude Code v2.x. For complex tasks, use the `effort: high` parameter for thorough analysis.