An openturn game definition is a pure value. It does not know whether it will run locally in a browser tab or authoritatively inside a Cloudflare Durable Object. That is the whole point: you author once, and the runtime is chosen by the React app at bindings-creation time.Documentation Index
Fetch the complete documentation index at: https://openturn.io/docs/llms.txt
Use this file to discover all available pages before exploring further.
Two ways to run a match
Local session —createLocalSession(game, { match }) from @openturn/core runs the reducer in your current process. The React binding createOpenturnBindings(game, { runtime: "local", match }) wires the same session into a subscribable store and exposes hooks. Good for:
- Local-only games (tic-tac-toe on the same device).
- Tests and dev loops.
- CLI and single-player UIs.
createRoomRuntime({ deployment, roomID }) from @openturn/server runs the same reducer inside a server. Clients connect over WebSocket using @openturn/client, and React apps use createOpenturnBindings(game, { runtime: "multiplayer" }) plus <OpenturnProvider> to consume useRoom (or useMatch if you don’t need lobby/bridge). Good for:
- Real multiplayer.
- Authoritative rules (server rejects illegal moves).
- Per-player views (server sends each client only their slice).
One provider, every environment
TheOpenturnProvider is zero-prop in normal app code. The runtime declared in createOpenturnBindings plus the URL fragment injected by the host shell determine what happens:
runtime: "local"→ renders an in-process session backed by thematchyou passed tocreateOpenturnBindings.runtime: "multiplayer"→ reads the#openturn-bridge=…URL fragment.openturn devinjects it locally; openturn-cloud injects it in production. Same fragment shape, same code path.
The stack, top to bottom
File layout for a cloud-ready game
The CLI and deploy pipeline expect three files underapp/:
app/game.ts— re-exportsgamefrom your worker package.app/page.tsx— the React entry. For local games this is a thin renderer (the host shell wraps it in<OpenturnProvider>). For multiplayer games it usually wraps the experience in its own provider plus auseRoomlobby.app/openturn.ts— metadata:name,runtime: "local" | "multiplayer", and for multiplayer thegameKeyandschemaVersion.
runtime: "local") and multiplayer (runtime: "multiplayer"). openturn build produces the right Worker bundle based on the metadata, and the React createOpenturnBindings call mirrors the same runtime declaration.
Local hosted dev
For multiplayer development,openturn dev runs a Bun server that mounts your game in @openturn/server, persists rooms in SQLite, and accepts WebSocket connections. The dev shell hosts your bundle in an iframe and injects the same #openturn-bridge=… fragment that openturn-cloud injects in production — your React app sees no difference between dev and prod, so a single <OpenturnProvider /> works in both.
See how-to: run a local hosted stack and how-to: deploy to openturn cloud.
What to read next
- Tutorial: tic-tac-toe multiplayer takes the local tic-tac-toe through the full hosted stack.
- Reference: server, client, and connect document the transport surfaces.