Mirukai - Moteur de Recommandation d'Animés

Lien vers le projet Dossier de production

Contexte

Mirukai est un projet personnel né de ma passion pour les animés et de ma volonté de maîtriser l'écosystème JavaScript moderne. Le nom vient du japonais : Miru (見る, regarder) et Kai (界, monde) "Trouve le prochain animé que tu vas aimer."

Développé seul, de la conception à la mise en production, Mirukai est une application web full-stack en production accessible publiquement sur mirukai.rlbrt.fr. Le défi central : recommander intelligemment un animé adapté à chaque utilisateur en combinant son historique AniList, un modèle vectoriel de goûts et un LLM pour des explications personnalisées.

Ce projet illustre ce que le cursus académique n'enseigne pas directement : l'autonomie technique complète, depuis le choix de la stack jusqu'aux décisions d'architecture en production, sans encadrement ni contrainte pédagogique.

Gif project Mirukai

Déroulement du projet

Moteur de recommandation

Le cœur de Mirukai est un algorithme de recommandation vectoriel construit sur un catalogue PostgreSQL de ~3500 animés synchronisé quotidiennement depuis l'API AniList.

  • Taste vector À partir de la liste de l'utilisateur, construction d'un vecteur de préférences pondéré par genres, tags et studios, avec une pondération IDF (Inverse Document Frequency) calculée sur tout le catalogue pour valoriser les goûts spécifiques au détriment des genres communs
  • Scoring multi-critères Chaque animé candidat reçoit un score composé : similarité genre (×0.30), tags (×0.40), studios (×0.10), qualité communautaire AniList (×0.15), popularité (×0.05), avec pénalité sur les genres détestés
  • Simulations pondérées runSimulations(5, pool=30) : 5 tirages probabilistes dans le top-30 candidats, le gagnant étant celui avec le meilleur score communautaire AniList pour éviter la répétition du même animé #1 tout en garantissant la qualité
  • Filtre prequel TV Seuls les animés sans préquel TV sont recommandés, garantissant toujours le point d'entrée d'une franchise
  • Profil utilisateur adaptatif Seuils personnalisés (excellent / bien / moyen) calculés par moyenne ± écart-type sur les notes de l'utilisateur, reflétant son échelle personnelle de notation

Authentification & Données

  • OAuth2 AniList avec 3 applications distinctes (production, développement, local) et compte email/password natif Mirukai
  • Sessions chiffrées via iron-session (cookies httpOnly), mots de passe hachés avec scrypt natif Node.js (timing-safe)
  • Catalogue PostgreSQL de ~3500 animés avec synchronisation quotidienne automatique depuis AniList GraphQL
  • Données streaming JustWatch GraphQL : plateformes disponibles en France, nombre de saisons, sync lazy par animé ou bulk admin
  • Cache Redis : listes utilisateurs (TTL 1h), suggestions journalières, rate limiting (200 req/h par utilisateur)

LLM & Intelligence artificielle

  • Gemini 2.0 Flash (primaire) Traduction des synopsis en français et génération d'explications personnalisées basées sur les références de goût de l'utilisateur
  • Groq llama-3.1-8b (fallback) Bascule automatique si Gemini est indisponible, sans interruption du service
  • pickDiverseReferences() Sélection intelligente de 2-4 animés de la liste utilisateur maximisant la diversité de genres pour alimenter le LLM avec des références équilibrées
  • Appels LLM parallèles (traduction + explication), section explication masquée côté UI si le LLM retourne null

Infrastructure & DevOps

  • Stack Docker Compose : Next.js 16 + PostgreSQL 16 + Redis 7, hébergée sur un conteneur LXC Proxmox auto-géré
  • Reverse proxy Nginx avec SSL Let's Encrypt (Certbot), routage vers deux environnements distincts (prod port 8080, dev port 8081)
  • CI/CD GitHub Actions : build image Docker → push GHCR → déploiement SSH automatisé sans downtime (docker compose up --no-deps)
  • Environnements production (mirukai.rlbrt.fr) et staging (dev.mirukai.rlbrt.fr) gérés depuis les branches git main et dev

Défis Techniques

  • Algorithme de recommandation vectoriel : construction du taste vector avec IDF dynamique sur ~3500 animés, système de simulations pondérées pour garantir variété et qualité simultanément éviter le candidat #1 fixe sans dégrader la pertinence
  • Gestion du cold-start : deux logiques distinctes (scoring vectoriel ≥10 animés / top populaires pondérés <10 animés) transparentes pour l'utilisateur, avec retour coldStart: true dans la réponse API pour adapter l'UI
  • Intégration JustWatch GraphQL (API non officielle, non documentée) : identification du matching par technicalName, TTL 15 jours, rate limiting 600ms entre requêtes, fallback sur les liens externes AniList si données absentes
  • Résilience LLM avec double provider : appels parallèles traduction + explication, bascule automatique Gemini → Groq, gestion des cas null avec masquage côté UI plutôt que message d'erreur
  • Infrastructure multi-environnement auto-hébergée : deux stacks Docker indépendantes sur un seul CT Proxmox, déploiement continu sans interruption, gestion des secrets par fichiers .env séparés par environnement
  • Cache multi-niveaux : Redis pour les listes utilisateurs (évite les appels AniList répétés), rate limiting distribué par user, suggestions journalières idempotentes (même résultat si redemandé dans la journée)

Compétences Acquises

  • Next.js 16 App Router et TypeScript : architecture full-stack moderne, API Routes REST, composants React avec Tailwind CSS v4, gestion d'état serveur et client
  • Algorithmes de recommandation : modèle vectoriel pondéré, IDF, simulations probabilistes Monte Carlo, gestion du cold-start capacité à traduire un besoin métier en modèle mathématique implémentable
  • Intégrations API avancées : GraphQL (AniList, JustWatch), REST LLM (Gemini, Groq), OAuth2 PKCE gestion de la résilience, des fallbacks et des limites de débit
  • DevOps complet : Docker Compose, CI/CD GitHub Actions + GHCR, déploiement SSH automatisé, Nginx reverse proxy, SSL Let's Encrypt, administration Proxmox LXC
  • Gestion des données à l'échelle : PostgreSQL avec requêtes optimisées sur catalogue large, stratégie de cache Redis multi-usage, synchronisation asynchrone et lazy loading
  • Autonomie technique end-to-end : conception, développement, mise en production et maintenance d'un projet complet sans supervision, avec prise de décisions d'architecture sous contraintes réelles

Conclusion

Mirukai représente ma capacité à mener un projet de bout en bout, hors cadre académique : choix de la stack, conception de l'algorithme, intégration d'APIs tierces, déploiement et maintenance d'une application en production réelle. Chaque décision technique du modèle vectoriel au choix de Redis comme cache distribué a été prise et assumée seul.

Il illustre ce que le cursus n'enseigne pas directement : résoudre des problèmes concrets (cold-start, latence LLM, API non documentée) avec les contraintes d'un service en production. Ce projet personnel, accessible publiquement, est la preuve de mon engagement au-delà des projets académiques et de ma passion durable pour le développement web.

← Projet Précédent Projet Suivant →
Back to top