# OpenAI key boundaries in Next.js

## Rules

1. The key lives in the server environment only. Never prefix it with
   `NEXT_PUBLIC_`; that prefix inlines the value into the client bundle at
   build time, which is the same as publishing it.
2. All OpenAI calls happen in route handlers, server actions, or server
   components. Client components call your route handler, never the OpenAI SDK.
3. Do not import the OpenAI client (or any module that constructs it at import
   time) from a client component, even indirectly. The import graph is what
   leaks, not just the variable.
4. For Realtime websocket endpoints, pin `export const runtime = "nodejs"`.
   Streaming and websocket code in route handlers needs the Node runtime; the
   edge runtime cannot hold the upstream socket the same way.

## The failure shape

The symptom is a key that works in development and gets abused in production:
client bundles are public, scrapers extract keys in minutes, and the bill
arrives before anyone notices. There is no alert for "key seen in bundle";
you have to check.

## Check before you ship

- `grep -r "NEXT_PUBLIC" --include="*.ts" --include="*.tsx"` for anything
  OpenAI-related; zero hits.
- Build the app and search the `.next/static` output for a fragment of a test
  key; it must not appear.
- Confirm every OpenAI SDK import resolves from server-only modules (route
  handlers, server components, files importing `server-only`).