Skip to content

H1ghSyst3m/TableGather

Repository files navigation

TableGather Hub

TableGather Hub is a browser-first React/Vite PWA for local table games. V1 ships Werewolf as the playable game. Imposter and Undercover are registered in the hub as coming-soon games so the registry and UI already support multiple games.

The product is designed for two table-play modes plus an optional public display:

  • Pass-and-play: one device is used by the host/table. Players privately reveal roles one at a time, then the host runs night and day phases.
  • Room mode: the host creates a room with a room code, join link, and QR code. Players join from their own phones. The host still runs the game; player devices only receive role-filtered private/public snapshots.
  • Stage mode: in a Werewolf room, the host can create a separate read-only stage link for a TV, projector, or second screen. The stage client receives only public snapshots and follows the host-controlled reveal queue.

Quick Start

Requirements:

  • Node.js >=22.12.0
  • npm

Commands:

npm install
npm run dev          # Vite frontend on all interfaces
npm run server:dev   # WebSocket room server
npm run server:start # WebSocket room server without watch mode
npm run dev:all      # frontend and server together
npm run lint
npm run test
npm run build

Room mode needs the WebSocket server. By default, the server listens on port 8787, and the browser connects to ws://<current-hostname>:8787/ws.

Configuration:

  • Copy .env.example to .env for local defaults or .env.production.local for production secrets. npm run server:start loads .env, .env.local, .env.production, and .env.production.local in that order.
  • PORT or TABLEGATHER_PORT changes the room server port.
  • TABLEGATHER_ADMIN_TOKEN enables the protected admin room overview API and /admin dashboard. Open /admin#token=<token> only as a transient way to load the token; the client immediately stores it in sessionStorage and removes it from the fragment so it is not kept in the address bar. Subsequent admin visits should use /admin without the token.
  • TABLEGATHER_ADMIN_ALLOWED_ORIGINS optionally allows comma-separated cross-origin admin UI origins. Production defaults to same-origin admin access; set this only for split-origin admin deployments.
  • TABLEGATHER_WS_ALLOWED_ORIGINS optionally allows comma-separated browser WebSocket origins for split frontend/server deployments. Production accepts same-origin browser WebSocket requests by default; development also allows the local Vite origins.
  • TABLEGATHER_SERVE_STATIC controls whether the room server serves the built dist/ frontend. It defaults to enabled when NODE_ENV=production and disabled otherwise.
  • TABLEGATHER_TRUSTED_PROXIES optionally allows comma-separated exact proxy peer IPs whose CF-Connecting-IP or X-Forwarded-For headers may identify room rate-limit clients. Leave it empty unless the room server is behind a trusted reverse proxy.
  • VITE_WS_URL overrides the browser WebSocket URL. It accepts ws://, wss://, http://, or https://; HTTP(S) values are converted to WS(S). In production, leave it empty for a same-origin /ws endpoint behind your reverse proxy.
  • For phone/tablet testing on the same local network, run npm run dev:all, open the Vite URL from the host machine's LAN address, and make sure the room server port is reachable from the other devices.

Production Deployment

Production can run as a single Node room server that also serves the built frontend. The process manager and reverse proxy are deployment-specific; they only need to start the current server script and forward traffic to it.

Use .env.example as the reference for production values. The usual production environment is:

  • NODE_ENV=production so the room server serves the built dist/ frontend by default.
  • PORT or TABLEGATHER_PORT for the room server listen port.
  • TABLEGATHER_ADMIN_TOKEN when the protected /admin dashboard should be enabled.
  • TABLEGATHER_ADMIN_ALLOWED_ORIGINS only when /admin is served from a different origin than /admin/rooms.
  • TABLEGATHER_WS_ALLOWED_ORIGINS only when the browser app is intentionally served from a different origin than /ws.
  • TABLEGATHER_SERVE_STATIC=false only for split deployments where another service serves dist/.
  • TABLEGATHER_TRUSTED_PROXIES only when a trusted reverse proxy overwrites forwarding headers before traffic reaches the room server.

Build and start with the repository scripts:

npm ci --include=dev
npm run build
npm run server:start

The current scripts build and start from TypeScript, so install the full dependency set needed by both build and runtime. Configure any process manager to run npm run server:start with the production environment available.

For same-origin production deployments, leave VITE_WS_URL empty. The built browser app connects to /ws on the current origin, and the room server exposes the matching WebSocket endpoint. In the single-process setup, route /, SPA routes, /ws, /health, and /admin/rooms to the same TableGather server. No separate static host or admin API location is required.

Set VITE_WS_URL only when the browser app and room server are intentionally split across different origins or path prefixes. It accepts ws://, wss://, http://, or https://; HTTP(S) values are converted to WS(S). For split-origin browser deployments, add the frontend origin to TABLEGATHER_WS_ALLOWED_ORIGINS on the room server.

Main routes:

  • / - hub game/mode selection and device-local room sessions.
  • /play/<gameId> - local pass-and-play for a playable game.
  • /room/create/<gameId> - create a room for a playable game as host.
  • /room/<CODE> - join or resume a room. The app resolves the room's game id through the room server, then opens the registered host or player view.
  • /stage/<CODE>/<TOKEN> - open a registered stage screen from a host-created stage link.
  • /admin - protected room overview dashboard when TABLEGATHER_ADMIN_TOKEN is configured on the room server.

V1 Scope

  • Werewolf is fully playable in local and room mode.
  • Werewolf room mode supports host, player, and read-only stage clients.
  • Room state is in-memory on the server. Rooms expire after 48 hours of inactivity, and a server restart clears active server-side room state.
  • Browser-stored reconnect tokens, stage tokens, and local session tokens remain on the client until explicitly invalidated by the server or user, but may no longer map to an active room after expiry or restart.
  • The Hub Session tab shows active host/player rooms known to the current browser by validating stored local tokens with the room server; locally stored tokens can outlive the server-side room they belonged to.
  • Local pass-and-play Werewolf persists its current game in localStorage.
  • Privacy is enforced by snapshots: host snapshots can contain full game state, player snapshots only expose the requesting player's private role data and public table status, and stage snapshots expose only public room/game information.
  • No placeholder role art is bundled for Werewolf. Icon fallbacks remain until real assets are added.

Documentation Map

  • docs/architecture.md - shared project architecture, game registry, runtime, tests, and extension boundaries.
  • docs/online-mode.md - shared room lifecycle, WebSocket protocol, snapshots, tokens, and adapter responsibilities.
  • docs/styling-and-theming.md - shared styling layers, theme tokens, and future-game styling guidance.
  • docs/games/README.md - game documentation ownership and per-game doc set expectations.
  • docs/games/werewolf/README.md - Werewolf-specific flow, role, room, Stage, and styling docs.
  • CONTRIBUTING.md - contribution workflow and local verification expectations.
  • NOTICE.md - project branding and attribution notice.
  • SECURITY.md - supported scope and private vulnerability reporting guidance.

Source Map

  • src/App.tsx owns route parsing and delegates game screen selection to the route component registry.
  • src/games/registry.ts registers games and exposes playable game adapters.
  • src/games/routeComponents.tsx maps playable game definitions to client-only route screens.
  • src/games/types.ts defines GameDefinition, structured player constraints, theme tokens, and the room adapter contract, including command validators and optional stage snapshots.
  • src/games/werewolf/ contains the Werewolf definition, domain engine, room adapter, stage snapshot builder, components, i18n, theme, and game-specific CSS.
  • src/stage/ contains reusable client-only Stage display state for fullscreen and Screen Wake Lock.
  • src/online/ contains client-side WebSocket message types, room session storage helpers, and the room socket hook.
  • server/ contains the in-memory WebSocket room runtime.
  • test/ contains Vitest coverage for domain behavior, room behavior, i18n, registry, clipboard, and UI rendering.

Public Release Notes

This repository is intended to be shared as source code, not published as an npm package. package.json keeps "private": true to prevent accidental package publication.

The source code is licensed under the GNU Affero General Public License v3.0 only. See LICENSE.

The TableGather name, logo, and branding are not licensed for reuse without prior written permission. See NOTICE.md.

Please read CONTRIBUTING.md before opening changes and use SECURITY.md for vulnerability reports.

Verification Notes

Run the full check set after behavior, room, role, UI, i18n, or documentation changes:

npm run lint
npm run test
npm run build

On this Windows sandbox, npm run test or npm run build can fail with spawn EPERM while loading native Vite/Tailwind bindings. If the failure is only that native binding error, rerun the same command outside the sandbox.

About

A small browser-based hub for playing table games with friends in the same room, using phones, shared screens, and simple host tools.

Topics

Resources

License

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages