Terungal est une plateforme de commande de plats sénégalais — thiéboudienne, yassa, maafé… — préparés à la commande et livrés. C'est un projet personnel que je mène avec l'ambition d'en faire un produit professionnel : partie d'une boutique unique, la plateforme est devenue une place de marché multi-restaurants, prête à accueillir des restaurateurs et à facturer un abonnement.
Cette page retrace le projet en trois temps : sa conception (le découpage du domaine et l'architecture microservices), son développement (la structure du code, la sécurité, la qualité et la livraison) puis sa présentation, application par application.

18 microservices Spring Boot (Java 21), chacun avec sa base PostgreSQL
4 BFF et 3 applications Angular 22 — boutique, back office, console — plus une application mobile Flutter en préparation
Environ 590 tests unitaires et d'intégration, 80 décisions d'architecture consignées dans des ADR
Conçu et développé avec Claude Code comme agent de développement
Conception
Point de départ : un monolithe à faire évoluer
Le projet est né d'une première application monolithique Spring Boot : un seul jar redéployé à chaque changement, un modèle de données partagé, un checkout en échec, six failles de sécurité identifiées et un seul test automatisé. Plutôt que de corriger à la marge, j'ai choisi de reconcevoir la plateforme pour qu'elle puisse grandir : plusieurs restaurants, des abonnements, une console d'administration et, à terme, une application mobile.
Découper le domaine (Domain-Driven Design)
La première étape a été un inventaire complet du monolithe, puis un découpage en contextes délimités (bounded contexts). Chaque contexte devient un service autonome qui possède ses données. Ils sont classés selon leur valeur : le cœur de métier reçoit le plus de soin, les contextes génériques reposent sur des solutions éprouvées.
La plateforme est multi-tenant : le locataire est l'organisation, le périmètre le restaurant. Chaque donnée et chaque événement des contextes métier portent l'identifiant de l'organisation et du restaurant.
Architecture cible
Les applications ne parlent qu'à leur BFF (Backend for Frontend), seul point d'entrée exposé derrière Caddy. Les services sont privés, ne partagent aucune base et collaborent par événements Kafka.
Une base par service : aucune jointure entre services, migrations Flyway versionnées.
Pas d'appel direct entre services : la collaboration passe uniquement par des événements.
BFF par application : chaque front-end a une API taillée pour ses écrans et ne voit jamais les jetons.
Des événements fiables : outbox et idempotence
Un événement ne doit jamais être perdu ni appliqué deux fois. Chaque service écrit l'agrégat et le message dans la même transaction (transactional outbox) ; un relais publie ensuite dans l'ordre. Côté consommateur, chaque message déjà traité est ignoré.
La commande : une saga
Le checkout, en échec dans le monolithe, a été reconstruit comme une saga orchestrée par le service des commandes : paiement, réservation du stock et vidage du panier s'enchaînent par événements, avec des compensations (annulation, remboursement) en cas d'échec.
Migrer sans tout arrêter
La migration suit le motif strangler : le BFF route chaque route soit vers le monolithe, soit vers le service déjà migré, et les données du monolithe sont répliquées vers les services (Debezium et Kafka). Les contextes ont été extraits par vagues, du moins risqué au plus central.
Chaque choix structurant — données par service, messagerie, saga, sécurité, multi-tenancy, déploiement — est consigné dans un ADR (Architecture Decision Record) : 80 décisions documentées à ce jour.
Développement
Un service, trois modules : architecture hexagonale
Chaque microservice suit la même structure, inspirée de l'architecture hexagonale et de la Clean Architecture : trois modules Maven domain, application et infrastructure. Les dépendances pointent toujours vers le domaine, écrit en Java pur, sans framework.
Règles vérifiées automatiquement (ArchUnit) : un contrôleur n'appelle que des ports d'entrée, le domaine ne dépend de rien.
Conventions communes : nommage, erreurs REST au format RFC 9457, clé d'idempotence sur les créations sensibles.
Modules partagés pour la messagerie (contrats d'événements versionnés, outbox, consommateurs idempotents).
Sécurité
L'identité est centralisée dans identity-service (OAuth2 / OIDC). Les jetons ne quittent jamais les BFF : le navigateur ne reçoit qu'un cookie de session, et chaque service revérifie le JWT et les droits sur la ressource demandée.
Contrôle d'accès par rôles et par périmètre (organisation, restaurant).
Journal d'audit chaîné : chaque action sensible est scellée avec l'empreinte de la précédente.
Documents légaux versionnés : la version acceptée est enregistrée avec chaque commande.
Front-ends
Trois applications Angular 22 partagent une bibliothèque commune : la boutique des clients, le back office des restaurants et la console de la plateforme. L'état est géré avec les signals (NgRx Signals) et l'interface avec Tailwind CSS 4. Une application mobile Flutter, avec son propre BFF, est en préparation.
Qualité, livraison et exploitation
Tests : environ 590 tests unitaires et d'intégration (Testcontainers) et 76 tests de caractérisation du monolithe.
Livraison : une image Docker et un pipeline par application ; chaque service se déploie indépendamment.
Environnements : démarrage léger (infrastructure dans Docker) ou complet, par profils Docker Compose.
Observabilité : traces de bout en bout (OpenTelemetry), journaux JSON corrélés, métriques métier et alertes dans Grafana.
Développé avec Claude Code
Terungal a été conçu et développé avec Claude Code comme agent de développement, de l'inventaire du monolithe jusqu'aux applications Angular. Chaque étape de la migration est guidée par un prompt versionné dans le dépôt, les conventions sont fixées dans des fichiers CLAUDE.md et chaque choix structurant fait l'objet d'un ADR. Le code produit est relu, testé et validé avant intégration.
Présentation
La boutique
La boutique accompagne le client du choix du plat jusqu'à la commande, et s'adapte à lui une fois connecté.








Le back office des restaurants
Chaque restaurant pilote son activité depuis son back office : service du jour, catalogue, offres, horaires et vitrine de sa boutique.






La console de la plateforme
La console, réservée aux administrateurs, pilote la place de marché dans son ensemble : activité, onboarding des restaurateurs, modèle économique, conformité et traçabilité.





Bilan et perspectives
Du monolithe à la plateforme : une application déployable devenue 18 services, 4 BFF et 3 front-ends, chacun livré indépendamment.
Commande fiabilisée : le checkout passe par une saga commande, paiement et stock.
Sécurité : les six failles du monolithe sont corrigées et vérifiées.
Nouvelles capacités : multi-restaurants, abonnements, offres, console de la plateforme.
Prochaines étapes vers un produit professionnel : la mise en production et l'arrêt du monolithe, le suivi des livraisons en temps réel et l'application mobile cliente.
