MatchCard: display '0–0' instead of '?–?' when a match is live but
score_ft_home is still NULL (sync hasn't picked up the score yet, or
Wikipedia hasn't been updated — every match starts at 0-0).
recentMatches resolver: fetch limit*2 rows then filter out live matches
so a match with score_ft_home=0 that is still in progress doesn't appear
in both the live section and recent results simultaneously.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diagonal ±45° goal-net texture on body background. All card surfaces
converted from opaque #0a1810 to glass-card (backdrop-blur + semi-transparent
rgba) or glass-card-hero (gradient rgba) so the net pattern shows through.
Covers all pages: home, groups, history, search, stats, teams, tournaments,
players, match cards, and 404.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Team page: add Tournament Participations (year pills → /tournaments/[year]) and
Match History (grouped by year, W/D/L badge, opponent, score from team's perspective,
PSO/AET annotations, each row → match anchor)
- GraphQL: extend matches() query with teamId filter (OR team1_id/team2_id)
- Match card: link team names to /teams/[slug]; fix ET score display — show scoreEt
as headline for AET matches, scoreFt as footnote; winner determination uses
scoreP ?? scoreEt ?? scoreFt
- Tournament page: scorer names below each match linked to /players/[name] with
dotted underline (solid + green on hover)
- Stats page: reduce mobile padding on Goals chart, Top Scorers, Titles, Goals by
Minute — hide progress bars and trophy emojis on small screens
- Homepage: Golden Boot Race same mobile padding/bar treatment; add slug to match
team queries
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replaced flex-wrap with grid-cols-[1fr_auto_1fr] so team columns fill
equally on either side of the score. Score font scales down on mobile,
padding tightens, team names truncate instead of wrapping.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
For shootout games the FT score (e.g. 2–2) was the main display, which
was misleading. Now the penalty score is the headline (4–2) with
"2–2 a.e.t." below it. Winner highlighting also uses the penalty score.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Full-stack World Cup web app (1930–2026):
- Next.js 16 + TailwindCSS 4 + GraphQL Yoga + Apollo Client 4 + Drizzle + PostgreSQL 16
- 23 tournaments synced from openfootball/worldcup.json (matches, goals, teams, stadiums, squads, standings)
- Pages: home (live), groups, stats, history, search, /tournaments/[year], /teams/[slug], /players/[name]
- Live match detection via isLive() + Apollo 60 s poll
- pnpm with node-linker=hoisted for Docker compatibility
- docker-compose.yml with Traefik labels (HTTPS redirect, TLS, security middleware)
- docker-compose.dev.yml for local dev (DB only, port 5432 exposed)
- Dockerfile: multi-stage pnpm build, standalone Next.js output, sync script bundled
- .env.example with all required variables documented
- Comprehensive README with local dev, deployment, schema, and GraphQL API reference
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>