Dans cet article
Construire invade.lol : une plateforme de statistiques League of Legends
Si vous jouez à League of Legends, vous connaissez sûrement le réflexe : quelqu'un rejoint votre lobby, vous ouvrez op.gg ou u.gg et vous regardez son rang, ses champions les plus joués et son taux de victoire.
invade.lol est ma version de cet outil. Je voulais pouvoir chercher un invocateur, consulter son profil, son historique de matchs et ses statistiques sans me perdre dans l'interface. Le projet est open source. Voici pourquoi je l'ai construit et comment j'ai choisi sa stack.
Pourquoi créer un autre site de statistiques ?
Il y avait trois raisons.
D'abord, l'esport. J'ai envie de travailler à la rencontre du développement web et du jeu compétitif. League of Legends possède une scène immense et une API officielle Riot Games qui expose les classements, l'historique et les chronologies détaillées des matchs. C'est un terrain idéal pour explorer des données que je connais en tant que joueur.
Ensuite, je voulais mon propre outil. Les sites existants sont puissants, mais leurs publicités, leurs fenêtres superposées et leurs nombreuses fonctionnalités rendent parfois la réponse difficile à trouver. Mon point de départ était plus simple : une recherche, un profil, les chiffres qui comptent. Construire l'outil moi-même me permet de décider ce qui est vraiment essentiel.
Enfin, je voulais apprendre. J'avais envie d'un vrai projet pour approfondir AdonisJS et ClickHouse, plutôt que de multiplier les prototypes jetables. Un produit que l'on utilise est un meilleur professeur qu'une démonstration isolée : les choix de stockage, de synchronisation et de déploiement finissent par avoir des conséquences concrètes.
Les choix techniques
AdonisJS v6 : un cadre complet en TypeScript
J'ai beaucoup travaillé avec Laravel et j'apprécie son approche : des conventions, un ORM, de la validation, des files d'attente et une CLI dans un même framework. AdonisJS v6 me donne une expérience proche dans l'écosystème TypeScript. Je garde un monolithe MVC cohérent, avec des types qui traversent les différentes couches de l'application.
Inertia et Vue : une seule application à déployer
Pour l'interface, j'ai choisi Inertia avec Vue 3, plutôt qu'une SPA séparée qui consommerait une API. Le serveur gère le routage et transmet directement les propriétés aux pages Vue. Je n'ai donc pas à maintenir deux définitions des routes, un client HTTP spécifique pour chaque écran et une couche supplémentaire de synchronisation d'état.
Pour un projet que je développe seul, ce choix réduit la surface de maintenance. L'interface reste réactive côté client, mais l'ensemble se déploie comme une seule application.
PostgreSQL et ClickHouse : deux charges de travail différentes
Cette séparation est le choix d'architecture le plus intéressant d'invade.lol.
- PostgreSQL conserve les données relationnelles : profils d'invocateurs, comptes et état de synchronisation. C'est le bon endroit pour les relations et les opérations transactionnelles.
- ClickHouse conserve les données de matchs destinées aux analyses. Les regroupements sur de nombreuses lignes, par exemple le taux de victoire par champion sur les 500 derniers matchs, relèvent d'une charge analytique.
Je ne voulais pas faire porter ces deux usages au même schéma. PostgreSQL garde des données relationnelles normalisées, tandis que ClickHouse peut organiser des données analytiques dénormalisées pour les requêtes qui les parcourent.
Redis et Cloudflare R2
Redis met en cache les réponses analytiques coûteuses. Les appels à l'API Riot sont limités et les calculs ne sont pas gratuits ; un profil consulté plusieurs fois ne devrait pas relancer systématiquement les mêmes requêtes. La plupart des vues peuvent ainsi éviter de solliciter ClickHouse à chaque chargement.
Les fichiers vont dans un stockage d'objets compatible S3 : MinIO en local et Cloudflare R2 en production. Cette séparation me permet de conserver la même logique applicative d'un environnement à l'autre.
Un environnement local reproductible
Docker Compose lance PostgreSQL, ClickHouse, Redis et MinIO. Un Makefile rassemble les opérations courantes. make dev installe les dépendances, démarre les services, exécute les migrations et lance l'application. Je voulais pouvoir repartir d'un clone du dépôt sans reconstruire toute la stack à la main.
Pourquoi le code est public
Le dépôt est disponible sur github.com/invadelol/core, sous licence Polyform Noncommercial. On peut lire le code, apprendre du projet et l'utiliser dans un cadre personnel, mais cette licence n'autorise pas sa commercialisation.
J'ai choisi de publier l'ensemble parce qu'une architecture associant PostgreSQL, ClickHouse et Redis derrière une application AdonisJS est plus instructive quand on peut voir le produit complet, ses modèles et ses flux de données.
Et maintenant ?
La recherche, la synchronisation des profils, l'historique des matchs et les analyses des champions et coéquipiers sont en ligne sur invade.lol. La suite consiste surtout à approfondir l'analyse : plus d'agrégations, de meilleures visualisations et des informations plus utiles tirées des chronologies de matchs.
Si vous essayez le site, cherchez votre propre profil. Et si vous parcourez le code, vos retours sur l'architecture m'intéressent.
Aller plus loin avec un replay
J'ai également construit Ward, un outil d'extraction ROFL et d'analyse de replays. Dans cet autre article, je détaille la vision par ordinateur, la calibration des positions, l'inférence différée et les benchmarks enregistrés sur des replays.
