Day 5 of 5
⏱ ~50 minutes
React + AI — Day 5

Deploy to Vercel: From localhost to Live URL

A React AI app running on localhost isn't a product. Today you'll migrate from the Express server to Vercel serverless functions and deploy with a live URL you can share — in about 30 minutes.

Vercel Serverless Functions

Vercel runs API routes as serverless functions. Instead of an Express server, you create files in an api/ folder. Each file becomes an endpoint. Vercel handles deployment, scaling, and cold starts.

text — new project structure
my-ai-app/
├── api/                 ← Vercel API routes
│   ├── chat.js          ← POST /api/chat
│   └── upload.js        ← POST /api/upload
├── src/
│   ├── App.jsx
│   └── ...
├── public/
└── vite.config.js
javascript — api/chat.js
import Anthropic from '@anthropic-ai/sdk';

const client = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });

export default async function handler(req, res) {
  if (req.method !== 'POST') {
    return res.status(405).json({ error: 'Method not allowed' });
  }

  const { messages, system } = req.body;

  try {
    const response = await client.messages.create({
      model: 'claude-3-haiku-20240307',
      max_tokens: 1024,
      system: system || 'You are a helpful assistant.',
      messages: messages,
    });
    res.json({ content: response.content[0].text });
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
}
ℹ️
For streaming on Vercel, use the Edge Runtime: export const config = { runtime: 'edge' }. The Edge Runtime supports streaming responses directly. Standard Node.js functions don't support SSE.

Vercel Configuration

json — vercel.json
{
  "rewrites": [
    { "source": "/api/(.*)", "destination": "/api/$1" }
  ],
  "buildCommand": "npm run build",
  "outputDirectory": "dist"
}
json — vite.config.js (for local dev with Vercel)
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

export default defineConfig({
  plugins: [react()],
  server: {
    proxy: {
      '/api': 'http://localhost:3000'  // proxy to Vercel dev server
    }
  }
});

Deploy in 5 Steps

bash
# 1. Install Vercel CLI
npm install -g vercel

# 2. Login
vercel login

# 3. Link your project (run once from project root)
vercel link

# 4. Set environment variables
vercel env add ANTHROPIC_API_KEY

# 5. Deploy
vercel --prod

# You'll get a URL like: https://my-ai-app.vercel.app

Environment Variables in Production

Never commit API keys. Vercel stores them securely and injects them at runtime.

bash
# Add via CLI
vercel env add ANTHROPIC_API_KEY production

# Or add via Vercel dashboard:
# Project Settings → Environment Variables → Add

# Verify locally
vercel env pull .env.local  # pulls production vars to a local .env.local file
# Don't commit .env.local
⚠️
Add .env.local and .env to .gitignore before your first commit. If you accidentally commit an API key, rotate it immediately.

Custom Domain (Optional)

bash
# Add a domain you own
vercel domains add yourdomain.com

# Or use a free .vercel.app subdomain
# Your app is automatically at: project-name.vercel.app
📝 Exercise
Deploy Your App to Vercel
  1. Create the api/ folder and move your Express routes to Vercel serverless functions.
  2. Install and configure the Vercel CLI.
  3. Add ANTHROPIC_API_KEY as an environment variable in Vercel.
  4. Deploy with vercel --prod and open the generated URL.
  5. Test the deployed app — send a message and verify Claude responds.
  6. Share the URL with someone and have them test it.

Lesson Summary

  • Vercel API routes live in the api/ folder. Each file becomes a serverless endpoint.
  • Set environment variables via vercel env add or the dashboard — never in code.
  • Use the Edge Runtime for streaming responses: export const config = { runtime: 'edge' }.
  • Your app deploys on every push to the main branch once connected to GitHub.

Build the Full Stack in the Live Bootcamp

In 3 days you'll build a full-stack React AI app with authentication, a database, streaming, and deploy it with a custom domain. Denver, LA, NYC, Chicago, Dallas — October 2026.

Reserve Your Seat — $1,490
Challenge

Add a share button that copies the current conversation (formatted as text) to the clipboard. Then implement conversation persistence using localStorage so the chat history survives a page refresh.

Finished this lesson?