Aller au contenu principal
Paris / --:--:--

Hey , Je m'appelle Clément.

Stage ingénieur informatique · mai 2027 Recrutez-moi
Retour

ALM Vote Manager

Application de vote MVP pour matchs de basket

TypeScript Next.js MySQL Drizzle Lucia

ALM est le club de basket de ma ville natale, Évreux. Entre deux quart-temps, les spectateurs sortent leur téléphone et votent pour le MVP. Le club récoltait les votes à main levée ou sur papier, une méthode lente, difficile à décompter, et peu engageante. Cette application a remplacé ça.

Déroulement d’un soir de match

La page d’accueil affiche un QR code en mode paysage, conçu pour être projeté sur un écran en salle. Les spectateurs le scannent, arrivent sur un formulaire d’inscription (nom, email, téléphone, CGU), puis sont redirigés vers la page de vote. Du scan au premier vote, le flux prend moins d’une minute.

L’interface de vote affiche la liste des joueurs (les blessés sont filtrés) avec un simple tap pour voter. Chaque spectateur a droit à un vote par match, appliqué par un cookie HttpOnly scopé à l’ID du match. Une fois que l’admin ferme le vote, l’écran de résultat affiche le podium avec le MVP mis en avant.

Architecture

L’application est un projet Next.js full-stack avec l’App Router. Le backend repose sur une base MySQL accédée via Drizzle ORM. Le schéma est simple : players, matches, votes et viewer (inscriptions spectateurs). Les votes sont des lignes immuables : chaque vote est un insert, et les tallies sont calculés à la lecture avec COUNT GROUP BY player_id. Cela maintient une faible latence d’écriture et évite toute contention de verrous lors des pics de vote.

Double authentification. Les admins s’authentifient via Lucia, une bibliothèque d’auth par session, avec des mots de passe hashés en Argon2 (memory-hard, résistant aux GPUs). Les spectateurs reçoivent un JWT stateless signé en HS256, valide 5 heures, suffisant pour couvrir un match complet et la cérémonie d’après-match. Les deux flux sont complètement isolés : un token spectateur ne peut accéder à aucune route admin.

Mises à jour des votes. Le dashboard admin récupère les décomptes à la demande plutôt que de maintenir une connexion persistante. Pour un événement où l’admin ferme manuellement le vote au bon moment, c’est le bon compromis : aucune infrastructure WebSocket à gérer, aucune logique de reconnexion, aucun problème de scaling. Juste un bouton et une requête HTTP.

Dashboard admin

Quatre sections : gestion des matchs (créer, modifier, supprimer), gestion des joueurs (ajouter des joueurs avec photo, marquer comme blessé), vue de vote en direct (affichage podium avec refresh manuel), et analytics (inscriptions spectateurs déchiffrées).

Ouvrir un match au vote bascule isOpen à true sur l’enregistrement du match, que le côté spectateur vérifie avant d’accepter un vote. Fermer le vote inscrit directement le nom du MVP et le nombre de votes sur la ligne du match, une dénormalisation délibérée pour des lectures historiques rapides.

Protection des données

Les clubs français opèrent sous RGPD. Les données spectateurs (nom, email, téléphone) sont chiffrées au repos en AES-256-CBC avant stockage. L’application est hébergée sur CleverCloud, un PaaS français, ce qui maintient toutes les données dans la juridiction européenne plutôt que de les router vers une infrastructure américaine.

Pourquoi ces choix

Polling plutôt que WebSockets. Un événement sportif live, c’est un admin et quelques centaines de spectateurs qui votent sur 5 à 10 minutes. Pas besoin de propagation en sous-seconde. Un bouton qui récupère les décomptes est plus simple à construire, plus simple à déboguer, et a zéro overhead infrastructure. Les WebSockets auraient été du sur-ingénierie.

Lucia pour les admins, JWT pour les spectateurs. Les sessions admin sont stockées côté serveur (Lucia + MySQL), ce qui permet une révocation immédiate si nécessaire. Les sessions spectateurs n’ont pas besoin de révocation : un JWT de 5 heures qui expire naturellement suffit. Utiliser le même système d’auth pour les deux aurait ajouté une complexité inutile au flux spectateur, qui doit être sans friction.

CleverCloud plutôt que Vercel. Vercel route les données par défaut via une infrastructure américaine. Pour un projet collectant des données personnelles de citoyens français sous RGPD, maintenir tout en France n’était pas optionnel, c’était le minimum.

Contact

Parlons-en.

Pas de formulaires, pas d’agenda, envoyez-moi un email avec ce que vous avez en tête. Je lis tout.

contact@clementomnes.dev