Chess
Play Stockfish in your browser, over a REST API
About
A Go server that exposes chess as a REST API, with Stockfish behind it for move validation and computer play. The server owns the rules; clients own nothing but the display, which is why three very different ones talk to the same endpoints.
Games are anonymous by default. An account is optional and only changes who the game is recorded against.
- Modes
- Human vs computer, human vs human, computer vs computer.
- Engine
- Stockfish, skill level 0–20, per-move search budget 100–10000 ms.
- Positions
- Any legal FEN — puzzles, endgames, mid-game starts.
- Export
- PGN move list plus the current FEN, straight to the clipboard.
- Clients
- Web UI, terminal CLI, and the same CLI compiled to WebAssembly.
Play
Drag-free click-to-move, last-move highlighting, undo, live server and storage indicators, and a move list that copies out as PGN.
Note: This interactive board requires JavaScript to function.
Terminal Client
The CLI from the repository, compiled to WebAssembly and wired to xterm.js. It opens in its own tab rather than in a frame here: the binary is around 10 MB, and there is no reason to spend that on a visitor who only came to look at the board.
Note: The terminal client requires a modern browser with JavaScript and WebAssembly support.
- Start
helpfor the command list, thennew white 10 1000.- Shares state
- Same API as the board above — a game started in one shows up in the other.
- Native build
- The same client runs as a normal terminal program against any instance; the WASM build only swaps the I/O layer.
Under the Hood
Transport
Processing
Execute(Command) entry point holds the game logic, which is what keeps the transport swappable. Validation runs against a synchronous UCI engine; computer moves go to an asynchronous queue so the request returns immediately.State and Long-Polling
Engine Pool
Persistence
Accounts
API
| Endpoint | Method | Notes |
|---|---|---|
/api/v1/auth/register | POST | Username, password, optional email. Returns a token. 5 req/min per IP. |
/api/v1/auth/login | POST | Username or email plus password. 10 req/min per IP. |
/api/v1/auth/me | GET | Current user, from the bearer token. |
/api/v1/auth/logout | POST | Invalidates the session server-side. |
/api/v1/games | POST | Per-colour player config, optional starting FEN. |
/api/v1/games/{id}/moves | POST | A UCI move, or cccc to hand the turn to the engine. |
/api/v1/games/{id} | GET | ?wait=true&moveCount=N long-polls for up to 30 seconds. |
/api/v1/games/{id}/undo | POST | Takes back count plies. |
/health | GET | Server and storage status. |
General rate limit is 10 req/s per IP. Authentication is optional on game endpoints; an anonymous game is issued a generated player ID instead.
Technical Details
Runtime
- Server: Go, Fiber, SQLite (WAL), Stockfish over UCI
- Web client: vanilla JavaScript and CSS, no framework, no build step
- Terminal client: Go → WASM, xterm.js with the WebGL renderer
- Auth: JWT (HS256), Argon2id password hashing
- Single instance enforced by a PID lock file
Build
- Clone
git clone https://github.com/lixenwraith/chess --depth 1- Build
cd chess && make release- Run
bin/chessd(Stockfish must be onPATH)