# ⚽ Premier Gunner A kid-friendly, mobile-friendly soccer training tracker. Gunner logs what he trains each day, plans his week, chases goals, and watches the **Road to London** thermometer fill up toward the reward: a trip to see Arsenal play in person. Installable as a PWA on his phone. ## Features - **Single-password login** — everything lives behind one password. - **Daily logging** — tap a category pill, bump the metric steppers (juggles, minutes, shots, …), add optional notes. Almost no typing. - **Categories Gunner controls** — Juggling, Left Foot, Shooting, Soccer Tennis, Dribbling Drills, Soccer Golf, Backyard with Dad, 1-on-1 with Elijah, EPA Agility & Speed — and he can add/edit/archive his own in Settings. - **Weekly planning** — set objectives for upcoming days; stick to them or change his mind. - **Dashboard** — total sessions, training days, streaks, a GitHub-style calendar heatmap, a radar chart of training spread, line charts of improvement over time, goal progress bars, and the main-goal thermometer. - **Goals** — overall or per-category, by number of sessions, personal best, or running total. Flag one as the ⭐ main goal to drive the thermometer. - **PWA** — installable, offline app shell, custom Arsenal-red cannon icon. ## Tech Node.js + Fastify + better-sqlite3 on the backend; a no-build vanilla-JS PWA frontend with Chart.js (vendored locally). All data in a single SQLite file. No external services. ## Run locally ```bash npm install PG_PASSWORD=your-password npm start # open http://localhost:3000 (default password is "gunner" if PG_PASSWORD is unset) ``` To start fresh, stop the server and delete the `data/` folder — categories and the starter goals re-seed on next boot. ## Configuration (environment variables) | Var | Default | Purpose | | ------------------ | ------------------ | -------------------------------------------------- | | `PG_PORT` | `3000` | HTTP port | | `PG_HOST` | `0.0.0.0` | Bind address | | `PG_DATA_DIR` | `./data` | Where the SQLite DB + WAL live (persist this!) | | `PG_PASSWORD` | `gunner` (dev) | Plaintext password, hashed on first boot | | `PG_PASSWORD_HASH` | — | Pre-computed bcrypt hash (preferred for prod) | | `PG_COOKIE_SECRET` | auto-generated | Session cookie signing secret (persisted if unset) | | `PG_SESSION_DAYS` | `30` | How long a login stays valid | The password can also be changed in-app under ⚙️ Settings. ## Phase 2 — not yet built These were intentionally deferred (see the plan in chat): 1. **StartOS 0.4.0 service package** — wrap this in an s9pk so it installs on Start9, with `PG_DATA_DIR` mounted on a persistent volume and the password exposed as a service config field. Serve it on the clearnet domain via Start9 pages + StartTunnel. Docs: https://docs.start9.com/packaging/0.4.0.x/ · https://docs.start9.com/start-tunnel/1.0.x/ 2. **DGX Spark (Qwen3.6) AI coach** — a server-side proxy to the OpenAI-compatible endpoint that, on login, reviews Gunner's objectives + full history and suggests what to train and how to plan ahead; plus on-demand drill ideas per category. Kept server-side so the endpoint and any key never reach the browser. ## Project layout ``` src/ server.js Fastify app, auth gate, route wiring config.js env-driven config + data dir db.js SQLite connection + schema bootstrap schema.sql tables seed.js default categories + starter goals auth.js password hashing, sessions routes/ auth, categories, entries, plans, goals, stats public/ index.html app shell (tabs: Today / Plan / Stats / Goals) login.html css/styles.css js/app.js views: logging, planning, goals, settings js/dashboard.js charts, heatmap, thermometer js/api.js fetch wrapper manifest.webmanifest, sw.js, icons/ ```