From b1413562472ad251162399fd1150c9fc7d668784 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Kr=C3=BCger?= Date: Mon, 15 Jun 2026 18:08:23 +0200 Subject: [PATCH] refactor: replace hardcoded hex colors with theme tokens, move data/ to root MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add --color-green-mid token (#4a7a55) to @theme for dimmer stat values - Replace all text-[#hex]/bg-[#hex] arbitrary values with named tokens: text-green, text-green-light, text-green-sec, text-green-muted, text-green-dark, text-green-mid, text-text, bg-card, bg-bg, border-border - Replace rgba(34,197,94,X) inline styles with bg-green/X opacity modifiers - Convert single-prop style={{ borderColor/background }} to className - Fix SVG stroke="#dff5e8" → stroke="currentColor" - Use CSS variables in globals.css base styles (background-color, color) - Move app/data/wikipedia/ → data/ (project root, not inside Next.js app dir) - Update Dockerfile, seed.ts, scrape-wikipedia.ts paths accordingly - Remove unused app/data/world_cup.csv Co-Authored-By: Claude Sonnet 4.6 --- Dockerfile | 2 +- app/data/world_cup.csv | 23 --- app/globals.css | 11 +- app/groups/page.tsx | 33 ++--- app/history/page.tsx | 32 ++--- app/layout.tsx | 6 +- app/not-found.tsx | 6 +- app/page.tsx | 51 ++++--- app/players/[name]/page.tsx | 26 ++-- app/search/page.tsx | 59 ++++---- app/stats/page.tsx | 131 +++++++++--------- app/teams/[slug]/page.tsx | 72 +++++----- app/tournaments/[year]/page.tsx | 70 +++++----- components/live-badge.tsx | 4 +- components/match-card.tsx | 32 ++--- components/nav.tsx | 33 ++--- components/team-flag.tsx | 2 +- .../1930/worldcup.groups.json | 0 .../wikipedia => data}/1930/worldcup.json | 0 .../1930/worldcup.meta.json | 0 .../1930/worldcup.squads.json | 0 .../1930/worldcup.stadiums.json | 0 .../wikipedia => data}/1934/worldcup.json | 0 .../1934/worldcup.meta.json | 0 .../1934/worldcup.stadiums.json | 0 .../wikipedia => data}/1938/worldcup.json | 0 .../1938/worldcup.meta.json | 0 .../1938/worldcup.stadiums.json | 0 .../1950/worldcup.groups.json | 0 .../wikipedia => data}/1950/worldcup.json | 0 .../1950/worldcup.meta.json | 0 .../1950/worldcup.squads.json | 0 .../1950/worldcup.stadiums.json | 0 .../1954/worldcup.groups.json | 0 .../wikipedia => data}/1954/worldcup.json | 0 .../1954/worldcup.meta.json | 0 .../1954/worldcup.squads.json | 0 .../1954/worldcup.stadiums.json | 0 .../1958/worldcup.groups.json | 0 .../wikipedia => data}/1958/worldcup.json | 0 .../1958/worldcup.meta.json | 0 .../1958/worldcup.squads.json | 0 .../1958/worldcup.stadiums.json | 0 .../1962/worldcup.groups.json | 0 .../wikipedia => data}/1962/worldcup.json | 0 .../1962/worldcup.meta.json | 0 .../1962/worldcup.squads.json | 0 .../1962/worldcup.stadiums.json | 0 .../1966/worldcup.groups.json | 0 .../wikipedia => data}/1966/worldcup.json | 0 .../1966/worldcup.meta.json | 0 .../1966/worldcup.squads.json | 0 .../1966/worldcup.stadiums.json | 0 .../1970/worldcup.groups.json | 0 .../wikipedia => data}/1970/worldcup.json | 0 .../1970/worldcup.meta.json | 0 .../1970/worldcup.squads.json | 0 .../1970/worldcup.stadiums.json | 0 .../1974/worldcup.groups.json | 0 .../wikipedia => data}/1974/worldcup.json | 0 .../1974/worldcup.meta.json | 0 .../1974/worldcup.squads.json | 0 .../1974/worldcup.stadiums.json | 0 .../1978/worldcup.groups.json | 0 .../wikipedia => data}/1978/worldcup.json | 0 .../1978/worldcup.meta.json | 0 .../1978/worldcup.squads.json | 0 .../1978/worldcup.stadiums.json | 0 .../1982/worldcup.groups.json | 0 .../wikipedia => data}/1982/worldcup.json | 0 .../1982/worldcup.meta.json | 0 .../1982/worldcup.squads.json | 0 .../1982/worldcup.stadiums.json | 0 .../1986/worldcup.groups.json | 0 .../wikipedia => data}/1986/worldcup.json | 0 .../1986/worldcup.meta.json | 0 .../1986/worldcup.squads.json | 0 .../1986/worldcup.stadiums.json | 0 .../1990/worldcup.groups.json | 0 .../wikipedia => data}/1990/worldcup.json | 0 .../1990/worldcup.meta.json | 0 .../1990/worldcup.squads.json | 0 .../1990/worldcup.stadiums.json | 0 .../1994/worldcup.groups.json | 0 .../wikipedia => data}/1994/worldcup.json | 0 .../1994/worldcup.meta.json | 0 .../1994/worldcup.squads.json | 0 .../1994/worldcup.stadiums.json | 0 .../1998/worldcup.groups.json | 0 .../wikipedia => data}/1998/worldcup.json | 0 .../1998/worldcup.meta.json | 0 .../1998/worldcup.squads.json | 0 .../1998/worldcup.stadiums.json | 0 .../2002/worldcup.groups.json | 0 .../wikipedia => data}/2002/worldcup.json | 0 .../2002/worldcup.meta.json | 0 .../2002/worldcup.squads.json | 0 .../2002/worldcup.stadiums.json | 0 .../2006/worldcup.groups.json | 0 .../wikipedia => data}/2006/worldcup.json | 0 .../2006/worldcup.meta.json | 0 .../2006/worldcup.squads.json | 0 .../2006/worldcup.stadiums.json | 0 .../2010/worldcup.groups.json | 0 .../wikipedia => data}/2010/worldcup.json | 0 .../2010/worldcup.meta.json | 0 .../2010/worldcup.squads.json | 0 .../2010/worldcup.stadiums.json | 0 .../2014/worldcup.groups.json | 0 .../wikipedia => data}/2014/worldcup.json | 0 .../2014/worldcup.meta.json | 0 .../2014/worldcup.squads.json | 0 .../2014/worldcup.stadiums.json | 0 .../2018/worldcup.groups.json | 0 .../wikipedia => data}/2018/worldcup.json | 0 .../2018/worldcup.meta.json | 0 .../2018/worldcup.squads.json | 0 .../2018/worldcup.stadiums.json | 0 .../2022/worldcup.groups.json | 0 .../wikipedia => data}/2022/worldcup.json | 0 .../2022/worldcup.meta.json | 0 .../2022/worldcup.squads.json | 0 .../2022/worldcup.stadiums.json | 0 scripts/scrape-wikipedia.ts | 6 +- scripts/seed.ts | 2 +- 125 files changed, 279 insertions(+), 322 deletions(-) delete mode 100644 app/data/world_cup.csv rename {app/data/wikipedia => data}/1930/worldcup.groups.json (100%) rename {app/data/wikipedia => data}/1930/worldcup.json (100%) rename {app/data/wikipedia => data}/1930/worldcup.meta.json (100%) rename {app/data/wikipedia => data}/1930/worldcup.squads.json (100%) rename {app/data/wikipedia => data}/1930/worldcup.stadiums.json (100%) rename {app/data/wikipedia => data}/1934/worldcup.json (100%) rename {app/data/wikipedia => data}/1934/worldcup.meta.json (100%) rename {app/data/wikipedia => data}/1934/worldcup.stadiums.json (100%) rename {app/data/wikipedia => data}/1938/worldcup.json (100%) rename {app/data/wikipedia => data}/1938/worldcup.meta.json (100%) rename {app/data/wikipedia => data}/1938/worldcup.stadiums.json (100%) rename {app/data/wikipedia => data}/1950/worldcup.groups.json (100%) rename {app/data/wikipedia => data}/1950/worldcup.json (100%) rename {app/data/wikipedia => data}/1950/worldcup.meta.json (100%) rename {app/data/wikipedia => data}/1950/worldcup.squads.json (100%) rename {app/data/wikipedia => data}/1950/worldcup.stadiums.json (100%) rename {app/data/wikipedia => data}/1954/worldcup.groups.json (100%) rename {app/data/wikipedia => data}/1954/worldcup.json (100%) rename {app/data/wikipedia => data}/1954/worldcup.meta.json (100%) rename {app/data/wikipedia => data}/1954/worldcup.squads.json (100%) rename {app/data/wikipedia => data}/1954/worldcup.stadiums.json (100%) rename {app/data/wikipedia => data}/1958/worldcup.groups.json (100%) rename {app/data/wikipedia => data}/1958/worldcup.json (100%) rename {app/data/wikipedia => data}/1958/worldcup.meta.json (100%) rename {app/data/wikipedia => data}/1958/worldcup.squads.json (100%) rename {app/data/wikipedia => data}/1958/worldcup.stadiums.json (100%) rename {app/data/wikipedia => data}/1962/worldcup.groups.json (100%) rename {app/data/wikipedia => data}/1962/worldcup.json (100%) rename {app/data/wikipedia => data}/1962/worldcup.meta.json (100%) rename {app/data/wikipedia => data}/1962/worldcup.squads.json (100%) rename {app/data/wikipedia => data}/1962/worldcup.stadiums.json (100%) rename {app/data/wikipedia => data}/1966/worldcup.groups.json (100%) rename {app/data/wikipedia => data}/1966/worldcup.json (100%) rename {app/data/wikipedia => data}/1966/worldcup.meta.json (100%) rename {app/data/wikipedia => data}/1966/worldcup.squads.json (100%) rename {app/data/wikipedia => data}/1966/worldcup.stadiums.json (100%) rename {app/data/wikipedia => data}/1970/worldcup.groups.json (100%) rename {app/data/wikipedia => data}/1970/worldcup.json (100%) rename {app/data/wikipedia => data}/1970/worldcup.meta.json (100%) rename {app/data/wikipedia => data}/1970/worldcup.squads.json (100%) rename {app/data/wikipedia => data}/1970/worldcup.stadiums.json (100%) rename {app/data/wikipedia => data}/1974/worldcup.groups.json (100%) rename {app/data/wikipedia => data}/1974/worldcup.json (100%) rename {app/data/wikipedia => data}/1974/worldcup.meta.json (100%) rename {app/data/wikipedia => data}/1974/worldcup.squads.json (100%) rename {app/data/wikipedia => data}/1974/worldcup.stadiums.json (100%) rename {app/data/wikipedia => data}/1978/worldcup.groups.json (100%) rename {app/data/wikipedia => data}/1978/worldcup.json (100%) rename {app/data/wikipedia => data}/1978/worldcup.meta.json (100%) rename {app/data/wikipedia => data}/1978/worldcup.squads.json (100%) rename {app/data/wikipedia => data}/1978/worldcup.stadiums.json (100%) rename {app/data/wikipedia => data}/1982/worldcup.groups.json (100%) rename {app/data/wikipedia => data}/1982/worldcup.json (100%) rename {app/data/wikipedia => data}/1982/worldcup.meta.json (100%) rename {app/data/wikipedia => data}/1982/worldcup.squads.json (100%) rename {app/data/wikipedia => data}/1982/worldcup.stadiums.json (100%) rename {app/data/wikipedia => data}/1986/worldcup.groups.json (100%) rename {app/data/wikipedia => data}/1986/worldcup.json (100%) rename {app/data/wikipedia => data}/1986/worldcup.meta.json (100%) rename {app/data/wikipedia => data}/1986/worldcup.squads.json (100%) rename {app/data/wikipedia => data}/1986/worldcup.stadiums.json (100%) rename {app/data/wikipedia => data}/1990/worldcup.groups.json (100%) rename {app/data/wikipedia => data}/1990/worldcup.json (100%) rename {app/data/wikipedia => data}/1990/worldcup.meta.json (100%) rename {app/data/wikipedia => data}/1990/worldcup.squads.json (100%) rename {app/data/wikipedia => data}/1990/worldcup.stadiums.json (100%) rename {app/data/wikipedia => data}/1994/worldcup.groups.json (100%) rename {app/data/wikipedia => data}/1994/worldcup.json (100%) rename {app/data/wikipedia => data}/1994/worldcup.meta.json (100%) rename {app/data/wikipedia => data}/1994/worldcup.squads.json (100%) rename {app/data/wikipedia => data}/1994/worldcup.stadiums.json (100%) rename {app/data/wikipedia => data}/1998/worldcup.groups.json (100%) rename {app/data/wikipedia => data}/1998/worldcup.json (100%) rename {app/data/wikipedia => data}/1998/worldcup.meta.json (100%) rename {app/data/wikipedia => data}/1998/worldcup.squads.json (100%) rename {app/data/wikipedia => data}/1998/worldcup.stadiums.json (100%) rename {app/data/wikipedia => data}/2002/worldcup.groups.json (100%) rename {app/data/wikipedia => data}/2002/worldcup.json (100%) rename {app/data/wikipedia => data}/2002/worldcup.meta.json (100%) rename {app/data/wikipedia => data}/2002/worldcup.squads.json (100%) rename {app/data/wikipedia => data}/2002/worldcup.stadiums.json (100%) rename {app/data/wikipedia => data}/2006/worldcup.groups.json (100%) rename {app/data/wikipedia => data}/2006/worldcup.json (100%) rename {app/data/wikipedia => data}/2006/worldcup.meta.json (100%) rename {app/data/wikipedia => data}/2006/worldcup.squads.json (100%) rename {app/data/wikipedia => data}/2006/worldcup.stadiums.json (100%) rename {app/data/wikipedia => data}/2010/worldcup.groups.json (100%) rename {app/data/wikipedia => data}/2010/worldcup.json (100%) rename {app/data/wikipedia => data}/2010/worldcup.meta.json (100%) rename {app/data/wikipedia => data}/2010/worldcup.squads.json (100%) rename {app/data/wikipedia => data}/2010/worldcup.stadiums.json (100%) rename {app/data/wikipedia => data}/2014/worldcup.groups.json (100%) rename {app/data/wikipedia => data}/2014/worldcup.json (100%) rename {app/data/wikipedia => data}/2014/worldcup.meta.json (100%) rename {app/data/wikipedia => data}/2014/worldcup.squads.json (100%) rename {app/data/wikipedia => data}/2014/worldcup.stadiums.json (100%) rename {app/data/wikipedia => data}/2018/worldcup.groups.json (100%) rename {app/data/wikipedia => data}/2018/worldcup.json (100%) rename {app/data/wikipedia => data}/2018/worldcup.meta.json (100%) rename {app/data/wikipedia => data}/2018/worldcup.squads.json (100%) rename {app/data/wikipedia => data}/2018/worldcup.stadiums.json (100%) rename {app/data/wikipedia => data}/2022/worldcup.groups.json (100%) rename {app/data/wikipedia => data}/2022/worldcup.json (100%) rename {app/data/wikipedia => data}/2022/worldcup.meta.json (100%) rename {app/data/wikipedia => data}/2022/worldcup.squads.json (100%) rename {app/data/wikipedia => data}/2022/worldcup.stadiums.json (100%) diff --git a/Dockerfile b/Dockerfile index da3ce7c..13c227a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -22,7 +22,7 @@ COPY --from=builder /app/scripts ./scripts COPY --from=builder /app/lib ./lib COPY --from=builder /app/package.json ./package.json COPY --from=builder /app/tsconfig.json ./tsconfig.json -COPY --from=builder /app/app/data ./app/data +COPY --from=builder /app/data ./data USER nextjs EXPOSE 3000 ENV PORT=3000 HOSTNAME="0.0.0.0" diff --git a/app/data/world_cup.csv b/app/data/world_cup.csv deleted file mode 100644 index 98148e0..0000000 --- a/app/data/world_cup.csv +++ /dev/null @@ -1,23 +0,0 @@ -Year,Host,Teams,Champion,Runner-Up,TopScorrer,Attendance,AttendanceAvg,Matches -2022,Qatar,32,Argentina,France,Kylian Mbappé - 8,3404252,53191,64 -2018,Russia,32,France,Croatia,Harry Kane - 6,3031768,47371,64 -2014,Brazil,32,Germany,Argentina,James Rodríguez - 6,3429873,53592,64 -2010,South Africa,32,Spain,Netherlands,"Wesley Sneijder, Thomas Müller... - 5",3178856,49670,64 -2006,Germany,32,Italy,France,Miroslav Klose - 5,3352605,52384,64 -2002,"Korea Republic, Japan",32,Brazil,Germany,Ronaldo - 8,2705337,42271,64 -1998,France,32,France,Brazil,Davor Šuker - 6,2903477,45367,64 -1994,United States,24,Brazil,Italy,"Hristo Stoichkov, Oleg Salenko - 6",3587538,68991,52 -1990,Italy,24,West Germany,Argentina,Salvatore Schillaci - 6,2516215,48389,52 -1986,Mexico,24,Argentina,West Germany,Gary Lineker - 6,2394031,46039,52 -1982,Spain,24,Italy,West Germany,Paolo Rossi - 6,2109723,40572,52 -1978,Argentina,16,Argentina,Netherlands,Mario Kempes - 6,1545791,40679,38 -1974,Germany,16,West Germany,Netherlands,Grzegorz Lato - 7,1865753,49099,38 -1970,Mexico,16,Brazil,Italy,Gerd Müller - 10,1603975,50124,32 -1966,England,16,England,West Germany,Eusébio - 9,1563135,48848,32 -1962,Chile,16,Brazil,Czechoslovakia,"Leonel Sánchez, Flórián Albert... - 4",893172,27912,32 -1958,Sweden,16,Brazil,Sweden,Just Fontaine - 13,819810,23423,35 -1954,Switzerland,16,Germany,Hungary,Sándor Kocsis - 11,768607,29562,26 -1950,Brazil,15,Uruguay,Brazil,Ademir - 8,1045246,47511,22 -1938,France,16,Italy,Hungary,Leônidas - 7,375700,20872,18 -1934,Italy,16,Italy,Czechoslovakia,Oldřich Nejedlý - 5,363000,21353,17 -1930,Uruguay,13,Uruguay,Argentina,Guillermo Stábile - 8,590549,32808,18 diff --git a/app/globals.css b/app/globals.css index 4fad125..9034a3d 100644 --- a/app/globals.css +++ b/app/globals.css @@ -12,6 +12,7 @@ --color-green-sec: #6abf7a; --color-green-muted: #2a5c35; --color-green-dark: #1a3a22; + --color-green-mid: #4a7a55; --color-text: #dff5e8; --color-border: rgba(34,197,94,0.15); @@ -25,7 +26,7 @@ html { scroll-behavior: smooth; } body { - background-color: #040d08; + background-color: var(--color-bg); /* Diagonal goal-net pattern */ background-image: repeating-linear-gradient( @@ -38,7 +39,7 @@ rgba(34,197,94,0.028) 0, rgba(34,197,94,0.028) 1px, transparent 1px, transparent 28px ); - color: #dff5e8; + color: var(--color-text); font-family: "Space Grotesk", system-ui, sans-serif; min-height: 100vh; overflow-x: hidden; @@ -47,7 +48,7 @@ /* Glass card — semi-transparent over the body net pattern */ .glass-card { background: rgba(4, 18, 8, 0.78); - border: 1px solid rgba(34,197,94,0.15); + border: 1px solid var(--color-border); border-radius: 1rem; overflow: hidden; backdrop-filter: blur(10px); @@ -56,7 +57,7 @@ .glass-card-hero { background: linear-gradient(145deg, rgba(13,32,22,0.82), rgba(16,42,28,0.82)); - border: 1px solid rgba(34,197,94,0.28); + border: 1px solid color-mix(in srgb, var(--color-green) 28%, transparent); border-radius: 1rem; overflow: hidden; backdrop-filter: blur(10px); @@ -65,7 +66,7 @@ ::-webkit-scrollbar { width: 5px; } ::-webkit-scrollbar-track { background: #020a04; } - ::-webkit-scrollbar-thumb { background: rgba(34,197,94,0.25); border-radius: 4px; } + ::-webkit-scrollbar-thumb { background: color-mix(in srgb, var(--color-green) 25%, transparent); border-radius: 4px; } @keyframes livePulse { 0%, 100% { opacity: 1; transform: scale(1); } diff --git a/app/groups/page.tsx b/app/groups/page.tsx index 27ebe99..20d2592 100644 --- a/app/groups/page.tsx +++ b/app/groups/page.tsx @@ -36,14 +36,14 @@ export default function GroupsPage() { return (
-

2026 Groups

-

48 teams · 12 groups · Top 2 + 8 best 3rd-place advance

+

2026 Groups

+

48 teams · 12 groups · Top 2 + 8 best 3rd-place advance

{loading && !data && (
{Array.from({ length: 12 }).map((_, i) => ( -
+
))}
)} @@ -58,13 +58,11 @@ export default function GroupsPage() { const letter = groupName.replace('Group ', '') return (
-
- GROUP {letter} +
+ GROUP {letter}
-
Team PW @@ -73,24 +71,19 @@ export default function GroupsPage() {
{sorted.map((t, idx) => ( -
+
- {t.team.name} + {t.team.name}
{[t.played, t.won, t.drawn, t.lost].map((v, i) => ( - {v} + {v} ))} - + {t.goalDiff > 0 ? `+${t.goalDiff}` : t.goalDiff} - {t.pts} + {t.pts}
))} diff --git a/app/history/page.tsx b/app/history/page.tsx index b4edfc4..d94cfa7 100644 --- a/app/history/page.tsx +++ b/app/history/page.tsx @@ -33,17 +33,17 @@ export default function HistoryPage() { return (
-

+

World Cup History

-

+

Every edition — Uruguay 1930 through 2026 · {tournaments.length} tournaments

{loading && !data && (
{Array.from({ length: 24 }).map((_, i) => ( -
+
))}
)} @@ -54,52 +54,50 @@ export default function HistoryPage() { const topScorer = t.topScorers?.[0] return ( -
+
{/* Year watermark */} -
+
{t.year}
-
{t.year}
-
+
{t.year}
+
{t.host}
{inProgress - ?
+ ?
IN PROGRESS
: t.winner && (
-
{t.winner}
+
{t.winner}
)}
{!inProgress && t.winner && t.runnerUp && ( -
- {t.winner} - def. +
+ {t.winner} + def. {t.runnerUp}
)} -
+
{t.totalGoals != null && {t.totalGoals}} {t.matchesCount != null && {t.matchesCount} games} {t.teamsCount != null && 🏳 {t.teamsCount} teams}
{topScorer && ( -
- Golden Boot: {topScorer.playerName} ({topScorer.goals}) +
+ Golden Boot: {topScorer.playerName} ({topScorer.goals})
)}
diff --git a/app/layout.tsx b/app/layout.tsx index b715a64..5c1802a 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -35,11 +35,11 @@ export default function RootLayout({ children }: { children: React.ReactNode })