Next.js can connect an application to an OpenAI backend through a server-side Route Handler, keeping the API key out of browser code and returning either a complete response or a stream. The usual workflow is to store the key in an environment variable, call OpenAI from a Node.js handler, and have the client submit a request and read the response.
How the request flow works
A typical setup separates the user interface, your Next.js server, and OpenAI. The browser sends a request to an endpoint such as /api/chat; a Route Handler validates it and makes an authenticated server-to-server request to OpenAI. The handler then returns the result to the browser.
- Client: collects the user’s input and displays pending, complete, or error states.
- Route Handler: checks the request, applies application rules, calls the OpenAI API, and shapes the response.
- OpenAI backend: processes the request using the API credentials and model specified by the server.
This boundary matters: a key placed in client-side code can be extracted by visitors. A Next.js endpoint is not automatically private just because its code lives in the project; it still needs appropriate input validation, access controls where relevant, and sensible limits on costly operations.
Store API keys on the server
Set the credential in the environment that runs the Next.js server, commonly under a name such as OPENAI_API_KEY. For local development, a root-level .env.local file is a common option. Add that file to the project’s ignored files so it is not committed. In production, set the value using the hosting platform’s environment-variable settings or secret manager.
- Read the variable only in server-side code, such as a Route Handler or another server-only module.
- Do not prefix a secret with
NEXT_PUBLIC_. Next.js exposes variables with that prefix to browser bundles. - Do not print the key in logs, return it in an API response, or include it in error messages.
- After adding or changing local environment variables, restart the development server if the change is not picked up.
Use the OpenAI JavaScript SDK from server code when its current API supports the operation you need. A minimal handler can create a client with the environment variable and make a request. Keep the selected model and request options in server-controlled code where possible; do not assume that a value supplied by the browser is safe to use without checking it.
Create a Route Handler
In the App Router, a Route Handler is defined by a route.js or route.ts file inside an app directory. For example, app/api/chat/route.ts can export a POST function. The handler receives a Web Request and returns a Web Response, making it a natural place to validate JSON and call a backend service.
A practical sequence is:
- Parse the incoming body and reject malformed or missing fields with an appropriate 4xx response.
- Validate types, acceptable sizes, and any options the client is allowed to choose. Treat submitted text as untrusted input.
- Call OpenAI using the server-side credential. Handle upstream failures without exposing secrets or internal details.
- Return a JSON response for ordinary requests, or a streaming response when the interface needs incremental output.
For example, the client might send {"message":"Explain photosynthesis"} to /api/chat. The server should not blindly forward arbitrary request fields, accept unlimited input, or allow callers to select unrestricted backend operations. Route Handlers can be reached by anyone who can reach the deployed site unless the application adds an access check.
Return complete responses or stream
A standard request waits for the backend response and then returns JSON. This is simpler to implement and works well when the interface can show a loading indicator until completion. Streaming sends pieces as they become available, allowing the page to display text progressively and often making the interaction feel more responsive. It does not necessarily make the model finish generating sooner.
OpenAI streaming APIs commonly deliver server-sent events (SSE), but the exact SDK method and event structure depend on the API being used. Follow the current OpenAI API and SDK documentation rather than assuming every endpoint returns the same shape. A Next.js handler must preserve the stream correctly: read the upstream stream, encode or forward chunks in the expected format, and return suitable headers, often including Content-Type: text/event-stream for SSE.
On the client, use a compatible streaming reader or an event-source library suited to the response format. The browser’s native EventSource is designed for GET-based SSE connections and does not directly provide a general way to send a JSON POST body. For a POST workflow, a fetch-based reader is often more appropriate. Also handle stream completion, cancellation, malformed chunks, and errors that occur after the response has begun; an HTTP status alone cannot describe every mid-stream failure.
Deploy and configure the backend
Deployment requires both the application and its secret to be configured in the target environment. Add the API key to the deployment environment-variable settings, then redeploy if the platform requires a new build or runtime instance to load updated variables. Never rely on a local .env.local file being present in production.
Check the hosting platform’s runtime and response limits before choosing a streaming design. Route Handlers can run in different runtimes, and Node-specific SDK features may not work in every runtime. Select a runtime compatible with the SDK and dependencies you use; do not change to an edge runtime solely on assumption that it is faster. Test streaming through the actual deployed path, since proxies or platform buffering can affect when chunks reach the browser.
For production, consider authentication or other access controls, request-size limits, rate limiting, timeouts, and usage monitoring. These controls help prevent accidental or abusive consumption. Avoid logging full prompts or generated content unless the application has a clear, appropriate reason and handles that data accordingly.
Common problems and useful checks
- Missing-key errors: confirm the variable name and deployment environment, then restart locally or redeploy as needed.
- Key exposed in browser tools: remove the secret from client code and use a server-side handler. Rotate a credential if it has been exposed.
- 401 or permission errors: verify that the credential is valid and has the access required for the requested API operation.
- Unexpected 404: check the Route Handler’s directory and filename, HTTP method, and request URL.
- Stream appears all at once: inspect the response format and client reader, then test whether the hosting path buffers data.
- Works locally, fails after deployment: check environment-variable configuration, runtime compatibility, and platform execution limits.
A frequent misconception is that using a server route alone prevents misuse. It protects the secret from being shipped to the browser, but a public endpoint can still be called by third parties. Protecting the key and controlling who can consume the endpoint are separate tasks.
Frequently Asked Questions
Can I call OpenAI directly from a Next.js client component?
No, not with a private API key. Put authenticated OpenAI calls in server-side code so the key is not included in browser-delivered JavaScript.
Where should I put the API key in Next.js?
Use a server-side environment variable such as OPENAI_API_KEY. Keep it out of NEXT_PUBLIC_ variables, source control, and client components.
Do I need a Route Handler?
A Route Handler is a common way for a browser client to reach your server-side OpenAI call in the App Router. Other server-side patterns may fit a particular application, but the credential must remain server-side.
Does streaming require a different OpenAI key?
Usually the same credential is used; streaming is a response mode supported by the relevant API operation. Check that operation’s current documentation and configure both server and client to handle its stream format.
Why does streaming work locally but not after deployment?
Possible causes include response buffering, runtime incompatibility, proxy behavior, or platform time limits. Test the deployed endpoint and verify its runtime and streaming support.
Is a Next.js API route automatically protected?
No. It keeps server-only code out of the browser, but the endpoint may still be publicly reachable. Add suitable authentication, validation, and usage controls for the application.
Related
Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.
More cards in this drawer
- Secure a Node.js API: Layered Checklist
- Zoom Desktop Client: Features, Setup, and Fixes
- Python Integer Identity: Why It Varies by Run
- Can Technology Solve Poverty? Facts & Limits
- Wireless Controller Charging: Can You Play While Plugged In?
- Cannot Detect Device? Fixes for USB & Bluetooth