Retour aux projets
PubliéPersonnel

BDS Tournament

Remplacer Excel par une plateforme web live pour gérer trois tournois simultanément.

Publié janvier 20267 min de lecture

🎯 Le Contexte & L'Objectif

En tant que Vice-Président du Bureau des Sports d'ESIGELEC Poitiers, j'organise chaque année des tournois sportifs inter-étudiants. Jusqu'ici, la gestion se faisait à la main : un fichier bloc-notes pour les équipes, un tableur Excel pour les scores, et beaucoup de copier-coller pour tenir tout le monde informé. Le résultat était fonctionnel mais fastidieux, peu lisible pour les participants, et sans aucune visibilité publique en temps réel.

Pour l'édition de janvier 2026 — trois tournois simultanés : Babyfoot (8 équipes), Ping-Pong Solo (16 joueurs) et Ping-Pong Duo (7 équipes) — l'objectif était clair : remplacer le tableur par une vraie plateforme web accessible depuis n'importe quel smartphone, affichant les scores, les classements et les brackets au fur et à mesure des matchs. L'ensemble du tournoi devait se dérouler sur environ deux semaines, avec des dizaines d'étudiants concernés.


Aperçu général de la plateforme et de la navigation entre les tournois

🛠️ Ma Contribution & Mon Rôle

J'ai conçu et développé l'intégralité du projet seul, de l'architecture initiale au déploiement en production, en parallèle de l'organisation logistique de l'événement.

Concrètement :

  • Modélisation des données : définition des structures JSON pour chaque format de tournoi (poules, ligues, brackets), avec des particularités propres à chaque sport (BO3 en finale de babyfoot, BO5 en ping-pong duo, système de points différent pour le ping-pong solo).
  • Développement front-end : construction de toutes les pages et composants React — tableaux de classement, listes de matchs, fiches équipes/joueurs, et trois composants de bracket distincts adaptés aux formats de chaque tournoi.
  • Interface d'administration : création d'un panneau d'administration accessible uniquement en développement, permettant de saisir les scores et de sauvegarder les fichiers JSON directement depuis le navigateur via un plugin Vite sur mesure.
  • CI/CD : mise en place d'un pipeline GitHub Actions qui reconstruit et redéploie automatiquement le site sur GitHub Pages à chaque push.

💻 Stack Technique

  • Frontend : React 19 avec Vite 7 — un duo choisi pour la rapidité de démarrage et le rechargement à chaud (HMR) pendant le développement, essentiel quand chaque heure compte.
  • Routing : React Router v7 pour la navigation côté client entre les trois tournois et leurs sous-pages (équipes, classements, bracket).
  • Styling : Tailwind CSS 4.0 via son plugin Vite officiel — configuration zéro, classes utilitaires, et un thème sombre custom avec des couleurs distinctes par sport (vert pour le babyfoot, bleu pour le ping-pong solo, violet pour le ping-pong duo).
  • Données : fichiers JSON statiques dans /public/data/ — pas de base de données, pas d'ORM, juste du fetch(). Simple, portable, adapté à un hébergement statique.
  • Administration : plugin Vite sur mesure exposant des endpoints REST en dev uniquement, pour persister les scores dans les JSON sans quitter le navigateur.
  • Déploiement : GitHub Pages + GitHub Actions — pipeline CI/CD automatique déclenché à chaque git push, reconstruction et mise en ligne en moins d'une minute.

⚙️ Architecture & Défis Techniques

Contrainte principale : un site statique avec des données dynamiques

GitHub Pages ne fournit aucun backend — impossible d'exécuter du code serveur ou une base de données. L'enjeu était donc de proposer une expérience "live" sans infrastructure. La solution : toutes les données du tournoi sont stockées dans des fichiers JSON dans le dossier /public/data/. Le site les récupère à la volée via fetch() au chargement de chaque page.

Pour mettre à jour les scores pendant l'événement, j'ai développé un plugin Vite personnalisé (vite-admin-plugin.js) qui expose des endpoints REST uniquement en mode développement. Un panneau d'administration — inaccessible en production — permet de modifier les scores et de sauvegarder les fichiers JSON via fs.writeFileSync(). Un simple git push déclenche ensuite le pipeline CI/CD et le site est mis à jour en quelques secondes.

// vite-admin-plugin.js — Ajout d'endpoints de sauvegarde uniquement en dev
server.middlewares.use('/api/save-babyfoot-pools', (req, res) => {
  let body = '';
  req.on('data', chunk => body += chunk);
  req.on('end', () => {
    fs.writeFileSync(poolsPath, body);
    res.end(JSON.stringify({ success: true }));
  });
});
Interface d'administration pour la saisie des scores en temps réel

Gestion du routing SPA sur GitHub Pages

GitHub Pages ne supporte pas le routing côté client nativement — toute URL autre que la racine renvoie une 404. J'ai résolu ce problème en injectant un script de redirection dans le fichier 404.html qui redirige les requêtes vers index.html avec les paramètres d'URL préservés, permettant à React Router de reprendre la main.

Formats de tournoi hétérogènes

Chaque sport avait ses propres règles : le babyfoot utilisait des poules qualificatives puis un bracket à partir des quarts de finale, le ping-pong solo et duo fonctionnaient en ligue ronde avant un bracket à partir des demi-finales. Le système de points différait également — le ping-pong solo comptabilisait les sets individuels en plus du résultat de match. Plutôt que de forcer une abstraction artificielle, j'ai opté pour des composants de bracket dédiés à chaque format, ce qui a simplifié le code et facilité les ajustements de dernière minute.

Gestion des imprévus en direct

Certaines équipes se sont déclarées forfait le jour J — un cas que je n'avais pas prévu visuellement. J'ai ajouté à la volée un champ forfait dans les données JSON pour signaler ces cas, et adapté les composants pour les afficher différemment. Ce genre d'improvisation est inhérent à un projet développé en parallèle d'un événement réel.


🚀 Résultats & Impact

  • Accessibilité : ~60 étudiants ont pu suivre les résultats en direct depuis leur téléphone, sans installation ni connexion requise.
  • Fiabilité : zéro crash ou interruption technique pendant les deux semaines de tournoi.
  • Déploiement : pipeline CI/CD opérationnel en moins de 24h après le premier commit, avec des mises à jour de scores publiées en moins d'une minute.
  • Remplacement complet d'un processus manuel (Excel + bloc-notes) par une interface web structurée et partageable.

💡 Ce que j'ai appris

Ce projet m'a confirmé que les contraintes d'infrastructure poussent à l'ingéniosité. Travailler exclusivement sur GitHub Pages m'a forcé à concevoir une architecture sans backend qui reste pourtant administrable — une contrainte que j'aurais peut-être contournée avec un VPS, et qui m'aurait probablement coûté plus de temps.

Sur le fond, c'est un projet que j'assume volontiers comme un prototype fonctionnel plutôt qu'un produit fini. Le code a été écrit vite, sans TypeScript ni tests, avec quelques raccourcis de dette technique. Il a rempli son rôle à 100 %, mais si c'était à refaire, je partirais sur une base plus solide : un schéma de données unifié entre les sports, des composants de bracket génériques paramétrables, et probablement une interface d'administration découplée du mode dev.

Il servira de référence et d'inspiration si le BDS souhaite reconduire l'expérience pour un prochain tournoi.

Extension envisagée : connexion au babyfoot connecté de l'école

Une idée reste en suspens : relier la plateforme directement au babyfoot connecté disponible à ESIGELEC Poitiers. Ce type de table est équipée de capteurs capables de détecter les buts en temps réel et d'exposer les données via une API ou une connexion réseau locale. Techniquement, l'intégration côté front serait relativement simple — remplacer la saisie manuelle des scores par une mise à jour automatique via WebSocket ou polling. La difficulté réelle est ailleurs : accès à l'interface de la table, documentation du protocole propriétaire, gestion du réseau local de l'école, et potentiellement une couche backend pour faire le pont entre la table et le site. C'est faisable, mais le ratio effort/bénéfice ne se justifie que dans le cadre d'un projet plus ambitieux et pérenne — pas d'un site monté en quelques jours.