Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
__pycache__/
*.pyc
*.pyo
*.pyd
.Python
.venv/
venv/
env/

.git/
.DS_Store

frontend/node_modules/
frontend/dist/

data/


54 changes: 54 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ OPENROUTER_API_KEY=sk-or-v1-...

Get your API key at [openrouter.ai](https://openrouter.ai/). Make sure to purchase the credits you need, or sign up for automatic top up.

If you want a starter template, copy `env.template` to `.env` and edit it.

### 3. Configure Models (Optional)

Edit `backend/config.py` to customize the council:
Expand All @@ -64,6 +66,58 @@ CHAIRMAN_MODEL = "google/gemini-3-pro-preview"
./start.sh
```

**Option 1b: Docker Compose**

1. Provide `OPENROUTER_API_KEY` (either via a local `.env` file or your shell environment).

Create a `.env` file in the project root (optional but recommended):

```bash
OPENROUTER_API_KEY=sk-or-v1-...
```

If you want a starter template, copy `env.template` to `.env` and edit it.

2. Build + run:

```bash
docker compose up --build
```

Then open http://localhost:5173 in your browser.

Notes:
- Data is persisted on the host at `./data/` (mounted into the backend container).
- If you’re not accessing the app from the same machine (i.e. not `localhost`), set `VITE_API_BASE` to the correct reachable backend URL (e.g. `http://YOUR_HOST:8001`) in `docker-compose.yml` or your environment.

**Podman (podman-compose)**

If you're using Podman instead of Docker, you can run the same `docker-compose.yml` with `podman-compose`.

- Detached mode (recommended):

```bash
podman-compose down && podman-compose build --no-cache && podman-compose up -d
```

- Foreground mode:

```bash
podman-compose down && podman-compose build --no-cache && podman-compose up
```

- Tail logs:

```bash
podman-compose logs -f
```

- Stop:

```bash
podman-compose down
```

**Option 2: Run manually**

Terminal 1 (Backend):
Expand Down
27 changes: 27 additions & 0 deletions backend/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
FROM python:3.11-slim

WORKDIR /app

ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1

# System deps for uv + httpx TLS
RUN apt-get update \
&& apt-get install -y --no-install-recommends ca-certificates curl \
&& rm -rf /var/lib/apt/lists/*

# Install uv (used by this repo)
RUN pip install --no-cache-dir uv

# Install python deps
COPY pyproject.toml uv.lock /app/
RUN uv sync --frozen --no-dev

# Copy backend code
COPY backend/ /app/backend/

EXPOSE 8001

CMD ["uv", "run", "uvicorn", "backend.main:app", "--host", "0.0.0.0", "--port", "8001"]


7 changes: 6 additions & 1 deletion backend/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,12 @@
# Enable CORS for local development
app.add_middleware(
CORSMiddleware,
allow_origins=["http://localhost:5173", "http://localhost:3000"],
allow_origins=[
"http://localhost:5173",
"http://127.0.0.1:5173",
"http://localhost:3000",
"http://127.0.0.1:3000",
],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
Expand Down
29 changes: 29 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
services:
backend:
build:
context: .
dockerfile: backend/Dockerfile
environment:
# Compose will read a local .env automatically if present; this keeps podman-compose happy
# even when the file doesn't exist.
- OPENROUTER_API_KEY=${OPENROUTER_API_KEY}
ports:
- "8001:8001"
volumes:
- ./data:/app/data
restart: unless-stopped

frontend:
build:
context: .
dockerfile: frontend/Dockerfile
environment:
# Optional; default in code is http://localhost:8001
- VITE_API_BASE=http://localhost:8001
ports:
- "5173:5173"
depends_on:
- backend
restart: unless-stopped


5 changes: 5 additions & 0 deletions env.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Rename to `.env` (repo root) or export these variables in your shell.
# Required for backend OpenRouter calls:
OPENROUTER_API_KEY=sk-or-v1-...


14 changes: 14 additions & 0 deletions frontend/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
FROM node:20-alpine

WORKDIR /app

COPY frontend/package.json frontend/package-lock.json /app/
RUN npm ci

COPY frontend/ /app/

EXPOSE 5173

CMD ["npm", "run", "dev", "--", "--host", "0.0.0.0", "--port", "5173", "--strictPort"]


4 changes: 3 additions & 1 deletion frontend/src/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
* API client for the LLM Council backend.
*/

const API_BASE = 'http://localhost:8001';
// In Vite, only env vars prefixed with VITE_ are exposed to the browser.
// Default keeps local dev + docker-compose (published backend port) working out of the box.
const API_BASE = import.meta.env.VITE_API_BASE || 'http://localhost:8001';

export const api = {
/**
Expand Down
5 changes: 5 additions & 0 deletions frontend/vite.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,9 @@ import react from '@vitejs/plugin-react'
// https://vite.dev/config/
export default defineConfig({
plugins: [react()],
server: {
host: true,
port: 5173,
strictPort: true,
},
})