🇬🇧 English | 🇫🇷 Français
A local web interface for chatting with Ollama models, with conversation storage in MongoDB.
- 💬 Streaming chat (NDJSON) with a thinking indicator, typing cursor, and stop button
- 🗂️ Persisted conversations — localStorage + MongoDB, auto-generated titles, renaming, JSON / Markdown export
- 🎨 Dark/light design system — configurable accent color (7 persisted hues), signature gradient, status LED
- ⚙️ Settings modal — model selection (size, loaded status), system prompt, temperature, external sources (Claude, GPT, Mistral, Gemini… API keys stored locally only)
- 🔌 Built-in Ollama proxy — no more CORS issues: the frontend goes through
/api/ollama/* - 📱 Responsive — sidebar as a drawer on mobile, touch targets ≥ 44 px, full keyboard navigation and ARIA support
- Frontend: Next.js 16 (App Router), React 19 (React Compiler), Tailwind CSS v4, TypeScript
- Backend: Next.js Route Handlers (Ollama proxy, conversation CRUD)
- AI: Ollama — local models (Llama, Mistral, etc.)
- Database: MongoDB (Mongoose 9)
- Tests: Vitest + Testing Library (jsdom)
- Containerization: Multi-stage Docker (pnpm/corepack), Docker Compose
- Package manager: pnpm (pinned via
packageManager, never npm/yarn)
- Node.js 24+ and pnpm 10 (
corepack enable pnpm) - Docker & Docker Compose (for the containerized stack)
- Ollama installed locally (
ollama serve)
# 1. Clone and install
pnpm install
# 2. Configure environment variables
cp .env.example .env
# Edit MONGODB_URI if needed
# 3. Start Ollama (in a separate terminal)
ollama serve
ollama pull llama3.2
# 4. Start the dev server
pnpm devOpen http://localhost:3000.
# Smart startup:
# - reuses Ollama/Mongo on the host machine if detected and reachable
# - only starts the missing containers
pnpm docker:up:auto
# Stop
docker compose down
# With the MongoDB Express admin UI (optional)
docker compose --profile admin up -d mongo-express| Service | URL |
|---|---|
| App | http://localhost:3000 |
| Ollama API | http://localhost:11434 |
| MongoDB | mongodb://localhost:27017 |
| MongoDB Express | http://localhost:8081 |
pnpm dev # Development
pnpm build # Production build
pnpm start # Start production server
pnpm lint # ESLint
pnpm test # Tests (Vitest)
pnpm test:watch # Tests in watch mode
pnpm test:coverage # Code coverage
pnpm docker:up:auto # Full Docker stack| Method | Route | Description |
|---|---|---|
| GET/POST | /api/ollama/[...path] |
Proxy to the Ollama API (OLLAMA_HOST) — removes CORS issues, preserves streaming. E.g. /api/ollama/api/tags, /api/ollama/api/chat |
| Method | Route | Description |
|---|---|---|
| GET | /api/ollama/health |
Ollama connectivity |
| GET | /api/ollama/version |
Ollama version |
| GET | /api/ollama/tags |
Installed models |
| GET | /api/ollama/ps |
Models currently loaded in memory |
| POST | /api/ollama/show |
Model details |
| POST | /api/ollama/load |
Load a model |
| POST | /api/ollama/unload |
Unload a model |
| Method | Route | Description |
|---|---|---|
| POST | /api/chat |
SSE streaming chat (legacy — the frontend uses the NDJSON proxy) |
| POST | /api/chat/title |
Generate a title |
| Method | Route | Description |
|---|---|---|
| GET | /api/conversations |
List conversations |
| POST | /api/conversations |
Create a conversation |
| GET | /api/conversations/[id] |
Fetch a conversation |
| PUT | /api/conversations/[id] |
Update a conversation |
| DELETE | /api/conversations/[id] |
Delete a conversation |
| POST | /api/conversations/[id]/save |
Append messages |
Docker variables are kept separate from local Next.js variables:
.env.docker: non-sensitive Docker values (safe to commit).env.docker.local: local Docker secrets (not committed).env.docker.runtime: auto-generated byscripts/docker-up-auto.sh(not committed)
Recommended setup:
cp .env.docker.local.example .env.docker.local
# then edit .env.docker.local with your private valuesFor the container to reach an Ollama instance installed on the Linux host,
Ollama must listen on 0.0.0.0 (not just 127.0.0.1):
OLLAMA_HOST=0.0.0.0:11434 ollama serveVerify with:
ss -ltn | grep 11434You should see 0.0.0.0:11434 or [::]:11434.
| Variable | Description | Default |
|---|---|---|
OLLAMA_HOST |
Target of the /api/ollama/[...path] proxy |
http://127.0.0.1:11434 (http://ollama:11434 in Compose) |
OLLAMA_BASE_URL |
Ollama URL used by the granular routes | http://localhost:11434 |
DEFAULT_MODEL |
Default model | llama3.2 |
MONGODB_URI |
MongoDB connection string | — |
⚠️ Use127.0.0.1rather thanlocalhostforOLLAMA_HOSToutside Docker (avoids IPv6 resolution failures).
pnpm test # Run the tests
pnpm test:coverage # Coverage reportCurrent coverage: 36 tests — UI components (sidebar, messages, streaming, theme, export, deletion) and type validation.
GitHub Actions workflows, run on push and pull request to master and development:
- Ollama CI — lint → tests + coverage → typecheck (
tsc --noEmit) → Next.js build → Docker image published to GHCR (push onmasteronly). All Node jobs use pnpm with caching. - CodeQL — JavaScript/TypeScript security analysis (plus a weekly run on Mondays)
- Dependency Review — dependency review on pull requests (fails on high+ severity vulnerabilities)
- Docker Security Scan — image build + Trivy scan (SARIF uploaded to the Security tab, blocking gate on fixed critical CVEs, plus a filesystem dependency scan; weekly on Wednesdays)
The project is configured for Claude Code and opencode:
next-devtoolsMCP (.mcp.json/opencode.json) — real-time app errors, routes, and logs while runningpnpm dev- GitHub MCP (
github-mcp-server, remote server) — reliable access to GitHub Actions runs, Dependabot alerts, and Dependency Review results when working on CI/CD and dependency updates - 7 specialized sub-agents (
.claude/agents/,.opencode/agent/) —designer(built-in official design system),frontend-dev,backend-dev,code-reviewer,test-reviewer,ci-reviewer,docker-dev
See AGENTS.md for the project's conventions.
See SECURITY.md for the supported versions and vulnerability reporting process.
MIT