You know what's fun? Watching people swim. You know what's not? Trying to keep track of swimming scores on paper while 40+ events are happening, the pool's echoing, and someone just dropped the heat sheet into the water.
That’s where Aquaclash ScoreApp dives in (yes, pun intended).
SLIIT’s annual inter-university swimming championship, Aquaclash, needed a
serious tech boost. In 2024, Manula Cooray SLIIT’s swimming captain for 2025
pitched the idea
“Can we build a real-time score app for the event? So competitors, organizers, and spectators can all see the scores in one place?”
So, Challenge accepted.
Designed and deployed a fully responsive, real-time scoring web app tailored for live swimming tournaments. It replaced manual sheets with something fast, reliable, and actually usable from poolside.
Key Features
- Real-time scoreboard for all users (no login required)
- Admin panel secured via Google Auth
- Updates on event results as they happen
- Mobile-friendly & responsive UI
- Public and live from the start
“This app was a lifesaver. We didn’t have to worry about writing and recalculating after every event. Everyone had access — swimmers, officials, even my uncle who watched it from home.” — Manula Cooray, SLIIT Swimming Captain (2025)

Tech Stack
- Frontend: Next.js (App Router)
- Design System: Shadcn + Tailwind
- Backend & Auth: Supabase (Database + Google Auth)
- Hosting: Vercel
Scoring Rules
interface EventResult {
eventId: string;
universityId: string;
place: number; // 1 = Gold, 2 = Silver, 3 = Bronze
}
function getPoints(place: number): number {
switch (place) {
case 1:
return 5;
case 2:
return 3;
case 3:
return 1;
default:
return 0;
}
}
function calculateUniversityScore(
results: EventResult[],
): Record<string, number> {
const scores: Record<string, number> = {};
for (const result of results) {
scores[result.universityId] =
(scores[result.universityId] || 0) + getPoints(result.place);
}
return scores;
}
Database Structure
universities id, name, logo
teams id, university_id (FK), event_id (FK)
players id, name, university_id (FK), event_id (FK), team_id (nullable)
events id, name, type (individual / relay), gender, order
results id, event_id (FK), player_id or team_id (FK), place (1/2/3), timestamp
This setup supports both individual and relay events, assigning results either to a single player or a team.
System Architecture
[Client (Browser)] --> [Next.js Frontend] --> [Supabase (DB + Auth)]
- Public Scoreboard: Static-rendered pages with client-side fetching
- Admin Panel: Secured routes using Supabase’s Google Auth
- Data Sync: Supabase’s real-time subscriptions used to reflect results instantly
- No Offline Usage: The system is fully online-dependent, ensuring data consistency and real-time updates.
What I Learned
- Real-time data sync is crucial for live sports — Supabase subscriptions made this seamless.
- UI/UX matters: poolside users need big buttons, clear scores, and zero distractions.
- Auth flows must be simple for admins but invisible for public viewers.
- Testing with actual event data and feedback from swimmers/officials is invaluable.
- Deploying fast, iterating with user feedback, and keeping things reliable is key for event tech.
Note: This app is currently for in-house use only. Soon, I'll make it public!