Some checks failed
Build and Push / build (push) Failing after 8s
Full-stack tournament management app with real-time scoring: - Go 1.26 backend with REST API and WebSocket live scoring - React 19 + Vite 8 frontend with mobile-first design - File-based JSON storage with JSONL audit logs - Multi-stage Docker build with Gitea CI/CD pipeline - Post-tournament questionnaire with spirit voting - Technical documentation and project description Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
165 lines
6.2 KiB
Markdown
165 lines
6.2 KiB
Markdown
# 🥏 Disc Agenda — Frisbee Tournament Platform
|
|
|
|
A self-hosted tournament management web app for ultimate frisbee, featuring live multiplayer scoring via WebSockets, a mobile-friendly questionnaire with QR codes, and a clean athletic visual design.
|
|
|
|
## Architecture
|
|
|
|
```
|
|
┌──────────────────────────────────────────┐
|
|
│ Go 1.26 Backend (single binary) │
|
|
│ ├─ REST API (gorilla/mux) │
|
|
│ ├─ WebSocket hub (gorilla/websocket) │
|
|
│ ├─ SPA file server │
|
|
│ └─ File-based JSON storage │
|
|
├──────────────────────────────────────────┤
|
|
│ React 19 + Vite 8 Frontend │
|
|
│ ├─ react-router-dom v7 (SPA) │
|
|
│ ├─ qrcode.react (QR generation) │
|
|
│ └─ Custom CSS (Bebas Neue + Barlow) │
|
|
├──────────────────────────────────────────┤
|
|
│ Data: flat JSON files + JSONL audit logs │
|
|
│ (no database required) │
|
|
└──────────────────────────────────────────┘
|
|
```
|
|
|
|
## Features
|
|
|
|
- **Tournament hub** — home page with location, dates, teams, rules
|
|
- **Schedule** — round-grouped game schedule with status badges
|
|
- **Live scoring** — WebSocket-powered multiplayer scoreboard with +/- and SET controls
|
|
- **Audit log** — every score change persisted as JSONL per game
|
|
- **Questionnaire** — mobile-friendly survey with QR code, team selectors, spirit voting, custom questions
|
|
- **Results** — final standings table with spirit award highlight
|
|
- **Past tournaments** — archive of completed events
|
|
|
|
## Quick Start
|
|
|
|
### Docker (recommended)
|
|
|
|
```bash
|
|
docker compose up --build
|
|
# → http://localhost:8080
|
|
```
|
|
|
|
Data persists in a Docker volume. Seed data auto-copies on first run.
|
|
|
|
### Local Development
|
|
|
|
**Prerequisites:** Go 1.26+, Node 22+
|
|
|
|
Terminal 1 — backend:
|
|
```bash
|
|
cd backend
|
|
go mod tidy
|
|
go run ./cmd/server -data ../data -static ../frontend/dist -port 8080
|
|
```
|
|
|
|
Terminal 2 — frontend (with hot reload + API proxy):
|
|
```bash
|
|
cd frontend
|
|
npm install
|
|
npm run dev
|
|
# → http://localhost:5173 (proxies /api and /ws to :8080)
|
|
```
|
|
|
|
## Project Structure
|
|
|
|
```
|
|
├── backend/
|
|
│ ├── cmd/server/main.go # Entry point, router, SPA handler
|
|
│ └── internal/
|
|
│ ├── handlers/handlers.go # REST + WS HTTP handlers
|
|
│ ├── models/models.go # Domain types
|
|
│ ├── storage/storage.go # File-based persistence
|
|
│ └── websocket/hub.go # Per-game WS hub + broadcast
|
|
├── frontend/
|
|
│ ├── src/
|
|
│ │ ├── api.js # API client + WS factory
|
|
│ │ ├── App.jsx # Router
|
|
│ │ ├── main.jsx # Entry
|
|
│ │ ├── components/ # Header, Footer, Icons
|
|
│ │ ├── pages/ # All page components
|
|
│ │ └── styles/global.css # Full stylesheet
|
|
│ ├── vite.config.js # Dev proxy config
|
|
│ └── index.html
|
|
├── data/ # Seed data (JSON files)
|
|
│ ├── tournaments.json
|
|
│ └── tournaments/{id}/
|
|
│ ├── schedule.json
|
|
│ ├── questionnaire_config.json
|
|
│ ├── results.json
|
|
│ └── games/ # Score state + audit logs
|
|
├── Dockerfile # Multi-stage build
|
|
├── docker-compose.yml
|
|
└── Makefile
|
|
```
|
|
|
|
## API Reference
|
|
|
|
| Method | Endpoint | Description |
|
|
|--------|----------|-------------|
|
|
| GET | `/api/tournaments` | List all tournaments |
|
|
| GET | `/api/tournaments/{id}` | Tournament details |
|
|
| GET | `/api/tournaments/{id}/schedule` | Game schedule |
|
|
| GET | `/api/tournaments/{id}/games/{gid}/score` | Current score |
|
|
| POST | `/api/tournaments/{id}/games/{gid}/score` | Update score (REST) |
|
|
| GET | `/api/tournaments/{id}/games/{gid}/audit` | Audit log |
|
|
| WS | `/ws/game/{id}/{gid}?user_id=x` | Live score WebSocket |
|
|
| GET | `/api/tournaments/{id}/questionnaire` | Questionnaire config + teams |
|
|
| POST | `/api/tournaments/{id}/questionnaire` | Submit response |
|
|
| GET | `/api/tournaments/{id}/questionnaire/results` | All responses (admin) |
|
|
| GET | `/api/tournaments/{id}/results` | Final standings |
|
|
|
|
### WebSocket Protocol
|
|
|
|
Connect: `ws://host/ws/game/{tourneyId}/{gameId}?user_id=alice`
|
|
|
|
**Send** (client → server):
|
|
```json
|
|
{"action": "increment", "team": "home"}
|
|
{"action": "decrement", "team": "away"}
|
|
{"action": "set", "team": "home", "value": 12}
|
|
```
|
|
|
|
**Receive** (server → all clients):
|
|
```json
|
|
{
|
|
"type": "score_update",
|
|
"state": {"game_id": "g01", "home_score": 8, "away_score": 6, ...},
|
|
"audit": {"action": "increment", "team": "home", "old_home": 7, ...}
|
|
}
|
|
```
|
|
|
|
## Configuration
|
|
|
|
All via flags or env vars:
|
|
|
|
| Flag | Env | Default | Description |
|
|
|------|-----|---------|-------------|
|
|
| `-port` | `PORT` | `8080` | Listen port |
|
|
| `-data` | `DATA_DIR` | `./data` | Data directory |
|
|
| `-static` | — | `./static` | Frontend files |
|
|
|
|
## Adding Tournament Data
|
|
|
|
Edit JSON files directly in `data/`:
|
|
|
|
- `tournaments.json` — add/edit tournament objects
|
|
- `tournaments/{id}/schedule.json` — game schedule
|
|
- `tournaments/{id}/questionnaire_config.json` — custom survey questions
|
|
- `tournaments/{id}/results.json` — final standings
|
|
|
|
No admin UI yet — data is managed via files. Future: add admin panel.
|
|
|
|
## Tech Stack
|
|
|
|
- **Backend:** Go 1.26, gorilla/mux 1.8.1, gorilla/websocket 1.5.3, rs/cors
|
|
- **Frontend:** React 19, Vite 8, react-router-dom 7, qrcode.react
|
|
- **Storage:** Flat JSON files + JSONL audit logs
|
|
- **Container:** Alpine 3.21, multi-stage Docker build
|
|
|
|
## Documentation
|
|
|
|
- **[Technical Documentation](docs/DOCUMENTATION.md)** — detailed API reference, data models, WebSocket protocol, deployment guides, troubleshooting
|
|
- **[Project Description](docs/PROJECT.md)** — project overview, motivation, features, design philosophy, roadmap
|