Retour aux projets
PubliéAcadémique

ESIGELEATS

Une plateforme de partage de recettes avec modération, notations et dashboard d'administration.

Publié novembre 20258 min de lecture

🎯 Le Contexte & L'Objectif

ESIGELEATS est né d'un projet de développement web en semestre 7 à l'ESIGELEC, avec un cas d'usage concret : fournir à l'association cuisine de l'école une plateforme où les membres pourraient publier les recettes de leurs ateliers cuisine, et où les adhérents pourraient noter, commenter et mettre en favoris leurs recettes préférées. L'idée était de créer un équivalent de Marmiton à l'échelle de l'école — un espace communautaire centré sur le partage culinaire, avec une modération adaptée au contexte associatif.

Le cahier des charges imposait une application web dynamique avec authentification et opérations CRUD. Plutôt que de livrer le strict minimum, j'ai choisi de construire une application qui ressemble à un vrai produit : workflow de publication avec validation admin, notations en temps réel, système de favoris, commentaires, dashboard d'administration avec visualisations statistiques, et une pipeline CI/CD complète pour garantir la qualité du code à chaque commit. Le tout conteneurisé avec Docker pour un déploiement reproductible.


Aperçu de l'interface et de l'interactivité

🛠️ Ma Contribution & Mon Rôle

J'ai conçu et développé l'intégralité du projet seul, de la modélisation de la base de données jusqu'au déploiement conteneurisé.

  • Architecture & Backend : mise en place d'une architecture MVC propre avec Flask — controllers pour la logique métier, models pour les objets de données, routes pour les endpoints HTTP. Gestion des sessions serveur, authentification sécurisée, et middleware de contrôle d'accès pour les routes admin.
  • Base de données : conception du schéma relationnel SQLite (utilisateurs, recettes, ingrédients, étapes, commentaires, notations, favoris) avec requêtes paramétrées via SQLAlchemy pour prévenir les injections SQL.
  • Interface utilisateur : développement de l'ensemble des templates Jinja2 avec Tailwind CSS — pages de recettes, profils utilisateurs, formulaires, dashboard admin. Composants réutilisables via le système de macros Jinja pour limiter la duplication.
  • Interactions temps réel : API REST interne (notation 5 étoiles, ajout/retrait de favoris, soumission de commentaires, actions de modération) consommée en AJAX depuis le frontend pour offrir une expérience fluide sans rechargement de page.
  • Dashboard d'administration : tableau de bord avec indicateurs clés (KPI) et graphiques ApexCharts — distribution des statuts de recettes, tendances de publication, statistiques par auteur.
  • Qualité & CI/CD : mise en place d'une chaîne de qualité complète — Ruff et Pylint pour le Python, DjLint pour les templates Jinja, ESLint et Prettier pour le JavaScript. Pipeline GitHub Actions en trois étapes (lint, tests, build Docker) avec seuils de couverture minimum à 70 %.

💻 Stack Technique

  • Backend : Flask 3.1 — un micro-framework Python léger mais suffisamment structurant pour une application de cette taille. Flask-Session pour la gestion des sessions côté serveur, SQLAlchemy 2.0 comme couche d'abstraction pour les requêtes SQL.
  • Base de données : SQLite — un choix assumé pour un projet académique : zéro configuration, fichier unique, et largement suffisant pour le volume de données visé. Le schéma relationnel reste transposable vers PostgreSQL sans modification majeure.
  • Frontend : Jinja2 pour le rendu côté serveur, Tailwind CSS 3.4 pour le styling, et du JavaScript vanilla pour les interactions dynamiques (AJAX, dark mode, notifications). ApexCharts pour les visualisations du dashboard admin.
  • Qualité : cinq linters configurés (Ruff, Pylint, DjLint, ESLint, Prettier), Pytest avec Coverage.py, et des hooks pre-commit pour garantir la qualité avant chaque commit.
  • DevOps : Docker pour la conteneurisation, GitHub Actions pour l'intégration continue. Le pipeline valide le linting, exécute les tests avec contrôle de couverture, puis construit l'image Docker sur la branche principale.

⚙️ Architecture & Défis Techniques

Une architecture MVC sans framework lourd

Flask ne prescrit aucune organisation de code — c'est à la fois sa force et son piège. Pour éviter le fichier monolithique classique des projets Flask, j'ai structuré l'application en couches distinctes : les routes reçoivent les requêtes HTTP et délèguent aux controllers qui encapsulent la logique métier, les models définissent les objets de données, et un module sql.py centralise l'exécution des requêtes SQL. Cette séparation rend le code navigable et testable, chaque couche ayant une responsabilité claire.

Workflow de modération des recettes

Un simple CRUD ne suffit pas quand plusieurs utilisateurs publient du contenu. J'ai mis en place un système de modération à quatre états — En attente, Modifications requises, Approuvée, Rejetée — avec des transitions contrôlées exclusivement par les administrateurs via l'API REST. Côté utilisateur, des notifications visuelles (badges rouges dans la navbar, rafraîchis toutes les 30 secondes) signalent les recettes nécessitant une action. Ce workflow garantit qu'aucune recette n'apparaît publiquement sans validation préalable.

Création d'une recette et notifications

Interactions AJAX sans framework JavaScript

Plutôt que d'intégrer React ou Vue pour les interactions dynamiques, j'ai opté pour du JavaScript vanilla avec des appels fetch() vers l'API REST interne. Les notations par étoiles, les favoris (toggle au clic), les commentaires et les actions de modération admin sont tous gérés sans rechargement de page. Ce choix maintient la simplicité de la stack tout en offrant une expérience utilisateur réactive — les moyennes de notation et les compteurs se mettent à jour instantanément après chaque action.

Dashboard admin et actions de modération

Sécurité et validation

La sécurité a été traitée à plusieurs niveaux : requêtes SQL paramétrées via SQLAlchemy pour prévenir les injections, échappement automatique Jinja2 contre les failles XSS, renommage des fichiers uploadés en UUID pour empêcher les collisions et les attaques par traversée de chemin, et validation des entrées côté serveur avant toute écriture en base. Les sessions sont stockées côté serveur via Flask-Session, et les routes d'administration sont protégées par un décorateur de contrôle d'accès.

Pipeline CI/CD à trois étages

Le pipeline GitHub Actions est structuré en trois jobs séquentiels. Le premier vérifie le formatage et le linting (Ruff, Pylint avec un score minimum de 7.0/10, DjLint). Le second exécute les tests Pytest avec un seuil de couverture à 70 %. Le troisième construit l'image Docker pour valider que le conteneur se build correctement. Si l'une des étapes échoue, les suivantes ne s'exécutent pas — le feedback est immédiat.


🚀 Résultats & Impact

  • Application complète : un produit fonctionnel de bout en bout — de l'inscription utilisateur à la publication modérée d'une recette, en passant par les notations, les favoris et les commentaires.
  • Qualité de code industrielle : cinq linters, tests automatisés avec couverture minimum, pipeline CI/CD, hooks pre-commit — un niveau d'exigence qui dépasse largement le cadre d'un projet académique.
  • Interface soignée : dark mode, notifications non intrusives, sélecteur de portions dynamique (ajustement automatique des quantités d'ingrédients), pages d'erreur personnalisées — des détails qui font la différence en termes d'expérience utilisateur.
  • Déploiement reproductible : un docker build && docker run suffit pour lancer l'application sur n'importe quelle machine, sans configuration supplémentaire.
  • Note obtenue : 20/20 — le projet a été évalué sur la qualité du code, le respect du cahier des charges et les fonctionnalités apportées au-delà des exigences initiales.

💡 Ce que j'ai appris

Ce projet a été l'occasion de confronter Flask à une application de taille réelle, au-delà du simple prototype. Structurer une application Flask en couches MVC propres demande de la discipline — le framework ne guide pas, il faut tout décider soi-même. C'est formateur, mais cela m'a aussi fait comprendre pourquoi des frameworks plus opiniâtres comme Django existent : ils offrent cette structure par défaut.

La mise en place de la chaîne de qualité (linters, tests, CI/CD) a représenté un investissement initial conséquent, mais qui s'est rentabilisé rapidement. Attraper un problème de formatage ou un test cassé avant le push évite les régressions silencieuses et force une rigueur qui profite à l'ensemble du projet.

Si c'était à refaire, plusieurs améliorations s'imposeraient :

  • Migrer vers PostgreSQL : SQLite atteint ses limites en contexte multi-utilisateurs concurrent, et le passage à un SGBD plus robuste serait nécessaire pour un déploiement en production.
  • Ajouter une couche de cache : les requêtes de dashboard recalculent les statistiques à chaque chargement — un cache Redis ou même un simple cache en mémoire améliorerait sensiblement les performances.
  • Introduire un ORM complet : SQLAlchemy est utilisé ici principalement comme couche d'exécution SQL, mais son ORM déclaratif permettrait de simplifier les requêtes complexes et d'ajouter des migrations de schéma via Alembic.
  • Renforcer les tests : la couverture à 70 % est un plancher — les controllers et les routes d'API mériteraient une couverture plus exhaustive, notamment sur les cas limites de modération.