Private friends pool — scoreboard reads public/data/latest.json (exported from xlsx/Master WorldCup26.xlsx).
Everything the browser loads lives in public/:
- Scoreboard:
public/index.html→ https://mikizi.github.io/toto/ - Admin:
public/admin/
GitHub Pages deploys the public/ folder (see .github/workflows/pages.yml).
- Actions → Publish match result
- Run workflow → match #, home score, away score
- Wait ~1–2 min → site updates (Pages redeploys on push)
pip install -r requirements.txt
make devpip install -r requirements.txt
SKIP_TESTS=1 make dev- Scoreboard: http://localhost:8080/
- Admin: http://localhost:8080/admin/
- Run
make dev(starts site + admin API on port 8090). - Open Admin → pick match → enter scores → Publish locally.
- Open Scoreboard and refresh — hero + points should update.
CLI equivalent:
PYTHONPATH=. python3 scripts/publish_match.py 1 0 1In Admin, use Upload in the header and choose a replacement Master WorldCup26.xlsx.
- Local admin replaces
xlsx/Master WorldCup26.xlsx, recalculates it, and rewritespublic/data/latest.json. - Production admin uploads the workbook to GitHub and queues Sync uploaded workbook; refresh the site after the Action finishes.
Manual local equivalent:
make export- Open https://mikizi.github.io/toto/admin/
- Enter the shared admin password → Publish
- Wait ~1–2 min for Actions + Pages deploy.
The production admin uses a free Cloudflare Worker so admins do not need GitHub tokens.
- Create a GitHub token for the worker:
- Classic token:
reposcope, or fine-grained token with access tomikizi/toto - Store it only in Cloudflare, not in
public/
- Classic token:
- Log in to Cloudflare and deploy:
npx wrangler login
npx wrangler secret put GITHUB_TOKEN
npx wrangler secret put ADMIN_PASSWORD
npx wrangler deploy- Copy the Worker URL from deploy output, for example:
https://toto-admin-publish.your-subdomain.workers.dev
- Update
PUBLISH_PROXY_URLinpublic/admin/admin.jsto:
https://toto-admin-publish.your-subdomain.workers.dev/publish
- Commit and push. Admins can then publish with the shared password only.
make testLibreOffice-backed workbook integration tests are slower. Run them only when changing recalc/pipeline behavior:
make test-integrationSimulate the first match kicking off in 5 minutes. Before kickoff you see coming soon; when the countdown hits zero the scoreboard appears.
make simulate # reset scores, move match 1 kickoff +5 min, export JSON
make serve # in another terminal
open http://localhost:8080/Restore the real schedule when done:
make simulate-restoreVerify that patching a result recalculates points and export correctly:
make simulate-scoresThis runs day zero → 1-0 → 0-1 → 1-0 on a temp copy and checks real-user points after each step.
Apply a result to your local xlsx + site JSON (example: South Africa win 0-1):
make simulate-scores-apply
make serveCI runs score + kickoff checks after merge via .github/workflows/kickoff-simulation.yml.
public/ ← entire client app (GitHub Pages root)
index.html
manifest.json ← PWA
admin/
css/styles.css
js/app.js
assets/ ← images only
bg.png, bg-card-header.png, euro2024_bets.png
icons/
data/latest.json
xlsx/ ← Master WorldCup26.xlsx
scripts/ ← patch, recalc, export
tests/
legacy/ ← old Euro 2024 app
.github/workflows/ ← pages.yml + publish-results.yml
After merge, set GitHub Pages → Source: GitHub Actions in repo settings (one-time).
PWA icons and background images live under public/assets/. Replace euro2024_bets.png with a WC26 share image when ready.