https://github.com/chess-centre/broadcasts
📺 DGT board data streaming
https://github.com/chess-centre/broadcasts
broadcast chess dgt react websocket
Last synced: 3 months ago
JSON representation
📺 DGT board data streaming
- Host: GitHub
- URL: https://github.com/chess-centre/broadcasts
- Owner: chess-centre
- Created: 2022-04-16T00:11:38.000Z (about 4 years ago)
- Default Branch: master
- Last Pushed: 2026-03-08T17:35:29.000Z (3 months ago)
- Last Synced: 2026-03-08T17:51:48.792Z (3 months ago)
- Topics: broadcast, chess, dgt, react, websocket
- Language: JavaScript
- Homepage: https://boardcast.studio
- Size: 37.5 MB
- Stars: 8
- Watchers: 1
- Forks: 2
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Boardcast
Professional 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.

---
## Monorepo Structure
```
apps/
desktop/ Electron app — organiser tool with embedded server
web/ Next.js — marketing site + spectator viewer
relay/ WebSocket relay — bridges desktop to internet spectators
packages/
chess/ Pure TypeScript chess logic (PGN parsing, eval, pairings)
protocol/ Shared message types and constants
ui/ Shared React components and hooks
config/ Shared TypeScript configs
```
### How It Works
```
Organiser's Machine Cloud Spectators
┌──────────────┐ push ┌──────────┐ subscribe ┌──────────┐
│ Desktop App │ ─────────────> │ Relay │ <──────────── │ Browser │
│ (DGT boards) │ game updates │ Service │ game updates │ (web app)│
└──────────────┘ └──────────┘ └──────────┘
```
---
## Quick Start
### Prerequisites
- [Node.js](https://nodejs.org/) 20+
- [pnpm](https://pnpm.io/) 10+
```bash
# Install pnpm if you don't have it
npm install -g pnpm
```
### Install
```bash
git clone https://github.com/chess-centre/broadcasts.git
cd broadcasts
pnpm install
```
### Build Packages
```bash
pnpm build
```
### Development
Run individual apps or the full stack:
```bash
# All apps in parallel
pnpm dev
# Individual apps
pnpm dev:desktop # Electron organiser app
pnpm dev:web # Next.js marketing + spectator site
pnpm dev:relay # WebSocket relay service
```
### Desktop App (Electron)
```bash
cd apps/desktop
cp .env.example .env # Configure DGT path, ports, etc.
pnpm dev # Starts server + React + Electron
```
The dashboard is the landing page — configure the simulator, hit **start**, then click **open live view** to watch.
### Marketing Site (Next.js)
```bash
cd apps/web
pnpm dev # http://localhost:3000
```
### Relay Service
```bash
cd apps/relay
pnpm dev # ws://localhost:3001
```
---
## Desktop App
The Electron app is the organiser's tool. It embeds the Express/WebSocket server — no terminal needed.
### Routes
| Route | Description |
| ------------------- | ------------------------------------------------------------ |
| `/` | System dashboard — network, engine, cloud relay, simulator |
| `/tournament` | Tournament wizard — create events, manage players & pairings |
| `/live` | Live broadcast viewer with boards and leaderboard |
| `/guide` | Built-in organiser guide and documentation |
| `/viewer/live` | Pop-out live viewer window (external display) |
| `/viewer/game` | Dedicated game viewer window with full analysis |
| `/viewer/tv` | TV mode window with smart board auto-cycling |
| `/viewer/tournament`| Pop-out tournament standings display |
| `/obs` | OBS browser source widgets |
### Dashboard
The landing page (`/`) is a tabbed control panel:
- **Broadcast** — network settings, DGT connection, live board status, server URL, spectator link
- **Engine** — UCI engine configuration, Stockfish download and setup
- **Cloud Relay** — public broadcast configuration for internet spectators
- **Simulator** — test board and game simulation for development and demos
### Configuration (`.env`)
```bash
# Server
PORT=8080
CORS_ORIGIN=*
# DGT LiveChess
DGT_BASE_PATH=C:/Users/user/Desktop/Live
DGT_API_URL=ws://127.0.0.1:1982/api/v1.0
DGT_WATCH_MODE=files
# Broadcast
MAX_BOARDS=20
POLL_INTERVAL=1000
DEBUG=false
```
### Building the Desktop App
```bash
cd apps/desktop
pnpm build # Build React + package Electron installers
pnpm pack # Quick pack to directory (testing)
```
Outputs: `.dmg` (macOS), `.exe` (Windows), `.AppImage` (Linux).
---
## Spectator Access
### Local Network
Spectators on the same WiFi/LAN connect directly to the desktop app's server:
```
http://:8080
```
Share via the built-in QR code or spectator link modal.
### Internet (via Relay)
The desktop app pushes game updates to the cloud relay. Spectators visit:
```
https://your-site.com/watch/
```
No port forwarding or tunnels required.
---
## Key Features
### Live Broadcast
- **Multi-board grid** — up to 20 simultaneous boards with responsive layout
- **Dedicated game viewer** — click any board to open a full analysis window with move navigation, engine lines, move time chart, and keyboard controls
- **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
- **Real-time evaluation** — Stockfish engine analysis with multi-PV lines, best move arrows, eval bars, and player accuracy tracking
- **Live clocks** — DGT clock integration with client-side countdown between server updates
- **Critical moments** — automatic blunder, mistake, and brilliancy detection badges
- **Featured board** — auto-highlights the most exciting game based on eval volatility
- **Opening names** — ECO classification displayed on each board
- **Customisable display** — 6 board themes, 5 accent colours, toggle individual overlays, animation speeds, and branding
### Tournament Management
- **Swiss pairings** — FIDE Dutch-system with score groups, colour balancing, and no repeat matchups
- **Round Robin** — Berger tables for optimal colour distribution
- **Tournament wizard** — step-by-step event creation with player management, recent player memory, and CSV import
- **Live standings & crosstable** — real-time leaderboard with Buchholz tiebreaks and head-to-head matrix
- **Pop-out tournament display** — dedicated window for venue screens
### Streaming & Sharing
- **OBS browser source widgets** — overlay-ready widgets for streaming software
- **QR code sharing** — built-in QR code and spectator link for local network access
- **Cloud relay** — push games to internet spectators via WebSocket relay service
- **Social media posts** — auto-generated game result and standings posts
- **Fullscreen mode** — dedicated projection mode with floating toolbar
---
## API Reference
### REST API (Desktop Server)
| Method | Endpoint | Description |
| ------ | ----------------------- | -------------------------------------------------------- |
| `GET` | `/api/config` | Server configuration (DGT, broadcast settings) |
| `GET` | `/api/status` | Runtime status (clients, watchers, stockfish, simulator) |
| `POST` | `/api/simulator/start` | Start simulator `{ boards, speed, round, eventName }` |
| `POST` | `/api/simulator/stop` | Stop simulator |
| `GET` | `/api/simulator/status` | Simulator game progress |
| `GET` | `/api/tournament` | Current tournament metadata |
| `POST` | `/api/tournament/create`| Create tournament with pairings |
| `GET` | `/:round/:board` | Fetch specific game PGN |
### WebSocket API (Desktop Server)
Connect to `ws://localhost:8080/games`.
```json
// Client → Server
{ "type": "subscribe_round", "round": 1 }
{ "type": "ping" }
// Server → Client
{ "type": "game_update", "round": 1, "board": 3, "data": { ... } }
{ "type": "eval_update", "board": 3, "evaluation": { ... }, "fen": "..." }
{ "type": "connected", "message": "Connected to chess broadcast server" }
```
### Relay API
```json
// Organiser → Relay
{ "type": "relay_auth", "eventId": "spring-open", "secret": "..." }
{ "type": "relay_publish", "eventId": "spring-open", "message": { ... } }
// Spectator → Relay
{ "type": "relay_subscribe", "eventId": "spring-open" }
```
Health check: `GET /health`
Active events: `GET /events`
---
## Packages
### `@broadcasts/chess`
Pure TypeScript chess utilities. No React, no browser APIs.
```ts
import { parseGame, evalToPercent, generatePairings } from "@broadcasts/chess";
```
- **parseGame** — PGN parser extracting players, clocks, FEN, result
- **evalToPercent / formatScore / uciToSan** — engine evaluation utilities
- **detectCriticalMoment** — blunder/mistake/inaccuracy detection
- **extractMoveTimes / formatTime** — clock time analysis
- **generatePairings / calculateRounds** — round-robin and Swiss pairing engine
- **generateGameEndPost / generateStandingsPost** — social media post generation
### `@broadcasts/protocol`
Shared TypeScript types for all WebSocket messages, game state, and event metadata. Used by desktop, relay, and web apps.
### `@broadcasts/ui`
Shared React hooks for broadcast apps:
- **useInterval** — isomorphic interval hook
- **useClockCountdown** — client-side clock countdown between server updates
- **useAutoCycle** — TV/kiosk board rotation with priority scoring
- **useFeaturedBoard** — selects most interesting game by eval volatility
---
## DGT LiveChess Setup
1. Install [DGT LiveChess](https://www.livechess.com/) 2.2+
2. Settings > File Output > Enable PGN saving
3. Set output directory to match `DGT_BASE_PATH`
4. Directory structure: `round-1/game-1.pgn`, `round-1/game-2.pgn`, etc.
5. Connect boards via USB, assign board numbers, enter player info
```
Live/
├── round-1/
│ ├── game-1.pgn
│ ├── game-2.pgn
│ └── game-3.pgn
└── round-2/
├── game-1.pgn
└── game-2.pgn
```
---
## Deployment
### Desktop App
Tag a version and push — GitHub Actions builds for all platforms and creates a release:
```bash
git tag v0.5.3
git push origin v0.5.3
```
Auto-updates are handled via `electron-updater` from GitHub Releases.
### Marketing Site
Deploys to Vercel on push to `master` (changes in `apps/web/` or `packages/`).
### Relay Service
Deploys to Fly.io on push to `master` (changes in `apps/relay/` or `packages/protocol/`).
```bash
cd apps/relay
flyctl launch # First time
flyctl deploy # Subsequent deploys
```
---
## Troubleshooting
**No games appearing** — Check `DGT_BASE_PATH` matches your PGN directory. Verify folder structure is `round-N/game-N.pgn`. Enable `DEBUG=true`.
**WebSocket not connecting** — Verify server is running on correct port. Check browser console. Ensure firewall allows WebSocket connections.
**Clocks not updating** — DGT LiveChess must include `[%clk H:MM:SS]` comments in PGN output.
**pnpm install fails** — Ensure you're using pnpm 10+ and Node 20+. Run `pnpm install --no-frozen-lockfile` on first setup.
---
## Credits
- [DGT](https://www.livechess.com/) — LiveChess software and hardware
- [chess.js](https://github.com/jhlywa/chess.js) — game logic
- [chessground](https://github.com/lichess-org/chessground) — board rendering
- [Boardcast](https://boardcast.studio) — original concept