In active developmentOwn product

EKSU Sports Hub

A sports platform for Ekiti State University. Students follow live scores, fixtures, results and tables; staff run competitions from an admin dashboard and control live matches from a separate operator console.

My role
Product design, front end, database, security model and deployment
Type
Own product
Category
Web application, Education
EKSU Sports Hub home page with live matches, today's fixtures and a league table preview.
Home: live now, today's matches and the table. Local build running on the project's demo data.

01

Overview

Campus football results usually live in group chats and on paper. EKSU Sports Hub gives them one public home: what is live, what is next, who is top of the table, and what happened in each match.

Behind the public site are two tools for staff. The admin dashboard manages competitions, teams, squads, fixtures, operator assignments and corrections. The match operator console is a deliberately plain app for the person at the pitch: score, clock, goals, cards, substitutions, stoppage time and periods.

  • Next.js
  • TypeScript
  • Tailwind CSS
  • Supabase
  • PostgreSQL
  • Row Level Security
  • Supabase Realtime
  • Web Push
  • pgTAP

02

The problem

A live score is only useful if it is right. The system has to accept updates from a phone at the side of a pitch, on an unreliable connection, and show the same score and match minute to everyone watching.

It also has to keep the public read-only, keep operators limited to the matches assigned to them, and leave a trail when anything is corrected.

03

Approach

I built the public site with Next.js server components behind a single data-source interface, so pages never know whether they are reading real data or the demo data used for development.

All writes go through PostgreSQL functions (RPCs) rather than table updates from the browser. Row Level Security decides who can read what, and roles (admin, manager, operator) decide who can call which function.

The database has its own test suite in pgTAP covering security, match flow, admin actions, realtime publication, line-ups, registration and notifications.

04

Architecture

Public site
Next.js App Router with loading, error and empty states on every route. Home, live, fixtures, results, tables, competitions, teams and a match centre.
Operator console
A separate app at /op with its own state machine. Commands are queued as intents, applied optimistically and reconciled with the server's canonical state.
Admin dashboard
Competitions, teams, squads, fixtures, operator assignments, live monitoring, event-based corrections, standings, staff and a read-only audit log.
Database
Supabase PostgreSQL with Row Level Security and SECURITY DEFINER functions as the only write path. 21 versioned migrations.
Realtime
Supabase Realtime sends a lightweight hint; clients then refetch canonical state instead of trusting the payload.
Notifications
Anonymous, per-device Web Push for followed matches and teams. Messages are queued in an outbox table in the same transaction as the match change.

05

Key features

  • Live match centre

    Score, running minute, timeline, line-ups on a responsive pitch that follows substitutions and red cards, stats and head-to-head.

  • Competitions and tables

    League tables calculated from completed matches, competition switching, fixtures and results by date, and top scorers.

  • Player registration and screening

    Players register with a private student number and are screened per team and season (pending, cleared, rejected, suspended) before joining a squad.

  • Line-ups and eligibility

    Formation, starting XI, bench and captain picked by an admin or the assigned operator. Kick-off needs both line-ups confirmed.

  • Match notifications

    Reminders, kick-off and goal alerts per match or team, with per-device preferences and no account required.

  • Corrections with history

    Mistakes are voided or added as new events; the score is recomputed from the events that remain, and every change is logged.

Match centre for an inter-faculty football match with score, timeline of goals and cards, and match information.
Match centre with a live timeline. Demo data.
The match centre on a phone, with the score header and event timeline.
Match centre on a phone.
League table on a phone with played, won, drawn, lost, goal difference, points and form.
League table with form guide.

06

Challenges

  1. Keeping the match clock honest

    Problem

    A ticking counter on each device drifts, and pauses or stoppage time make it worse.

    What I did

    The minute is derived from timestamps (period start, pauses, offset) and the server's clock, measured once per session, so every screen computes the same minute.

  2. Updating from a weak connection

    Problem

    An operator can tap Goal twice, lose signal, or act before the last action reached the server.

    What I did

    Actions become ordered intents with retry and discard. The console shows the optimistic result immediately, then replays anything still pending on top of the server's state.

  3. A public site that cannot be written to

    Problem

    Browsers talk to the database directly in a Supabase app, so a missed check is a public write.

    What I did

    No table is writable from the browser. Writes exist only as checked database functions, and pgTAP tests assert that anonymous users, operators and non-staff are refused.

07

Where it stands

Built

  • Public site, admin dashboard and operator console running on Supabase
  • Hosted Supabase project with migrations applied and the database test suite run against it
  • Player registration, screening, squads and line-ups
  • Per-device match and team notifications

The project is still being extended; the public launch date and domain are not final.

↑ ↓ to move · Enter to openAMIGODEV