diff --git a/README.md b/README.md new file mode 100644 index 0000000..11bfe8a --- /dev/null +++ b/README.md @@ -0,0 +1,221 @@ +

+
+ ♠ ♥ ♣ ♦ +

+

+ +

Felt

+ +

+ The Operating System for Poker Venues +
+ Run a complete tournament offline on a €100 device — it just works. +

+ +

+ Features • + Architecture • + Getting Started • + Development • + Project Structure • + License +

+ +--- + +**Felt** replaces the fragmented tools poker venues cobble together — TDD, whiteboards, spreadsheets, Blind Valet, BravoPokerLive — with one integrated platform. From a 3-table Copenhagen bar to a 40-table casino floor. + +TDD's brain. Linear's face. Dark-room ready. + +## Features + +### Tournament Engine +- **Clock Engine** — Countdown, blind levels, antes, breaks, chip-ups, pause/resume, hand-for-hand. 100ms tick resolution with configurable warnings +- **Blind Structure Wizard** — Generate playable structures from target duration, starting chips, and game type. Mixed-game rotation, big-blind antes, chip-up breaks +- **Financial Engine** — Buy-ins, rebuys, add-ons, bounties (standard + PKO), payouts, rake — all `int64` cents, never `float64`. CI-gated: sum of payouts always equals prize pool +- **ICM Calculator** — Exact Malmuth-Harville for ≤10 players, Monte Carlo (100K iterations) for 11+. Chop/deal support: ICM, chip-chop, even-chop, custom split, partial chop +- **Player Management** — Full-text search, buy-in with auto-seating, bust-out with hitman tracking, undo with full re-ranking, CSV import/export, QR codes +- **Table & Seating** — Configurable layouts, auto-balancing with clockwise distance fairness, break table (fully automatic), tap-tap seat moves +- **Multi-Tournament** — Run simultaneous tournaments with fully independent state (clocks, financials, players, tables) +- **Audit Trail** — Every state-changing action logged. Any financial transaction or bust-out undoable with full re-ranking + +### Operator UI +- **Mobile-first, touch-native** — 48px touch targets, FAB with contextual actions, persistent header with tournament switcher +- **Catppuccin Mocha** dark theme (dark-room ready) with Latte light alternative +- **Overview** — Large clock display, player counts, table balance status, financial summary, activity feed +- **Financials** — Prize pool breakdown, transaction history, payout preview, bubble prize, chop/deal flow +- **Players** — Typeahead search, buy-in flow (search → auto-seat → confirm → receipt), bust-out flow (minimal taps) +- **Tables** — SVG oval table view with seat positions, list view for large tournaments, balancing panel +- **Templates** — LEGO-style building blocks: chip sets, blind structures, payout structures, buy-in configs, assembled into reusable tournament templates + +### Architecture +- **Single Go binary** — Embeds HTTP server, SvelteKit frontend, NATS JetStream, and LibSQL. One process, zero dependencies +- **Offline-first** — Entire operation works without internet. Cloud is never a dependency during a tournament +- **WebSocket real-time** — State changes propagate to all clients within 100ms +- **PIN authentication** — Operators log in with 4-6 digit PINs. Argon2id hashing, rate limiting, JWT sessions + +## Architecture + +``` +┌──────────────────────────────────────────────┐ +│ Leaf Node │ +│ │ +│ ┌──────────┐ ┌──────────┐ ┌────────────┐ │ +│ │ SvelteKit │ │ Go │ │ NATS │ │ +│ │ Frontend │──│ Server │──│ JetStream │ │ +│ │ (embed) │ │ (HTTP) │ │ (embedded) │ │ +│ └──────────┘ └──────────┘ └────────────┘ │ +│ │ │ +│ ┌─────┴─────┐ │ +│ │ LibSQL │ │ +│ │ (SQLite) │ │ +│ └───────────┘ │ +└──────────────────────────────────────────────┘ + │ │ │ + ┌────┴────┐ ┌────┴────┐ ┌────┴────┐ + │ Operator │ │ Display │ │ Player │ + │ Phone │ │ TV/Pi │ │ Phone │ + └─────────┘ └─────────┘ └─────────┘ +``` + +**Stack:** + +| Layer | Technology | Why | +|-------|-----------|-----| +| Backend | Go 1.24 | Single binary, ARM cross-compile, goroutine concurrency | +| Frontend | SvelteKit 2 | Reactive UI, SPA for operator, SSR for public pages | +| Database | LibSQL (SQLite) | Embedded, zero-config, WAL mode, crash-safe | +| Messages | NATS JetStream | Embedded, 10MB RAM, persistent queuing, ordered replay | +| Auth | Argon2id + JWT | Offline PIN login, role-based access | +| Theme | Catppuccin Mocha | Dark-room optimized, systematic accent palette | + +## Getting Started + +### Prerequisites + +- **Go 1.24+** with CGO enabled +- **Node.js 20+** and npm +- Linux (developed on Debian/Ubuntu in LXC) + +### Build & Run + +```bash +# Clone the repository +git clone ssh://git@your-forgejo-instance/mikkel/felt.git +cd felt + +# Build frontend + backend +make all + +# Run in development mode +make run-dev + +# Run tests +make test +``` + +The server starts at `http://localhost:8080`. Open it on any device on the local network. + +### First Run + +1. Navigate to `http://:8080` +2. Log in with the default operator PIN (shown in terminal on first start) +3. Go to **More → Templates** to set up your tournament building blocks +4. Create a tournament from a template +5. Start managing your tournament + +## Development + +### Commands + +```bash +make build # Build Go binary (CGO_ENABLED=1) +make run # Build and run on :8080 +make run-dev # Build and run in dev mode +make test # Run all Go tests +make frontend # Build SvelteKit frontend +make all # Build frontend + backend +make clean # Remove binary and data +``` + +### Environment Variables + +| Variable | Default | Description | +|----------|---------|-------------| +| `DATA_DIR` | `./data` | SQLite database and data storage | +| `ADDR` | `:8080` | HTTP listen address | + +## Project Structure + +``` +felt/ +├── cmd/leaf/ # Main binary entrypoint +│ └── main.go # Server startup, wiring, graceful shutdown +├── internal/ # Application packages +│ ├── audit/ # Append-only audit trail + undo engine +│ ├── auth/ # PIN auth (Argon2id) + JWT tokens +│ ├── blind/ # Blind structure + wizard generation +│ ├── clock/ # Tournament clock engine (100ms resolution) +│ ├── financial/ # Buy-in/rebuy/addon/payout/ICM/chop engine +│ ├── nats/ # Embedded NATS JetStream server + publisher +│ ├── player/ # Player CRUD, search, rankings, CSV, QR +│ ├── seating/ # Table management, balancing, break table +│ ├── server/ # HTTP server, middleware, WebSocket hub +│ │ ├── middleware/ # Auth + role middleware +│ │ ├── routes/ # API route handlers +│ │ └── ws/ # WebSocket hub + client management +│ ├── store/ # Database setup, migrations, queries +│ │ ├── migrations/ # SQL migration files +│ │ └── queries/ # Named SQL queries +│ ├── template/ # Building blocks: chipsets, payouts, buyins +│ └── tournament/ # Tournament lifecycle, multi-tournament, state +├── frontend/ # SvelteKit operator UI +│ ├── src/ +│ │ ├── lib/ +│ │ │ ├── api/ # HTTP API client (auto-JWT, error handling) +│ │ │ ├── components/ # Svelte components (clock, tables, FAB, etc.) +│ │ │ ├── stores/ # Svelte 5 runes state (tournament, auth, multi) +│ │ │ ├── theme/ # Catppuccin CSS custom properties +│ │ │ └── ws/ # WebSocket client with auto-reconnect +│ │ └── routes/ # SvelteKit pages (overview, players, tables, etc.) +│ └── build/ # Compiled frontend (go:embed) +├── Makefile # Build commands +├── go.mod +└── go.sum +``` + +## Design Philosophy + +> *"TDD's brain, Linear's face."* + +Match The Tournament Director's depth and power while looking and feeling like a modern premium product. + +- **Dark-room ready** — Catppuccin Mocha dark theme optimized for dimly lit poker rooms +- **Touch-native** — 48px minimum touch targets, FAB for frequent actions, swipe-friendly +- **Glanceable** — Information-dense without clutter. Monospace numbers, semantic color coding +- **Offline-first** — Internet is never required during operation. Everything runs locally +- **int64 cents** — All monetary values are integer cents. No floating point. Ever. CI-gated + +## Roadmap + +| Phase | Description | Status | +|-------|-------------|--------| +| **1** | Tournament Engine | In Progress | +| **2** | Display Views + Player PWA | Planned | +| **3** | Core Sync + Platform Identity | Planned | +| **4** | Digital Signage + Events Engine | Planned | +| **5** | Leagues, Seasons + Regional | Planned | +| **6** | TDD Migration | Planned | +| **7** | Hardware Leaf (ARM64 + Offline) | Planned | + +## License + +Proprietary. All rights reserved. + +--- + +

+ Built with Go, SvelteKit, LibSQL, and NATS JetStream. +
+ Designed for dark rooms and fast decisions. +