Claude API Vercel Deployment Tutorial (Next.js)
Deploying a Claude-powered app to Vercel involves three things most tutorials gloss over: where the API key lives, whether your route runs on the Node.js or Edge runtime, and how streaming responses behave once they leave your local machine. Get those three right and the deployment itself takes minutes.
This guide walks through a working Next.js App Router setup, from local development to a production deployment on Vercel, including the config that trips people up (timeouts, streaming, environment variable scoping).
Project Setup
Start with a fresh Next.js app or use an existing one:
npx create-next-app@latest claude-vercel-app
cd claude-vercel-app
npm install
Create an API route at app/api/chat/route.ts. This is the server-side code that talks to Claude — never call the Anthropic (or any LLM) API directly from client-side JavaScript, since that exposes your key in the browser bundle.
// app/api/chat/route.ts
export const runtime = "nodejs"; // or "edge" — see note below
export async function POST(req: Request) {
const { message } = await req.json();
const res = await fetch("https://api.anthropic.com/v1/messages", {
method: "POST",
headers: {
"content-type": "application/json",
"x-api-key": process.env.ANTHROPIC_API_KEY!,
"anthropic-version": "2023-06-01",
},
body: JSON.stringify({
model: "claude-3-5-sonnet-latest",
max_tokens: 1024,
messages: [{ role: "user", content: message }],
}),
});
const data = await res.json();
return Response.json(data);
}
Call this route from a client component with fetch("/api/chat", { method: "POST", body: ... }).
Environment Variables on Vercel
Local development uses .env.local, which Vercel ignores by design — it's gitignored and never uploaded. You need to set the variable separately in the dashboard:
- Open your project on vercel.com → Settings → Environment Variables
- Add the key (e.g.
ANTHROPIC_API_KEY) with its value - Choose which environments it applies to: Production, Preview, Development
- Redeploy — environment variable changes don't apply to already-built deployments
You can also set it via CLI:
vercel env add ANTHROPIC_API_KEY production
A common mistake is setting the variable only for Production and then wondering why preview deployments (from pull requests) fail with an auth error. Add it to all three scopes if you want previews to work.
Edge vs Node.js Runtime
Vercel functions can run on the standard Node.js runtime or the Edge runtime. This matters for a Claude API route:
- Node.js runtime: full compatibility, longer max execution time on paid plans, works with any npm package. Use this unless you have a specific reason not to.
- Edge runtime: lower cold-start latency, runs closer to the user, but has a stricter set of available APIs and a default 25-second execution cap on some plans.
For streaming chat responses, Edge is often preferred because it starts sending bytes to the client faster. But if your route does anything beyond a simple fetch — logging to a database, complex retry logic — Node.js is usually simpler to reason about.
Set the runtime explicitly at the top of your route file:
export const runtime = "edge";
Handling Streaming Responses
If you want Claude's response to stream token-by-token to the browser instead of waiting for the full completion, your route needs to proxy the stream rather than buffer it:
export const runtime = "edge";
export async function POST(req: Request) {
const { message } = await req.json();
const upstream = await fetch("https://api.anthropic.com/v1/messages", {
method: "POST",
headers: {
"content-type": "application/json",
"x-api-key": process.env.ANTHROPIC_API_KEY!,
"anthropic-version": "2023-06-01",
},
body: JSON.stringify({
model: "claude-3-5-sonnet-latest",
max_tokens: 1024,
stream: true,
messages: [{ role: "user", content: message }],
}),
});
return new Response(upstream.body, {
headers: { "content-type": "text/event-stream" },
});
}
Vercel supports this pattern natively on both runtimes — just make sure you don't accidentally await res.json() somewhere in the chain, which buffers the whole stream and defeats the purpose.
If you're building this for a product with multiple users or teams and want streaming, per-key usage metadata, and dashboard visibility without writing your own proxy layer, SubToAPI (/docs/streaming) gives you an HTTPS endpoint that handles the streaming plumbing so your Vercel route just forwards the request.
Deploying
Once your route works locally with npm run dev, deploy with:
vercel --prod
Or connect the GitHub repo in the Vercel dashboard for automatic deployments on every push. Vercel builds the app, applies your environment variables for the target environment, and gives you a production URL.
Check the Functions tab in the deployment logs if something fails — API errors from Anthropic (rate limits, invalid model names, malformed requests) show up there with the actual response body, which is more useful than the generic 500 Next.js shows in the browser.
Common Deployment Errors
- "ANTHROPIC_API_KEY is not defined" — the variable wasn't added to the environment you're testing (Preview vs Production), or you forgot to redeploy after adding it.
- Function timeout — long completions on the Node.js runtime can exceed the default execution limit on the Hobby plan. Either switch to streaming (so the client gets data immediately) or upgrade the plan.
- CORS errors calling your route from another domain — add explicit
Access-Control-Allow-Originheaders in your route response if the frontend isn't served from the same Vercel project. - Key exposed in client bundle — if you see the key in browser dev tools, you called the API directly from a client component instead of your server route. Move the call server-side.
Managing the API Key Across Environments
Teams often end up creating separate Anthropic keys per environment, then losing track of which one is live, which is staging, and who has access. If you want a single dashboard for issuing scoped API keys, streaming, and usage metadata across a team without managing raw provider keys in every environment variable panel, SubToAPI (/docs/quickstart) sits in front of your Claude access and gives each environment its own sub_live_... key you can revoke independently. Setup takes about the same steps as above — sign up (/signup), generate a key, drop it into Vercel's environment variables.
questions
Do I need a paid Vercel plan to run a Claude API route? No. The Hobby plan works for development and low-traffic apps, but it has stricter function timeout limits, which matters for long non-streaming completions. Streaming responses avoid most of that limitation.
Should I use the Edge or Node.js runtime for a chat route? Use Edge if you want lower latency and are only doing a simple fetch-and-stream. Use Node.js if your route needs npm packages, database writes, or more complex logic — it's more forgiving and easier to debug.
Why does my route work locally but fail after deploying to Vercel? Almost always an environment variable scoping issue — the key was added for Production but you're testing a Preview deployment, or it wasn't added at all. Check Settings → Environment Variables and redeploy after changes.