A multi-model AI chat interface built with Next.js and TypeScript. Supports OpenAI, Anthropic Claude, Google Gemini, and Ollama (local models) from a single unified interface.
- Multi-provider support -- Switch between OpenAI, Claude, Gemini, and local Ollama models from a dropdown
- Auto-detection -- Only shows providers you've configured API keys for
- Responsive design -- Works on desktop and mobile
- Markdown rendering -- AI responses render with full GitHub-flavored markdown (code blocks, tables, lists, links)
- Security hardened -- Input validation, rate limiting, system prompt injection prevention, security headers
- Dark theme -- Clean, modern dark UI
| Provider | Models | Env Variable |
|---|---|---|
| OpenAI | GPT-5.2, GPT-5.2 Instant, GPT-5 Mini, GPT-5 Nano, GPT-4o, GPT-4o Mini, o3-mini | OPENAI_API_KEY |
| Anthropic | Claude Opus 4.6, Claude Sonnet 4.5, Claude Haiku 4.5 | ANTHROPIC_API_KEY |
| Gemini 2.5 Pro, Gemini 2.5 Flash, Gemini 2.5 Flash-Lite, Gemini 2.0 Flash | GOOGLE_AI_API_KEY |
|
| Ollama | Any local model (llama3.3, mistral, phi4, etc.) | OLLAMA_BASE_URL |
- Node.js >= 18.x
- npm or yarn
- At least one AI provider API key (or a local Ollama instance)
- Clone the repository:
git clone https://github.com/hillis/gpt-4-chat-ui.git
cd gpt-4-chat-ui- Install dependencies:
npm install- Create a
.env.localfile with your API keys (use any combination):
# OpenAI (https://platform.openai.com/api-keys)
OPENAI_API_KEY=sk-...
# Anthropic Claude (https://console.anthropic.com/)
ANTHROPIC_API_KEY=sk-ant-...
# Google Gemini (https://aistudio.google.com/apikey)
GOOGLE_AI_API_KEY=AIza...
# Ollama local models (https://ollama.com/)
OLLAMA_BASE_URL=http://localhost:11434
OLLAMA_MODELS=llama3.3,mistral,phi4You only need to set the keys for the providers you want to use. The UI will auto-detect which are available.
- Start the development server:
npm run dev- Open http://localhost:3000 in your browser.
├── lib/
│ └── providers.ts # Provider abstraction (OpenAI, Claude, Gemini, Ollama)
├── pages/
│ ├── api/
│ │ ├── chat.ts # POST /api/chat — sends messages to selected provider
│ │ └── providers.ts # GET /api/providers — returns available models
│ ├── index.tsx # Main chat UI
│ ├── _app.tsx # Next.js app wrapper
│ └── _document.tsx # Next.js document wrapper
├── styles/
│ ├── Home.module.css # Component styles
│ └── globals.css # Global styles
├── public/ # Static assets (icons, images)
├── next.config.js # Next.js config with security headers
├── package.json
└── tsconfig.json
Browser ──POST /api/chat──▶ API Route ──▶ Provider Router
│ { provider, model, messages } │
│ ├── OpenAI SDK
│ ├── Anthropic SDK
│ ├── Google GenAI SDK
│ └── Ollama (fetch)
│◀── { result: { role, content } } ──────────┘
The frontend calls GET /api/providers on load to discover available models, then sends chat messages to POST /api/chat with the selected provider and model. The backend validates the request, routes to the correct SDK, and returns a unified response format.
To add a new AI provider, create a factory function in lib/providers.ts:
function createMyProvider(): ProviderConfig | null {
const apiKey = process.env.MY_PROVIDER_API_KEY;
if (!apiKey) return null;
return {
provider: "myprovider",
models: [
{ id: "my-model-id", name: "My Model", provider: "myprovider" },
],
async chat(model, messages) {
// Call your provider's API and return the response text
return "response text";
},
};
}Then add it to the providerFactories array and add "myprovider" to the ALLOWED_PROVIDER_NAMES set in pages/api/chat.ts. No other files need changes.
This project includes several security measures:
- Input validation -- All messages validated for type, length (max 4000 chars), and count (max 50)
- Role sanitization -- Only
"user"and"assistant"roles accepted from clients; prevents system prompt injection - Rate limiting -- 20 requests per minute per IP (in-memory)
- Error handling -- API errors logged server-side only; clients receive generic messages (no API key leakage)
- Security headers --
X-Content-Type-Options,X-Frame-Options,Referrer-Policy,Permissions-Policy - No
X-Powered-By-- Header disabled - Provider/model allowlist -- Server validates provider name and model ID against registered allowlists
| Command | Description |
|---|---|
npm run dev |
Start development server |
npm run build |
Create production build |
npm start |
Start production server |
npm run lint |
Run ESLint |
Deploy to any platform that supports Next.js:
- Vercel -- Zero-config deployment (recommended)
- Railway
- Render
- Docker -- Use
npm run build && npm start
Set your API keys as environment variables in your hosting platform's dashboard.
- Next.js 14 -- React framework
- TypeScript 5 -- Type safety
- OpenAI SDK -- GPT-5.2 / GPT-4o
- Anthropic SDK -- Claude Opus 4.6 / Sonnet 4.5
- Google GenAI SDK -- Gemini 2.5
- React Markdown -- Markdown rendering
- Material UI -- Loading spinner component
Contributions are welcome. Please open an issue or submit a pull request.
Originally inspired by LangChain-Chat-NextJS.
This project is licensed under the MIT License.