Back to Projects

VolleyX — Design and production of a mobile application for managing and scoring volleyball matches

Volleyball referee app deployed on App Stores. Real-time match management, PostgreSQL optimization, active user community.

Mobile PostgreSQL Expo-SDK React-Native Firebase Prisma CI/CD
VolleyX — Design and production of a mobile application for managing and scoring volleyball matches
Table des matières

Why

Volleyball referees had no suitable digital tool to manage scores, faults, and statistics in real time during matches. Existing solutions were either too complex or not specialized enough.

What

Volleyx is a complete mobile application that allows referees to manage a volleyball match from start to finish: real-time scoring, set management, fault tracking, match statistics, and history. Available on the App Store and Google Play Store.

How

Developed with cross-platform mobile technology and a PostgreSQL database for persistence. The architecture follows an offline-first model for use without connectivity. UX was designed in collaboration with real referees to ensure smooth usage in real conditions.

Technical case study – December 2025

1. Context and project origin

Four months ago, a regional volleyball referee (Centre-Val de Loire) shared a common pain point among amateur clubs:

  • Match scoring is still done on paper or whiteboards
  • Sheets are sent by photo or retyped into a spreadsheet
  • License tracking is approximate (shared files + manual reminders)
  • No reliable traceability for player evaluations

The goal was not to build a national or commercial product, but to ship a tool that referees, coaches, players, and club admins would actually adopt.

VolleyX

2. Main features delivered (MVP – 2 months)

  1. Sign-up and login with role selection (player – referee – coach – club admin)
  2. License status view (valid / expired / pending) + pre-expiry alert
  3. Real-time scoring during matches (scores + qualitative player evaluation)
  4. Dual evaluation grid: technical performance + sportsmanship
  5. Secure, filtered stats browsing per user role
  6. Self-service, full account deletion (GDPR and App Store requirement)

3. Architecture

Type: cross-platform mobile app + REST API backend

LayerTechnologyPrimary rationale
Mobile frontendReact Native + Expo SDKFast iOS/Android delivery, OTA updates, simplified build
BackendNode.js + PrismaFlexibility, strong typing, automatic OpenAPI
DatabasePostgreSQL 16Integrity constraints, JSONB, solid performance
AuthenticationFirebase AuthenticationDelegated identity, native JWT, MFA support
NotificationsExpo notificationsCross-platform reliability, native Auth integration
HostingGoogle Kubernetes Engine (GKE)Horizontal scale, managed ops, high availability

Architecture separates:

  • business logic
  • role-based access control (RBAC)
  • data persistence

Global architecture diagram

graph TD
    A[Mobile - React Native + Expo] -->|HTTPS + Firebase JWT| B[API FastAPI]
    B -->|JWT verification + RBAC| C[PostgreSQL]

    subgraph Backend
        B
        D[RBAC middleware]
        E[Scoring service]
        F[License service]
        B --> D
        D --> E
        D --> F
    end

    subgraph Database
        C --> G[Users + Roles]
        C --> H[Matches]
        C --> I[Ratings - performance + behavior]
        C --> J[Licenses]
    end

    K[FCM - Notifications] -->|push| B
    B -->|push| K

    L[Club Admin] -->|license management| B
    B -->|license management| L

    M[GKE - Kubernetes] -->|Orchestration| B

    N[Firebase Auth] -->|Authentication| A
    A -->|Authentication| N

4. Key technical points

4.1 Relational model (simplified, anonymized extract)

-- Core tables (anonymized)
CREATE TABLE users (
    id              uuid          PRIMARY KEY DEFAULT gen_random_uuid(),
    email           text          UNIQUE NOT NULL,
    role            text          NOT NULL CHECK (role IN ('player','referee','coach','administrator')),
    club_id         uuid,
    created_at      timestamptz   DEFAULT now()
);

CREATE TABLE licenses (
    id              uuid          PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id         uuid          REFERENCES users(id) ON DELETE CASCADE,
    status          text          NOT NULL,
    expires_at      date          NOT NULL
);

CREATE TABLE matches (
    id              uuid          PRIMARY KEY DEFAULT gen_random_uuid(),
    date            timestamptz   NOT NULL,
    club_id         uuid
);

CREATE TABLE ratings (
    id              uuid          PRIMARY KEY DEFAULT gen_random_uuid(),
    match_id        uuid          REFERENCES matches(id),
    player_id       uuid          REFERENCES users(id),
    score_technique integer       CHECK (score_technique BETWEEN 1 AND 5),
    score_comportement integer    CHECK (score_comportement BETWEEN 1 AND 5),
    created_by      uuid          REFERENCES users(id)
);

4.2 Role-based access control (conceptual extract)

// middleware/requireRole.js
const requireRole = (...allowedRoles) => {
  return (req, res, next) => {
    const user = req.user
    if (!user || !user.role) {
      return res.status(401).json({ error: 'Not authenticated' })
    }
    if (!allowedRoles.includes(user.role)) {
      return res.status(403).json({ error: 'Forbidden for this role' })
    }
    next()
  }
}

module.exports = requireRole

5. Main challenges and solutions

  • Concurrent input on the same match → lightweight lock + version check
  • In-match UX friction for referees → max 3 screens, instant visual feedback
  • Fine-grained permissions → centralized RBAC + exhaustive tests
  • Push notification reliability → FCM plus email fallback
  • GDPR / App Review compliance → self-service deletion + anonymization

6. Lessons learned (engineer viewpoint)

  • Poor relational modeling is far costlier to fix later than to get right upfront
  • Role management looks simple but quickly becomes the most complex component
  • A referee mid-match tolerates zero latency and zero friction
  • Cross-platform push notifications remain a recurring weak spot
  • Thinking about traceability and audit from day one prevents trust crises

7. Current status & next steps

Status: v1.0 submitted to the App Store (December 2025)
Pilot clubs: 21 clubs in Centre-Val de Loire (~25 active users)

Next steps being considered:

  • PDF / CSV export of match reports
  • Multi-club support for district committees
  • Optional real-time collaborative sync (via Firebase or PostgreSQL LISTEN/NOTIFY)

Thank you for reading.

Technologies & Tools

Commentaires