Build a Next.js Chatbot with OpenAI Responses API
Create a small, working web chatbot with the Next.js App Router, the official OpenAI JavaScript SDK, and the Responses API. The browser sends a message to your own server route; that route, not the browser, calls OpenAI.
What you will build
This tutorial builds a request-and-response chatbot. A visitor writes a message, Next.js posts it to /api/chat, and the server route calls the OpenAI Responses API. The returned text is appended to the chat window. This is deliberately a compact foundation: it proves the data flow and protects the API key without pretending to include production features such as user accounts, saved conversations, streaming, or a knowledge base.
The verified OpenAI developer resources surface the Responses API, conversation state, streaming, token counting, background mode, webhooks, and a migration guide as separate topics. That separation matters. A basic chatbot does not need every advanced capability on day one. Start with a reliable server-side call, then choose conversation state, streaming, and other features only when a product requirement justifies them.
The example selects gpt-5.6, which appears in the current OpenAI developer resource navigation. The model is configured through an environment variable so the application code does not need to change when your team adopts a different permitted model.
Prerequisites
- Node.js 18 or later.
- An OpenAI API key available through your OpenAI platform account.
- Basic familiarity with JavaScript, React, and the command line.
- A new or existing Next.js project using the App Router.
Do not put an OpenAI key in client-side code, a component marked with 'use client', a public repository, or an environment variable beginning with NEXT_PUBLIC_. Variables with that prefix are designed for browser exposure. In this project, only the route handler reads OPENAI_API_KEY.
Step 1: Create the Next.js project
Create a fresh application, enter its directory, and install the official OpenAI JavaScript SDK. When prompted by create-next-app, choose JavaScript and enable the App Router. The code below assumes the default app directory structure.
npx create-next-app@latest nextjs-openai-chatbot
cd nextjs-openai-chatbot
npm install openai
npm run devOpen http://localhost:3000. The starter screen confirms that Next.js is running before you add any AI integration. Stop the server with Ctrl+C before changing configuration if your local workflow requires it.
The resulting files relevant to this tutorial are:
nextjs-openai-chatbot/
├── app/
│ ├── api/
│ │ └── chat/
│ │ └── route.js
│ ├── globals.css
│ ├── layout.js
│ └── page.js
├── .env.local
└── package.jsonUsing the App Router avoids the routing mismatch in the original draft. Route handlers belong in app/api/.../route.js and can export methods such as POST. The older pages/api convention uses a different handler shape.
Step 2: Add server-only environment variables
At the project root, create .env.local. Replace the example key with your real key. Keep the model in a separate variable so it can be changed without editing route logic.
OPENAI_API_KEY=your_openai_api_key
OPENAI_MODEL=gpt-5.6Never commit .env.local. If you use source control, check that the file is ignored before adding files. Restart npm run dev after adding or editing environment variables so Next.js loads the current values.
There is intentionally no NEXT_PUBLIC_API_ENDPOINT in this setup. The client does not call an OpenAI endpoint directly. It calls the relative internal endpoint /api/chat, while the server-side SDK handles the OpenAI request.
Step 3: Create the Responses API route
Create app/api/chat/route.js. This complete route validates the incoming JSON shape, limits the conversation sent by this demo to the latest 20 messages, calls the Responses API, and returns plain JSON. The message limit is an application choice to keep the example bounded; it is not an OpenAI platform limit.
import OpenAI from 'openai';export const runtime = 'nodejs';const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
});export async function POST(request) {
if (!process.env.OPENAI_API_KEY) {
return Response.json(
{ error: 'OPENAI_API_KEY is not configured on the server.' },
{ status: 500 }
);
}try {
const body = await request.json();
const messages = Array.isArray(body.messages) ? body.messages : null;if (!messages || messages.length === 0) {
return Response.json(
{ error: 'Send a non-empty messages array.' },
{ status: 400 }
);
}const input = messages.slice(-20).map((message) => ({
role: message.role === 'assistant' ? 'assistant' : 'user',
content: String(message.content || '').slice(0, 4000),
}));if (input.some((message) => message.content.trim().length === 0)) {
return Response.json(
{ error: 'Every message must contain text.' },
{ status: 400 }
);
}const response = await openai.responses.create({
model: process.env.OPENAI_MODEL || 'gpt-5.6',
input,
});const content = response.output_text.trim();return Response.json({
message:...Continue Reading
Log in for free to read the rest of this article and access exclusive AI tools.
Log in / Register