Files
Wizard/README.md
T
marvinandClaude Opus 5.5 90176e1cca Serve API and website behind Caddy path prefixes
Caddy forwards /wizard/api/* and /wizard/website/* with the prefix
stripped, so the server received /ws instead of /api/ws and the website
connected to /api/ws on the domain root.

- Server routes are now /ws and /health (was /api/ws, /api/health)
- Website derives the websocket URL from its own location (../api/ws),
  giving /wizard/api/ws in production and /api/ws in development
- Vite dev proxy strips /api like the production proxy
- nginx back to the plain SPA config since Caddy strips the prefix
- /internal/ai rejects requests that came through the reverse proxy,
  in addition to the shared secret
- Docs updated for the prefixed deployment

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 10:00:29 +02:00

68 lines
3.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Wizard online
An online version of the card game Wizard (rules: `wizard_instructions/`).
| Component | Path | Tech |
|-----------|------|------|
| Frontend | `wizard_website/` | React + TypeScript + Vite, CSS modules, served by nginx |
| Game server | `wizard_server/` | Python, FastAPI, websockets |
| Game logic | `wizard_server/game_logic/` | Pure Python package `wizard_game` (no dependencies) |
| AI player | `wizard_ai/` | Python; RL training skeleton + websocket service |
```
browser ──wss /wizard/api/ws──────▶ Caddy ──/ws──▶ wizard_server:8083 ◀──ws /internal/ai── wizard_ai
──https /wizard/website/──▶ Caddy ──/────▶ wizard_website:8082 (network wizard_internal)
```
## How it works
1. A player opens the website, enters a name and creates a lobby (and joins it).
2. The lobby shows a code (and an invite link, `?lobby=CODE`) others use to join.
3. The host can add AI players, toggle the *not equal* / *hidden bids* rules, and start the game (3–6 players).
4. The server runs the game with `wizard_game` and sends every player a personal view
(`Observation`) after each move. Reloading the page reconnects to the same seat.
A player who leaves a running game is replaced by an AI player.
5. When an AI seat has to act, the server sends its `Observation` to the AI service over the
internal websocket and applies the answered action. If the AI service is unavailable or
too slow, a random legal move is played so games never get stuck.
The `Observation` / action JSON format is defined once in `wizard_game` and shared by the
frontend, the server and the AI, so AI models see exactly the same data in training and in
production.
## Deployment
```bash
cp .env.example .env # set AI_SHARED_SECRET
docker network create wizard_website # if they don't exist yet
docker network create wizard_api
docker compose up -d --build
```
- `wizard_website` joins the external network `wizard_website` (port 8082).
- `wizard_server` joins the external network `wizard_api` (port 8083) and `wizard_internal`.
- `wizard_ai` joins only `wizard_internal`, created by compose as an internal network.
In the Caddy reverse proxy, `/wizard/website/*` goes to `wizard_website:8082`
and `/wizard/api/*` to `wizard_server:8083`, both with the prefix stripped. The website uses
relative asset paths and derives the API address from its own URL (`../api/ws`), so it works under
any prefix as long as the website and API are siblings. `/internal/ai` refuses requests that come
through the proxy (forwarding headers present), in addition to requiring `AI_SHARED_SECRET`.
Trained AI checkpoints go into `wizard_ai/models/latest/` (mounted read-only). Until one exists
the AI service uses the built-in heuristic player.
## Development
```bash
python -m venv .venv && . .venv/bin/activate
pip install -r wizard_server/requirements-dev.txt -r wizard_ai/requirements-dev.txt
(cd wizard_server && uvicorn app.main:app --reload) # :8000
(cd wizard_ai && python -m wizard_ai serve) # connects to :8000
(cd wizard_website && npm install && npm run dev) # :5173
(cd wizard_server && pytest) # game logic + server tests
(cd wizard_ai && pytest)
```