---
title: "Deploy to Vercel"
description: "Deploy your Slack bot to Vercel, configure environment variables, handle the URL verification challenge, and update your manifest for production. This lesson takes your bot from local development to a live production environment."
canonical_url: "https://vercel.com/academy/slack-agents/deploy-to-vercel"
md_url: "https://vercel.com/academy/slack-agents/deploy-to-vercel.md"
docset_id: "vercel-academy"
doc_version: "1.0"
last_updated: "2026-04-09T09:30:37.478Z"
content_type: "lesson"
course: "slack-agents"
course_title: "Slack Agents on Vercel with the AI SDK"
prerequisites:  []
---

<agent-instructions>
Vercel Academy — structured learning, not reference docs.
Lessons are sequenced.
Adapt commands to the human's actual environment (OS, package manager, shell, editor) — detect from project context or ask, don't assume.
The lesson shows one path; if the human's project diverges, adapt concepts to their setup.
Preserve the learning goal over literal steps.
Quizzes are pedagogical — engage, don't spoil.
Quiz answers are included for your reference.
</agent-instructions>

# Deploy to Vercel

# Deploy Your Bot to Production on Vercel

Running `slack run` locally is fine for development, but your bot needs to be available 24/7. When a major incident hits and the team needs instant AI assistance, your bot better be online. Production deployment means real URLs, proper secrets management, and zero downtime during Slack's URL verification handshake.

## Outcome

Deploy your bot to Vercel with working event handling, proper environment variables, and a verified Slack Events URL.

## Fast Track

1. Link or create your Vercel project and deploy: `pnpm dlx vercel --prod`
2. Update manifest with production URLs and reinstall
3. Verify bot responds in a real Slack channel

## Deployment Pipeline

```
┌─────────────────────────────────────────────────────────────────┐
│                    Local → Production Flow                     │
└─────────────────────────────────────────────────────────────────┘

Local Development                Production Deployment
        ↓                               ↓
┌─────────────────┐                ┌─────────────────┐
│ slack run       │                │ pnpm dlx vercel │
│ (ngrok tunnel)  │                │    --prod       │
└─────────────────┘                └─────────────────┘
        ↓                               ↓
┌─────────────────┐                ┌─────────────────┐
│ manifest.json   │   UPDATE URLs  │ manifest.json   │
│ localhost:3000  │ ──────────────→│ yourapp.vercel  │
│                 │                │     .app        │
└─────────────────┘                └─────────────────┘
        ↓                               ↓
┌─────────────────┐                ┌─────────────────┐
│ Test locally    │                │ Slack URL       │
│ @bot ping       │                │ Verification    │
│ ✓ works         │                │ Challenge       │
└─────────────────┘                └─────────────────┘
                                           ↓
                                   ┌─────────────────┐
                                   │ Production      │
                                   │ Bot Live        │
                                   │ @bot ping ✓     │
                                   └─────────────────┘

Environment Variables Flow:
Local: .env file → process.env
Production: Vercel Dashboard → Function runtime
```

## Building on Previous Lessons

This deployment brings together every pattern from the course into production:

- **From [Project Setup](./sandbox-repo-setup-smoke-test)**: You already have your own repo (and likely a Vercel project from the Deploy button); now you'll make that deployment production-ready
- **From [repository flyover](./repository-flyover)**: Stateless request-response architecture enables horizontal scaling - Vercel can spawn thousands of function instances
- **From [correlation middleware](./bolt-nitro-middleware-and-logging)**: Correlation middleware tracks requests across distributed function executions
- **From [ack semantics](./acknowledgment-and-latency)**: Ack-first pattern prevents timeouts in serverless environments with cold starts
- **From [slash commands](./slash-commands)**: All interaction surfaces (commands, shortcuts, modals) work identically in serverless
- **From [AI tools](./ai-tools-and-functions)**: Active context fetching and tool calls (no shared memory) are essential for stateless functions
- **From [system prompts](./system-prompts-shape-behavior)**: AI orchestration with retries, status, and fallbacks handles real production traffic
- **Production reality**: Each Slack event spawns a fresh function execution - zero shared state, perfect for serverless deployment

## Hands-On Exercise 5.1

Deploy your bot to Vercel and verify it handles production traffic:

**Requirements:**

1. Deploy to Vercel with all environment variables
2. Update manifest URLs to point to production domain
3. Pass Slack's URL verification challenge
4. Verify bot responds to mentions in a public channel
5. Check logs show correlation IDs and structured data

**Implementation hints:**

- Vercel automatically exposes env vars to your app
- The `/api/slack/events` route must handle both verification and events
- Watch for the verification challenge in Vercel Function logs
- Test with a real `@mention` in a non-DM channel

**Environment variables needed:**

```bash
SLACK_BOT_TOKEN=xoxb-...
SLACK_SIGNING_SECRET=...
```

For production you may be using a **different** Slack app than your sandbox one (for example, if `slack manifest update` created a new app). In any case, get the correct secrets from your Slack app config at `https://api.slack.com/apps`:

- **Signing Secret**: App → **Basic Information** → **App Credentials**
- **Bot token**: App → **Install App** → **Bot User OAuth Token**

\*\*Note: AI Gateway Auth in Production\*\*

In local development, you configure `AI_GATEWAY_API_KEY` so the AI SDK can talk to Vercel AI Gateway. In production on Vercel, the **recommended path** is to rely on the platform’s automatically generated **OIDC token** – the AI SDK will pick this up as long as you use plain string model IDs (for example, `'openai/gpt-4.1'` or `'xai/grok-3'`) and have Gateway enabled for the project.

Sharp edges to watch out for:

- You **won’t** see the OIDC token in `process.env` – it’s injected at the platform/runtime level.
- If you set `AI_GATEWAY_API_KEY` in production, Gateway will use that key instead of OIDC (which is fine, but now you own key rotation).
- Make sure you’re deploying to the same Vercel project you configured Gateway for, or you’ll see auth errors even though “it works locally”.

To inspect this behavior later:

- Open your project’s security settings: [Secure Backend Access with OIDC Federation](https://vercel.com/d?to=%2F%5Bteam%5D%2F%5Bproject%5D%2Fsettings%2Fsecurity\&title=Secure+Backend+Access+with+OIDC+Federation)
- Open the AI Gateway dashboard: [AI Gateway Dashboard](https://vercel.com/d?to=%2F%5Bteam%5D%2F%5Bproject%5D%2Fai%2Fgateway\&title=AI+Gateway)

See the official docs for details: [AI Gateway Authentication – OIDC token](https://vercel.com/docs/ai-gateway/authentication#oidc-token) and this AI SDK course's setup guide’s Gateway step ([AI SDK dev setup – Step 4](https://vercel.com/academy/ai-sdk/ai-sdk-dev-setup#step-4-setting-up-the-vercel-ai-gateway)).

## Try It

1. **Deploy to Vercel (link or create project):**

   ```bash
   pnpm dlx vercel --prod
   ```

   Expected output:

   ```
   Vercel CLI 28.5.5
   ? Set up and deploy "<PATH_TO_YOUR_REPO>"? [Y/n] y
   ? Which scope do you want to deploy to? Your Team
   # If you already created a project via the Deploy with Vercel button, choose that existing project here.
   # Otherwise, create a new project for this repo.
   ? What's your project's name? slack-bot-prod
   ? In which directory is your code located? ./
   Auto-detected Project Settings (Nitro):
   - Build Command: npm run build
   - Output Directory: .output
   - Development Command: npm run dev
   ? Want to override the settings? [y/N] n
   🔗 Linked to yourteam/slack-bot-prod (created .vercel)
   🔍 Inspect: https://vercel.com/yourteam/slack-bot-prod/abc123
   ✅ Production: https://slack-bot-prod.vercel.app [21s]
   ```

2. **Update manifest.json:**
   ```json
   {
     "features": {
       "app_home": {
         "home_tab_enabled": false,
         "messages_tab_enabled": true
       }
     },
     "oauth_config": {
       "scopes": {
         "bot": [
           "app_mentions:read",
           "channels:history",
           "chat:write",
           "groups:history",
           "im:history",
           "mpim:history"
         ]
       }
     },
     "settings": {
       "event_subscriptions": {
         "request_url": "https://<your-app-domain>.vercel.sh/api/slack/events",
         "bot_events": ["app_mention", "message.channels", "message.groups", "message.im", "message.mpim"]
       }
     }
   }
   ```

3. **Reinstall app and verify URL:**

   ```bash
   slack manifest update
   slack install
   ```

   In Slack App config, you'll see:

   ```
   Request URL: https://<your-app-domain>.vercel.sh/api/slack/events
   Your URL has been verified ✓
   ```

4. **Test in production channel:**
   ```
   You: @bot-name what's the deployment status?

   Bot: I'm successfully deployed to production! Here's my status:
   - Environment: Production (Vercel)
   - Correlation ID: ev09E5EDA89M_1234567890.123456
   - Response time: 1.2s
   - All systems operational ✓
   ```

5. **Verify logs in Vercel dashboard:**
   ```
   [INFO] bolt-app {
     correlationId: 'ev09E5EDA89M_1234567890.123456',
     event_id: 'Ev09E5EDA89M',
     type: 'app_mention',
     channel: 'C09D4DG727P',
     thread_ts: '1234567890.123456',
     user: 'U0123ABCDEF'
   } Processing app_mention event

   [INFO] bolt-app {
     correlationId: 'ev09E5EDA89M_1234567890.123456',
     operation: 'respondToMessage',
     model: 'openai/gpt-4o-mini',
     promptTokens: 156,
     completionTokens: 47,
     latencyMs: 892
   } AI response generated successfully
   ```

## Troubleshooting

**URL Verification Fails:**

- Check your signing secret is correctly set in Vercel env vars
- Ensure the route is `/api/slack/events` (not `/api/events`)
- Look for the challenge parameter in Vercel Function logs

**Bot Doesn't Respond:**

- Verify `SLACK_BOT_TOKEN` starts with `xoxb-`
- Check bot is in the channel (invite with `/invite @bot-name`)
- Confirm manifest has `app_mentions:read` scope

**Environment Variables Missing:**

```bash
# List current env vars for your project
pnpm dlx vercel env ls

# Add missing Slack secrets (production)
pnpm dlx vercel env add SLACK_BOT_TOKEN production
pnpm dlx vercel env add SLACK_SIGNING_SECRET production

# (Optional) Add AI gateway key if you want to override OIDC-based auth
pnpm dlx vercel env add AI_GATEWAY_API_KEY production
```

## Commit

```bash
git add -A
git commit -m "feat(deploy): production deployment to Vercel with URL verification

- Configure Vercel deployment with Nitro preset
- Update manifest URLs to production domain  
- Handle Slack URL verification challenge
- Verify bot responds in production channels
- Structured logs with correlation IDs working"
```

## Done-When

- [x] Bot deployed to Vercel and accessible via public URL
- [x] Slack Events URL verified (green checkmark in app config)
- [x] Bot responds to mentions in production channel
- [x] Logs show correlation IDs and structured fields
- [x] All environment variables properly configured

## Solution

The key parts for production deployment:

1. **Vercel deployment command:**

```bash
pnpm dlx vercel --prod
```

2. **Updated manifest.json with production URL:**

````json title="/slack-agent/manifest.json" {15}
```json title="/slack-agent/manifest.json" {15}
{
  "display_information": {
    "name": "AI Assistant Bot",
    "description": "Production AI assistant with context awareness",
    "background_color": "#1a1a2e"
  },
  "features": {
    "app_home": {
      "home_tab_enabled": false,
      "messages_tab_enabled": true
    }
  },
  "settings": {
    "event_subscriptions": {
      "request_url": "https://<your-app-domain>.vercel.sh/api/slack/events",
      "bot_events": [
        "app_mention",
        "message.channels",
        "message.groups",
        "message.im",
        "message.mpim"
      ]
    }
  },
  "oauth_config": {
    "scopes": {
      "bot": [
        "app_mentions:read",
        "channels:history",
        "chat:write",
        "groups:history",
        "im:history",
        "mpim:history"
      ]
    }
  }
}
````

3. **Environment variables in Vercel:**
   All secrets are added through Vercel dashboard or CLI:

```bash
pnpm dlx vercel env add SLACK_BOT_TOKEN production
pnpm dlx vercel env add SLACK_SIGNING_SECRET production
```

4. **Verification of deployment:**
   Check Function logs in Vercel dashboard for:

- URL verification challenge handled
- Events being received
- Correlation IDs in structured logs
- Response times under 3 seconds

\*\*Side Quest: Zero-Downtime Deployment Pipeline\*\*

## Key Takeaways

- Production deployment requires proper URL configuration in both Vercel and Slack
- The URL verification handshake must complete within 3 seconds
- Environment variables must be set in Vercel, not just locally
- Structured logging with correlation IDs is essential for debugging production issues
- Always test in a real channel after deployment


---

[Full course index](/academy/llms.txt) · [Sitemap](/academy/sitemap.md)
