Bilingual tournament platform for BHOS's 32-team inter-major futsal championship.
- Role
- Full-stack developer
- Type
- Live site
- Year
- 2026
- Links
- Live site ↗



Problem
A 32-team championship needed one place for its matches, results and statistics.
Solution
A bilingual platform with the full tournament picture: fixtures, results, the bracket, teams and top scorers.
What I did
- The admin enters scores from a phone in the hall, and they appear on every open page within seconds, without a reload (Sanity Live).
- Wrote a self-updating bracket: only first-round teams are stored and the rest comes from results. When an old result is corrected, the results that depend on it stay hidden until an admin confirms them again.
- Shaped the admin panel for phones: a "Today's matches" list, large + and - buttons for the score and name suggestions for goalscorers.
- Added fan predictions, add-to-calendar (.ics, Google Calendar) and a score image for every match to share on WhatsApp and Telegram.
- Kept the tournament logic in a framework-free module and covered it with 80+ Vitest tests.
- Set up a strict CSP, HSTS, Turnstile and rate limits. Contact messages are stored in Sanity where only admins can read them, and the English site shows names in their international spelling.
How it's built
FansAZ / EN
AdminIn the hall, on a phone
Next.jsBracket, predictions
Sanity StudioInside the site
SanityContent Lake, Live API
The admin enters and publishes the score. Every open page changes within seconds, without a reload.
Stack
- Next.js
- React
- TypeScript
- Sanity
- Tailwind CSS
- GSAP
- next-intl
- Vitest
- Vercel