{"id":46664257,"url":"https://github.com/chess-centre/broadcasts","last_synced_at":"2026-03-13T22:02:21.699Z","repository":{"id":37025731,"uuid":"482115377","full_name":"chess-centre/broadcasts","owner":"chess-centre","description":"📺 DGT board data streaming","archived":false,"fork":false,"pushed_at":"2026-03-08T17:35:29.000Z","size":39349,"stargazers_count":8,"open_issues_count":0,"forks_count":2,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-03-08T17:51:48.792Z","etag":null,"topics":["broadcast","chess","dgt","react","websocket"],"latest_commit_sha":null,"homepage":"https://boardcast.studio","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/chess-centre.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2022-04-16T00:11:38.000Z","updated_at":"2026-03-08T17:35:32.000Z","dependencies_parsed_at":"2024-11-28T08:32:58.426Z","dependency_job_id":null,"html_url":"https://github.com/chess-centre/broadcasts","commit_stats":null,"previous_names":[],"tags_count":22,"template":false,"template_full_name":null,"purl":"pkg:github/chess-centre/broadcasts","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chess-centre%2Fbroadcasts","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chess-centre%2Fbroadcasts/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chess-centre%2Fbroadcasts/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chess-centre%2Fbroadcasts/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chess-centre","download_url":"https://codeload.github.com/chess-centre/broadcasts/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chess-centre%2Fbroadcasts/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30477242,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-13T20:45:58.186Z","status":"ssl_error","status_checked_at":"2026-03-13T20:45:20.133Z","response_time":60,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["broadcast","chess","dgt","react","websocket"],"created_at":"2026-03-08T16:08:13.418Z","updated_at":"2026-03-13T22:02:21.693Z","avatar_url":"https://github.com/chess-centre.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Boardcast\n\nProfessional live chess tournament broadcasting. Real-time DGT board integration, built-in Stockfish analysis, Swiss/Round Robin pairings, and dedicated viewer windows. Installable desktop app for organisers, cloud relay for internet spectators.\n\n\u003cimg src=\"./img/example-full-boards.png\" /\u003e\n\u003cimg src=\"./img/dashboard.png\" /\u003e\n\n---\n\n## Monorepo Structure\n\n```\napps/\n  desktop/       Electron app — organiser tool with embedded server\n  web/           Next.js — marketing site + spectator viewer\n  relay/         WebSocket relay — bridges desktop to internet spectators\n\npackages/\n  chess/         Pure TypeScript chess logic (PGN parsing, eval, pairings)\n  protocol/      Shared message types and constants\n  ui/            Shared React components and hooks\n  config/        Shared TypeScript configs\n```\n\n### How It Works\n\n```\nOrganiser's Machine                Cloud                    Spectators\n┌──────────────┐      push      ┌──────────┐   subscribe   ┌──────────┐\n│ Desktop App  │ ─────────────\u003e │  Relay   │ \u003c──────────── │ Browser  │\n│ (DGT boards) │  game updates  │ Service  │  game updates │ (web app)│\n└──────────────┘                └──────────┘               └──────────┘\n```\n\n---\n\n## Quick Start\n\n### Prerequisites\n\n- [Node.js](https://nodejs.org/) 20+\n- [pnpm](https://pnpm.io/) 10+\n\n```bash\n# Install pnpm if you don't have it\nnpm install -g pnpm\n```\n\n### Install\n\n```bash\ngit clone https://github.com/chess-centre/broadcasts.git\ncd broadcasts\npnpm install\n```\n\n### Build Packages\n\n```bash\npnpm build\n```\n\n### Development\n\nRun individual apps or the full stack:\n\n```bash\n# All apps in parallel\npnpm dev\n\n# Individual apps\npnpm dev:desktop    # Electron organiser app\npnpm dev:web        # Next.js marketing + spectator site\npnpm dev:relay      # WebSocket relay service\n```\n\n### Desktop App (Electron)\n\n```bash\ncd apps/desktop\ncp .env.example .env    # Configure DGT path, ports, etc.\npnpm dev                # Starts server + React + Electron\n```\n\nThe dashboard is the landing page — configure the simulator, hit **start**, then click **open live view** to watch.\n\n### Marketing Site (Next.js)\n\n```bash\ncd apps/web\npnpm dev                # http://localhost:3000\n```\n\n### Relay Service\n\n```bash\ncd apps/relay\npnpm dev                # ws://localhost:3001\n```\n\n---\n\n## Desktop App\n\nThe Electron app is the organiser's tool. It embeds the Express/WebSocket server — no terminal needed.\n\n### Routes\n\n| Route               | Description                                                  |\n| ------------------- | ------------------------------------------------------------ |\n| `/`                 | System dashboard — network, engine, cloud relay, simulator   |\n| `/tournament`       | Tournament wizard — create events, manage players \u0026 pairings |\n| `/live`             | Live broadcast viewer with boards and leaderboard            |\n| `/guide`            | Built-in organiser guide and documentation                   |\n| `/viewer/live`      | Pop-out live viewer window (external display)                |\n| `/viewer/game`      | Dedicated game viewer window with full analysis              |\n| `/viewer/tv`        | TV mode window with smart board auto-cycling                 |\n| `/viewer/tournament`| Pop-out tournament standings display                         |\n| `/obs`              | OBS browser source widgets                                   |\n\n### Dashboard\n\nThe landing page (`/`) is a tabbed control panel:\n\n- **Broadcast** — network settings, DGT connection, live board status, server URL, spectator link\n- **Engine** — UCI engine configuration, Stockfish download and setup\n- **Cloud Relay** — public broadcast configuration for internet spectators\n- **Simulator** — test board and game simulation for development and demos\n\n### Configuration (`.env`)\n\n```bash\n# Server\nPORT=8080\nCORS_ORIGIN=*\n\n# DGT LiveChess\nDGT_BASE_PATH=C:/Users/user/Desktop/Live\nDGT_API_URL=ws://127.0.0.1:1982/api/v1.0\nDGT_WATCH_MODE=files\n\n# Broadcast\nMAX_BOARDS=20\nPOLL_INTERVAL=1000\nDEBUG=false\n```\n\n### Building the Desktop App\n\n```bash\ncd apps/desktop\npnpm build              # Build React + package Electron installers\npnpm pack               # Quick pack to directory (testing)\n```\n\nOutputs: `.dmg` (macOS), `.exe` (Windows), `.AppImage` (Linux).\n\n---\n\n## Spectator Access\n\n### Local Network\n\nSpectators on the same WiFi/LAN connect directly to the desktop app's server:\n\n```\nhttp://\u003corganiser-ip\u003e:8080\n```\n\nShare via the built-in QR code or spectator link modal.\n\n### Internet (via Relay)\n\nThe desktop app pushes game updates to the cloud relay. Spectators visit:\n\n```\nhttps://your-site.com/watch/\u003cevent-id\u003e\n```\n\nNo port forwarding or tunnels required.\n\n---\n\n## Key Features\n\n### Live Broadcast\n- **Multi-board grid** — up to 20 simultaneous boards with responsive layout\n- **Dedicated game viewer** — click any board to open a full analysis window with move navigation, engine lines, move time chart, and keyboard controls\n- **TV mode** — dedicated window that auto-cycles through boards, prioritising the most interesting games (mate threats, eval swings, balanced positions) with smooth fade transitions and periodic leaderboard display\n- **Real-time evaluation** — Stockfish engine analysis with multi-PV lines, best move arrows, eval bars, and player accuracy tracking\n- **Live clocks** — DGT clock integration with client-side countdown between server updates\n- **Critical moments** — automatic blunder, mistake, and brilliancy detection badges\n- **Featured board** — auto-highlights the most exciting game based on eval volatility\n- **Opening names** — ECO classification displayed on each board\n- **Customisable display** — 6 board themes, 5 accent colours, toggle individual overlays, animation speeds, and branding\n\n### Tournament Management\n- **Swiss pairings** — FIDE Dutch-system with score groups, colour balancing, and no repeat matchups\n- **Round Robin** — Berger tables for optimal colour distribution\n- **Tournament wizard** — step-by-step event creation with player management, recent player memory, and CSV import\n- **Live standings \u0026 crosstable** — real-time leaderboard with Buchholz tiebreaks and head-to-head matrix\n- **Pop-out tournament display** — dedicated window for venue screens\n\n### Streaming \u0026 Sharing\n- **OBS browser source widgets** — overlay-ready widgets for streaming software\n- **QR code sharing** — built-in QR code and spectator link for local network access\n- **Cloud relay** — push games to internet spectators via WebSocket relay service\n- **Social media posts** — auto-generated game result and standings posts\n- **Fullscreen mode** — dedicated projection mode with floating toolbar\n\n---\n\n## API Reference\n\n### REST API (Desktop Server)\n\n| Method | Endpoint                | Description                                              |\n| ------ | ----------------------- | -------------------------------------------------------- |\n| `GET`  | `/api/config`           | Server configuration (DGT, broadcast settings)           |\n| `GET`  | `/api/status`           | Runtime status (clients, watchers, stockfish, simulator)  |\n| `POST` | `/api/simulator/start`  | Start simulator `{ boards, speed, round, eventName }`    |\n| `POST` | `/api/simulator/stop`   | Stop simulator                                           |\n| `GET`  | `/api/simulator/status` | Simulator game progress                                  |\n| `GET`  | `/api/tournament`       | Current tournament metadata                              |\n| `POST` | `/api/tournament/create`| Create tournament with pairings                          |\n| `GET`  | `/:round/:board`        | Fetch specific game PGN                                  |\n\n### WebSocket API (Desktop Server)\n\nConnect to `ws://localhost:8080/games`.\n\n```json\n// Client → Server\n{ \"type\": \"subscribe_round\", \"round\": 1 }\n{ \"type\": \"ping\" }\n\n// Server → Client\n{ \"type\": \"game_update\", \"round\": 1, \"board\": 3, \"data\": { ... } }\n{ \"type\": \"eval_update\", \"board\": 3, \"evaluation\": { ... }, \"fen\": \"...\" }\n{ \"type\": \"connected\", \"message\": \"Connected to chess broadcast server\" }\n```\n\n### Relay API\n\n```json\n// Organiser → Relay\n{ \"type\": \"relay_auth\", \"eventId\": \"spring-open\", \"secret\": \"...\" }\n{ \"type\": \"relay_publish\", \"eventId\": \"spring-open\", \"message\": { ... } }\n\n// Spectator → Relay\n{ \"type\": \"relay_subscribe\", \"eventId\": \"spring-open\" }\n```\n\nHealth check: `GET /health`\nActive events: `GET /events`\n\n---\n\n## Packages\n\n### `@broadcasts/chess`\n\nPure TypeScript chess utilities. No React, no browser APIs.\n\n```ts\nimport { parseGame, evalToPercent, generatePairings } from \"@broadcasts/chess\";\n```\n\n- **parseGame** — PGN parser extracting players, clocks, FEN, result\n- **evalToPercent / formatScore / uciToSan** — engine evaluation utilities\n- **detectCriticalMoment** — blunder/mistake/inaccuracy detection\n- **extractMoveTimes / formatTime** — clock time analysis\n- **generatePairings / calculateRounds** — round-robin and Swiss pairing engine\n- **generateGameEndPost / generateStandingsPost** — social media post generation\n\n### `@broadcasts/protocol`\n\nShared TypeScript types for all WebSocket messages, game state, and event metadata. Used by desktop, relay, and web apps.\n\n### `@broadcasts/ui`\n\nShared React hooks for broadcast apps:\n\n- **useInterval** — isomorphic interval hook\n- **useClockCountdown** — client-side clock countdown between server updates\n- **useAutoCycle** — TV/kiosk board rotation with priority scoring\n- **useFeaturedBoard** — selects most interesting game by eval volatility\n\n---\n\n## DGT LiveChess Setup\n\n1. Install [DGT LiveChess](https://www.livechess.com/) 2.2+\n2. Settings \u003e File Output \u003e Enable PGN saving\n3. Set output directory to match `DGT_BASE_PATH`\n4. Directory structure: `round-1/game-1.pgn`, `round-1/game-2.pgn`, etc.\n5. Connect boards via USB, assign board numbers, enter player info\n\n```\nLive/\n├── round-1/\n│   ├── game-1.pgn\n│   ├── game-2.pgn\n│   └── game-3.pgn\n└── round-2/\n    ├── game-1.pgn\n    └── game-2.pgn\n```\n\n---\n\n## Deployment\n\n### Desktop App\n\nTag a version and push — GitHub Actions builds for all platforms and creates a release:\n\n```bash\ngit tag v0.5.3\ngit push origin v0.5.3\n```\n\nAuto-updates are handled via `electron-updater` from GitHub Releases.\n\n### Marketing Site\n\nDeploys to Vercel on push to `master` (changes in `apps/web/` or `packages/`).\n\n### Relay Service\n\nDeploys to Fly.io on push to `master` (changes in `apps/relay/` or `packages/protocol/`).\n\n```bash\ncd apps/relay\nflyctl launch      # First time\nflyctl deploy      # Subsequent deploys\n```\n\n---\n\n## Troubleshooting\n\n**No games appearing** — Check `DGT_BASE_PATH` matches your PGN directory. Verify folder structure is `round-N/game-N.pgn`. Enable `DEBUG=true`.\n\n**WebSocket not connecting** — Verify server is running on correct port. Check browser console. Ensure firewall allows WebSocket connections.\n\n**Clocks not updating** — DGT LiveChess must include `[%clk H:MM:SS]` comments in PGN output.\n\n**pnpm install fails** — Ensure you're using pnpm 10+ and Node 20+. Run `pnpm install --no-frozen-lockfile` on first setup.\n\n---\n\n## Credits\n\n- [DGT](https://www.livechess.com/) — LiveChess software and hardware\n- [chess.js](https://github.com/jhlywa/chess.js) — game logic\n- [chessground](https://github.com/lichess-org/chessground) — board rendering\n- [Boardcast](https://boardcast.studio) — original concept\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchess-centre%2Fbroadcasts","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchess-centre%2Fbroadcasts","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchess-centre%2Fbroadcasts/lists"}