13 Commits

Author SHA1 Message Date
144c001c1b Fix basic auth: use htpasswd instead of openssl passwd
openssl passwd -apr1 produces inconsistent output in nginx:alpine.
Switch to htpasswd from apache2-utils which is the standard tool.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 06:14:40 +01:00
29db643407 Add nginx HTTP Basic Auth for production
A custom entrypoint generates /etc/nginx/.htpasswd at container startup
from AUTH_USER and AUTH_PASSWORD env vars (via openssl). No credentials
are baked into the image. Pass AUTH_USER and AUTH_PASSWORD in docker-compose.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 05:49:29 +01:00
2217489c15 Add README
Covers features, supported competitions, tech stack, local dev setup,
Docker production deployment, environment variables and project structure.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-17 20:18:10 +01:00
861462b41e Re-enable all competitions in the picker
Championship, Brasileirão, European Championship and FIFA World Cup
are now shown as tiles on the home screen.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-17 20:16:23 +01:00
b070b91115 Replace competition picker bar with full-page tile home screen
- New CompetitionHome page shows all competitions as clickable tiles
  in a responsive grid (4 → 3 → 2 columns)
- Selecting a tile navigates to the standings page
- Standings page has a back button to return to the home screen
- Emblems pre-loaded on mount so tiles show logos immediately
- Remove CompetitionPicker component from standings view

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-17 20:14:45 +01:00
072a985ba0 Make application responsive for mobile and tablet
Breakpoints at 600px (tablet) and 420px (mobile):
- Header: smaller emblem and title on mobile
- StandingsTable: hide DV/DT/Vorm at 600px, also W/D/L at 420px
- TeamMatchesModal: bottom sheet on mobile, hide matchday column
- CompetitionPicker: smaller buttons, hide country label on mobile

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-15 06:49:47 +01:00
36474d3525 Load all competition emblems upfront so picker shows logos immediately
Previously emblems were only cached after visiting each competition.
Now a single /api/competitions fetch on mount populates all emblems
at once, including the initially selected button.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-15 06:45:27 +01:00
0209aa806e Show clear error message on API rate limit (429)
Free plan allows 10 requests/min; show a Dutch user-friendly message
instead of a generic API error.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-15 06:41:15 +01:00
c0ca5b9072 Disable Championship and Brasileirão from competition picker
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-15 06:33:05 +01:00
90149d62e9 Disable EC and WC from competition picker
Tournament competitions don't have regular standings.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-15 06:29:34 +01:00
26b1779354 Add package-lock.json for reproducible Docker builds
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 20:04:35 +01:00
5db020132e Add Docker + nginx deployment for homelab
- Multi-stage Dockerfile: Node builds static assets, nginx serves them
- nginx proxies /api/* to football-data.org and injects X-Auth-Token
  server-side via FOOTBALL_API_KEY env var (key never in browser bundle)
- docker-compose.yml exposes the app on port 3000
- Extract apiFetch() helper: sends key in dev (Vite proxy), skips in prod
- .env.example updated with both dev and production key vars

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 07:40:20 +01:00
d8fba41ea5 Initial commit: football competition standings viewer
Vite + React app using football-data.org API to display standings
and match details for 12 competitions. Supports competition switching,
team match history modal, and Vite proxy to handle CORS.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 07:33:50 +01:00