Opi!
Site d'entraînement au finnois : il présente le contenu nouveau, interroge par des exercices tapés au clavier, planifiés par répétition espacée, et corrige en montrant la forme attendue et la règle. Il tourne sur un cluster Kubernetes monté dans mon homelab, mis à jour automatiquement à chaque merge.
- Année
- 2026
- Technologies
- Python
- Flask
- Kubernetes
- k3s
- Terraform
- Proxmox

01 · Contexte
Le défi
Projet personnel né d'une petite application Flask de conjugaison, devenu une vraie plateforme pensée comme en production. Opi! fait trois choses : il présente le contenu nouveau (verbes, mots, expressions) sur une fiche de découverte, il interroge par des exercices tapés au clavier dont le rythme est planifié par répétition espacée (FSRS), et il corrige en montrant la forme attendue, les lettres qui diffèrent et la règle. Chaque session mélange les révisions dues, les exercices que débloquent les compétences de grammaire et les nouveautés du jour, et la Bibliothèque permet de parcourir tout le contenu. Ce contenu est la contrainte centrale : il vit dans des fichiers YAML relus à la main, seul ce que j'ai validé arrive dans les exercices, et le code n'invente aucune forme finnoise. Usage personnel, non public, déployé comme en production.
02 · Architecture
Comment c'est construit
Les points clés
- Contenu finnois versionné dans Git et validé à la main : le code n'invente aucune forme
- Quatre services (front React, api, lexicon, srs) qui ne communiquent qu'en HTTP JSON : aucun ne lit la base d'un autre
- Révisions planifiées par la bibliothèque FSRS (répétition espacée), sans réimplémenter l'algorithme
- Infrastructure décrite en code (Terraform) : trois machines virtuelles et un cluster k3s recréables à l'identique
- Livraison automatique : un merge sur main reconstruit les images, les range dans un registre privé Harbor, et Argo CD met le cluster à jour
- Site accessible seulement depuis le réseau privé (Tailscale), avec sauvegarde de la progression chaque soir, restaurée et testée
03 · En images
Galerie

Une session en cours : le tableau du présent d'un verbe, à remplir forme par forme 
La Bibliothèque, filtrée par tag : les couleurs, chacune avec sa pastille 
Les compétences de grammaire, que l'on débloque une à une (état de démonstration) 
Comment une session se compose : révisions dues, exercices débloqués, notions, puis nouveautés 
D'un élément à ses cartes, et les compétences que chaque carte exige 
Le circuit du contenu : de la proposition en brouillon à la validation à la main, puis à la révision 
L'architecture en détail : les ports, les règles qui tiennent l'ensemble et les flux entre les services 
Connexion et sécurité : deux couches, un cookie de session et des contrôles à chaque requête 
Une carte de bout en bout : la question, la réponse corrigée, la note enregistrée 
Ce que renvoie l'API à chaque étape de session, et l'écran du front qui s'en charge 
La vie d'une carte dans FSRS : apprentissage, révision et réapprentissage 
La première version, en local sous docker compose, et ce que change chaque pull request de la v1 
De la fusion sur main au cluster : images reconstruites, poussées sur Harbor, puis synchronisation d'Argo CD par vagues 
Le registre d'images Harbor sur le NAS, joint par deux chemins : le tailnet pour la CI, le réseau local pour les nœuds 
Comment la CI entre dans le tailnet sans secret : un jeton OIDC de GitHub vérifié par Tailscale 
La sauvegarde nocturne de la base srs sur le NAS, et les deux façons de la contrôler ou de la restaurer 
La supervision : Prometheus lit les services, deux règles surveillent la sauvegarde, l'interface reste sur le tailnet
Cliquer sur une image l'ouvre en plein écran, avec navigation entre les captures.
04 · Bilan
Ce que j'en retire
Décrire une infrastructure en code (Terraform) : les machines se recréent à l'identique, et Argo CD remet le cluster dans l'état décrit dans Git. Un merge suffit à déployer.