Dashboard for (niche) sweepstakes tournaments with friends
  • Java 69%
  • JavaScript 20.9%
  • CSS 5.8%
  • HTML 3.6%
  • Dockerfile 0.7%
Find a file
2026-06-15 00:32:43 +01:00
src comment fixing, add disclaimer, license 2026-06-15 00:08:26 +01:00
.dockerignore initialise sweepstakes dashboard 2026-06-14 23:39:22 +01:00
.gitignore initialise sweepstakes dashboard 2026-06-14 23:39:22 +01:00
DEPLOYMENT.md trim readme 2026-06-15 00:26:21 +01:00
Dockerfile initialise sweepstakes dashboard 2026-06-14 23:39:22 +01:00
friends.json initialise sweepstakes dashboard 2026-06-14 23:39:22 +01:00
groups.json initialise sweepstakes dashboard 2026-06-14 23:39:22 +01:00
LICENSE comment fixing, add disclaimer, license 2026-06-15 00:08:26 +01:00
package-lock.json initialise sweepstakes dashboard 2026-06-14 23:39:22 +01:00
package.json initialise sweepstakes dashboard 2026-06-14 23:39:22 +01:00
pom.xml initialise sweepstakes dashboard 2026-06-14 23:39:22 +01:00
quotes.json initialise sweepstakes dashboard 2026-06-14 23:39:22 +01:00
README.md remove duplicate test section. 2026-06-15 00:32:43 +01:00
screenshot.png initialise sweepstakes dashboard 2026-06-14 23:39:22 +01:00
vitest.config.js initialise sweepstakes dashboard 2026-06-14 23:39:22 +01:00

World Cup Sweepstakes Dashboard

Tracks which friend/team is the dirtiest (cards) and worst (points / goal difference) across your group's World Cup sweepstakes.

  • Backend: Java 17 + Spring Boot (REST API + static frontend)
  • Frontend: plain HTML/CSS/JS, polls the backend every 60s
  • Data source: API-Football v3
Dashboard screenshot

Contents

  1. Get an API-Football key
  2. Configure friends & teams
  3. Configure the tournament
  4. Run it
  5. How it works
  6. Scoring
  7. API endpoint
  8. Deploying
  9. Forking this for your own group or tournament
  10. Who built this

Get an API-Football key

Sign up at API-Football and grab an API key from your dashboard. Note that the free plan's season coverage is limited, check their docs for which seasons/competitions your plan includes.

Set the key as an environment variable before running the app:

export API_FOOTBALL_KEY=your-key-here

Configure friends & teams

Edit friends.json at the project root. Each entry is a friend and their teams.

[
  {"friend": "Alice", "teams": ["Argentina", "France", "Japan", "Morocco"], "flag": "🏴"},
  ...
]

flag is optional. Any emoji or short text, shown next to the friend's name on the dashboard.

This file is read from disk on every app startup, so you can edit it without rebuilding.

Quotes

Edit quotes.json A list of quotes (inspriational or maybe some friend lore) shown on "Today's Fixtures" when two friends' teams face each other:

[
  "Bragging rights are on the line tonight."
]

Each fixture gets a quote picked deterministically from this list.

Also read from disk on startup, no rebuild needed.

Configure the tournament

In src/main/resources/application.yml:

api-football:
  league-id: 1     # 1 = FIFA World Cup in API-Football
  season: 2026     # tournament year

Run it

mvn spring-boot:run

Then open http://localhost:8080.

How it works

The app refreshes fixtures from API-Football on startup and at defined intervals (sweepstakes.refresh-interval-ms) It caches finished-fixture results to data/fixture-cache.json so they're never re-fetched.

The dashboard polls /api/leaderboard every 60s, just reading the cached result from memory.

Scoring

  • Dirtiest (team or friend) = yellow cards + 2 × red cards + 0.5 × fouls + 3 × penalties conceded.
  • Worst = lowest points (3/win, 1/draw), tie-broken by most goals conceded, then most shots conceded.

API endpoint

  • GET /api/leaderboard current aggregated stats (JSON)

Deploying

See DEPLOYMENT.md for Cloud Run deployment and custom domain setup.

Forking this for your own group or tournament

This repo is intentionally generic. The dashboard, scoring, and "Today's Fixtures" logic don't assume any specific tournament, friend count, or number of teams per friend. friends.json, quotes.json and groups.json ship with placeholder content you can edit directly:

  1. Fill in your own group:

    • friends.json: one entry per person with their team picks (any number of teams per person). Team names must match API-Football's naming for the competition you're tracking.
    • quotes.json: any list of quotes or friendship lore, shown on fixture cards when two friends' teams play each other.
    • groups.json: the tournament's group-stage draw (group name -> team names). Update for your competition.
  2. Set the competition in src/main/resources/application.yml:

    api-football:
      league-id: 1     # look up the right ID for your competition in API-Football's docs
      season: 2026     # the season/year for that competition
    
  3. Update branding index.html (title/heading) and style.css (color theme) are currently World Cup 2026-themed; tweak for your event.

  4. Tune scoring (optional) The highly advanced dirty-score formula (yellow/red cards, fouls, penalties) is in TeamRecord.java if you want different weightings.

  5. Run tests with mvn test && npm test

  6. Run locally (mvn spring-boot:run) to check everything loads, then deploy per DEPLOYMENT.md with your own GCP project and domain.

Who built this

Made with love as a pair programming endeavour between me (a human) and claude code. Respect our robot overlords. #noyolo

License

MIT