Initial release: Disc Agenda frisbee tournament platform
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>
This commit is contained in:
2026-03-15 14:48:15 +01:00
commit a7244406fd
38 changed files with 5749 additions and 0 deletions

164
README.md Normal file
View File

@@ -0,0 +1,164 @@
# 🥏 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