Keep Keys Server-Side

The most important production rule: your API key must never reach the browser.

This rule is worth its own lesson because breaking it is costly. Your API key must stay on the server. If it reaches the browser, anyone can read it and spend money on your account.

How keys leak

  • Calling Claude directly from frontend JavaScript.
  • Hardcoding the key in a source file that ships to the client.
  • Committing a .env file to a public repo.

The safe setup

  • Store the key in a server environment variable.
  • Call Claude only from backend code.
  • The browser calls your endpoint, which calls Claude.

Example

Example · javascript
// WRONG — never do this in browser code:
// const client = new Anthropic({ apiKey: "sk-ant-..." }); // key visible to everyone!

// RIGHT — browser calls YOUR server, key stays in the environment there:
async function askServer(question) {
  const res = await fetch("/api/ask", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ question }),
  });
  return (await res.json()).answer;
}

When to use it

  • Store ANTHROPIC_API_KEY in Vercel environment variables so it is never bundled into your Next.js client build.
  • Rotate a leaked key in the Anthropic Console and update the server env var without changing any application code.
  • Use a secrets manager like AWS Secrets Manager to inject the key at runtime instead of hardcoding it in .env files.

More examples

Read key from environment in Node

Shows the correct pattern (env var) and the dangerous anti-pattern (hard-coded string) side by side.

Example · javascript
import Anthropic from "@anthropic-ai/sdk";

// The SDK reads ANTHROPIC_API_KEY automatically — never hard-code it
const client = new Anthropic();

// This would be catastrophically wrong:
// const client = new Anthropic({ apiKey: "sk-ant-api03-..." });

Block the key from the browser bundle

In Next.js, only NEXT_PUBLIC_ vars are bundled into the client; omitting the key here keeps it server-side.

Example · javascript
// next.config.ts — expose ONLY public vars to the browser
const nextConfig = {
  // ANTHROPIC_API_KEY is NOT listed here — it stays server-only
  env: {
    NEXT_PUBLIC_APP_NAME: process.env.NEXT_PUBLIC_APP_NAME,
  },
};
export default nextConfig;

Fail fast if key is missing at startup

Validates the key exists at module load time so a missing secret surfaces immediately at startup, not mid-request.

Example · javascript
// src/lib/claude.ts
if (!process.env.ANTHROPIC_API_KEY) {
  throw new Error("ANTHROPIC_API_KEY environment variable is not set.");
}

export const client = new Anthropic();

Discussion

  • Be the first to comment on this lesson.