Plateforme de réseau social orientée milieu étudiant. Le backend est découpé en cinq microservices Spring Boot derrière un gateway, les données vivent dans des PostgreSQL isolés par service, et le frontend est une SPA React + Vite.
Le projet est conçu pour tourner en local via Docker Compose. Des pistes de déploiement existent aussi (Ansible pour un serveur Linux, Vagrant pour reproduire un serveur sur sa machine, Kubernetes via Minikube), mais elles ne sont pas nécessaires pour développer.
Chaque microservice a un périmètre métier net, sa propre base, et ne connaît les autres que par leur URL injectée dans les variables d'environnement. Les classes sont volontairement package-private quand elles n'ont pas à être exposées : le but est de garder le couplage minimal.
user-service(port 8081) : authentification, profils, abonnements/followers, blocages entre utilisateurs, et catalogue des centres d'intérêt (Activity). C'est ce service qui signe les JWT au login et au register.circle-service(8082) : les cercles de discussion, les membres avec leurs rôles et statuts (adhesion_status,member_role,is_muted,is_banned), et la liste des cercles bloqués par un utilisateur.content-service(8083) : le feed. Gère lesPostetEvent(qui héritent d'unContentpolymorphique), les commentaires, les likes, les médias, la géolocalisation des événements et la participation.message-service(8084) : messagerie 1-à-1 avec WebSocket. Les messages portent leurs propres états (is_read,is_edited,response_to).admin-service(8085) : modération transverse. Reçoit les signalements (Report, qui peuvent cibler un user, un cercle ou un contenu) et orchestre les notifications globales.gateway-service(8080) : seule porte d'entrée publique. Route vers le bon service selon le path, valide le JWT au bord, propage l'identité de l'appelant via des headersX-User-*et applique la configuration CORS.
Le frontend (frontend/, port 5173 en dev) consomme uniquement le gateway via Axios. Il utilise Zustand pour l'état d'auth, react-router pour la navigation, et TailwindCSS pour le style.
Côté backend : Java 21, Spring Boot 4.0, Spring MVC pour les microservices métier, Spring Cloud Gateway en pile réactive (WebFlux) pour le gateway, JPA + Hibernate + HikariCP pour la persistance, jjwt pour les tokens. PostgreSQL 16 pour chaque base. Le build est multi-module avec un pom.xml parent qui fixe les versions.
Côté frontend : React 18 avec Vite comme bundler/dev server, Zustand pour le store global, Axios pour les appels HTTP avec un interceptor qui injecte le token, TailwindCSS pour les classes utilitaires.
Côté infra : Dockerfiles multi-stage par service (Maven build dans une image temurin-21, runtime dans une jre-alpine plus légère), docker-compose.yml qui orchestre tout en local, manifestes Kubernetes dans k8s/, playbook Ansible dans ansible/, Vagrantfile pour monter une VM Ubuntu identique à la cible serveur.
Le détail des commandes est dans HOW_TO_RUN.md. Le mode standard tient en une seule commande à la racine de backend-campus/ : docker compose up -d --build. Ça construit et lance tous les services y compris le frontend (Vite build puis nginx). L'app est ensuite disponible sur http://localhost:5173, le gateway sur http://localhost:8080.
Pour itérer sur le frontend avec hot reload, tu peux stopper le container (docker compose stop frontend) et lancer npm run dev dans frontend/. Sinon, après une modif, docker compose up -d --build frontend rebuild juste ce service.
Un fichier .env à la racine de backend-campus/ fournit le mot de passe Postgres, le secret JWT et la clé d'authentification interne service-à-service. Un .env.example montre la forme attendue. Le .env ne doit jamais être committé.
backend-campus/
pom.xml parent Maven (versions des deps)
docker-compose.yml orchestration locale
Vagrantfile VM Ubuntu pour reproduire un serveur
.env / .env.example secrets locaux
user-service/ code + Dockerfile par service
circle-service/
content-service/
message-service/
admin-service/
gateway-service/
frontend/ SPA React + Vite
k8s/ manifestes Kubernetes
ansible/ playbook + inventory + group_vars
.github/ workflows CI
Le gateway lit les URIs des services en aval via USER_SERVICE_URI, CIRCLE_SERVICE_URI, etc. Ces variables sont déjà câblées dans docker-compose.yml pour que les services se trouvent par leur nom sur le réseau Docker (http://user-service:8081...). En dev hors Docker, les valeurs par défaut pointent vers localhost:8081, 8082, etc.
Le JWT est signé par user-service et validé par gateway-service avec le même JWT_SECRET. La durée par défaut est 24 h (JWT_EXPIRATION_MS=86400000).
Les communications service-à-service (ex. user-service qui publie une notification dans admin-service) sont protégées par une clé partagée transmise en header X-Service-Key, configurée via NOTIFICATIONS_API_KEY.
La CORS du gateway autorise par défaut http://localhost:5173. Pour ajouter un autre origin, passer CORS_ALLOWED_ORIGINS (liste séparée par virgules) au container du gateway, lue par la propriété cors.allowed-origins.
Postgres initialise le mot de passe d'un volume une seule fois, au tout premier démarrage (initdb). Si POSTGRES_PASSWORD est modifié dans .env après coup, les volumes existants gardent l'ancien mot de passe et le service ne pourra plus s'y connecter. Le fix est de supprimer le volume concerné (docker compose down, puis docker volume rm backend-campus_<service>-postgres-data) avant de redémarrer.
spring.jpa.hibernate.ddl-auto=update est utilisé en dev : Hibernate ajuste les tables au démarrage à partir des entités. Pratique pour itérer, mais à ne pas garder tel quel en prod.
Le gateway ignore l'authentification sur /api/v1/auth/** (login et register publics) et sur les requêtes OPTIONS (preflight CORS). Tout le reste exige un Authorization: Bearer <token>.
GitHub Actions builds chaque service via Maven, exécute les tests, publie les rapports JUnit (rétention 7 jours). Le pipeline est dans .github/.
Pour déployer sur un serveur Linux : le playbook ansible/playbook.yml installe Docker, copie le projet, monte les variables depuis ansible/group_vars/campus_nodes/ et lance la stack Compose. Adapter l'IP cible dans ansible/inventory.ini.
Pour valider le playbook sans serveur distant, vagrant up provisionne une VM Ubuntu 22.04 et exécute le même playbook à l'intérieur.
Pour Kubernetes en local : minikube start puis minikube image build pour chaque service, puis kubectl apply -f k8s/.