A Star Wars: Unlimited league app for weekly voting and leaderboards, built as a static front end on GitHub Pages backed by a Cloudflare Worker + D1 database backend.
- Players link once on each device by entering an email and picking their player profile; the backend mints a per-device token. They then submit a weekly vote (a favorite leader and favorite opponent) through a mobile-styled web app.
- A Cloudflare Worker backend tracks votes, compiles leaderboards, advances weeks, and calculates end-of-season awards. Data is stored in a D1 (SQLite) database.
- Player data is synced from the Melee.gg API on a weekly cron trigger (dual-cron for DST handling).
- Gamification features: raffle tickets (1 per vote), streak tracking, and voting milestones.
- 4 tabs: Vote | Standings | Awards | My Stats
| Folder | Role |
|---|---|
backend/src/ |
Cloudflare Worker backend. Modular ES modules handling API requests, vote validation, and weekly Melee.gg-sync lifecycle triggers. Data stored in D1. |
docs/app/ |
Static client (plain HTML/CSS/JS) served from GitHub Pages. Calls the Worker URL directly with fetch. |
The backend is protected by per-device session tokens (see docs/SECURITY.md).
- Deploy the Worker and verify the
API_URLindocs/app/app.jspoints to it — seedocs/DEPLOYMENT.md. - Publish
docs/on GitHub Pages and point players at the/app/sub-path. - Configure the D1
settingstable — seedocs/DATABASE.md.
The app's API_URL auto-detects localhost and points to a local Worker dev server:
- Backend:
cd backend && npx wrangler dev— starts onhttp://localhost:8787. - Frontend:
python3 -m http.server 8080 --directory docs/app(or any static server). - Open:
http://localhost:8080— the app talks to your local Worker.
No code changes needed — the API_URL toggle is built in.
- Deployment & configuration — Worker deploy, GitHub Pages, D1 config.
- Database (D1 schema) — tables, columns, and award computation.
- Security model — how voting integrity is enforced.
- Load reliability — retry logic, lazy-loaded leaderboard.
- Triggers & lifecycle — weekly automation schedule and lifecycle functions.
The Cloudflare Worker backend has a comprehensive test suite using node:test and an
in-memory D1 mock — zero external dependencies:
cd backend && node --test "test/**/*.test.js"| Category | Files | Tests |
|---|---|---|
| Library (awards, auth, badges, careerStats, melee, meleeLeague, participation, seasonTable, voteAudit) | 9 | 200+ |
| Handlers (getAppData, submitVote, updateVote, linkAccount, unlinkAccount, getStandingsData, getLeaderboardData, getMySeasonStats, getMyCareerStats, getPlayerProfile, admin, etc.) | 12 | 200+ |
| Database (queries, schema) | 2 | 30+ |
| Triggers (syncFromMelee, backfillFromMelee) | 2 | 45+ |
| Router & rate limiter | 2 | 40+ |
| Frontend (app-core + responsive redesign phases 1–7 + shortcuts) | 10 | 130+ |
| Privacy guard | 1 | 5+ |
| Total | 41 files | 715 |
Test infrastructure: backend/test/helpers/mock-db.js (D1 mock), mock-fetch.js,
mock-crypto.js, fixtures.js, test-utils.js.