A Bun and TypeScript browser multiplayer prototype for an isometric social room loop.
- Project overview
- Architecture
- WebSocket protocol
- Realtime room loop
- Persistence plan
- Art design principles
- Development workflow
- Bun
- Docker and Docker Compose, for containerized development
- PostgreSQL is required for account creation and login. Drizzle schema and migrations live under
apps/server/src/db.
bun installStart the WebSocket server and client dev server:
bun run devOr run them separately:
bun run dev:server
bun run dev:clientDefaults:
- Server:
http://localhost:3000 - WebSocket:
ws://localhost:3000/ws - Client:
http://localhost:3001
Open the client in two browser tabs, create or log in with different usernames, and join room lobby.
For normal Codex worktrees, run the client and server natively with Bun and use Docker only for Postgres:
bun install
bun run worktree:setup
bun run db:up
bun run db:migrateThen start the native dev servers when you are ready to use that worktree:
bun run devworktree:setup writes an ignored .env with an isolated Compose project name and available
client, server, and database ports. Use bun run db:reset to delete that worktree's Postgres
volume.
Start the client, server, and Postgres together:
docker compose up --buildDocker defaults:
- Client:
http://localhost:3001 - Server:
http://localhost:3000 - WebSocket:
ws://localhost:3000/ws - Postgres:
postgres://postgres:postgres@localhost:5432/tilezofrom the host, andpostgres://postgres:postgres@db:5432/tilezofrom Compose services
Compose runs database migrations before starting the server.
Run checks inside the container when you want parity with the Docker environment:
docker compose exec server bun run typecheck
docker compose exec server bun run lint
docker compose exec server bun testThe Docker setup uses one shared Bun image for development and separate Dockerfile targets for later deployment:
docker build --target server -t tilezo-server .
docker build --target client -t tilezo-client .Compose runs a one-shot deps service before the app services so the container-owned Bun dependency volume stays in sync with bun.lock.
bun run typecheck
bun run lint
bun testServer:
HOST=0.0.0.0
PORT=3000
DATABASE_URL=postgres://postgres:postgres@localhost:5432/tilezo
AUTH_SECRET=change-me-in-production
NODE_ENV=developmentClient:
PUBLIC_API_URL=http://localhost:3000
PUBLIC_WS_URL=ws://localhost:3000/wsIf PUBLIC_API_URL or PUBLIC_WS_URL is omitted, the client uses the local server defaults.