Dossier technique à destination des élus, directions des systèmes d'information, développeurs et décideurs publics souhaitant comprendre l'architecture, les garanties de souveraineté et les mécanismes de résilience d'UrbaFood.
UrbaFood n'est pas une simple application de commande en ligne. C'est une infrastructure logicielle pensée comme un service public : open source, auditée, hébergée localement, et gouvernée par la collectivité qui la déploie.
Stack full-stack NestJS (API REST) + Next.js (interface web) + PWA React (application mobile coursiers). Reverse proxy Nginx devant un HAProxy terminant le TLS. Déployable sur tout hébergeur conforme NIS2 ou en auto-hébergement municipal.
Interface web progressive (PWA) : catalogue de restaurants, panier, suivi de commande en temps réel, compte citoyen avec historique. Conforme RGAA accessibilité. Aucun traceur publicitaire tiers.
Espace dédié : gestion du menu, tableau de bord commandes en temps réel, statistiques de chiffre d'affaires, connexion optionnelle à Google Business Profile pour import automatique de la fiche établissement.
Application web installable sur Android/iOS sans passer par les stores. Service Worker Workbox pour fonctionnement partiel hors-ligne. Interface mobile-first : disponibilité, commandes disponibles, livraison active, gains en temps réel.
Interface d'administration pour la collectivité : validation des restaurants, gestion des coursiers, suivi des commandes, rapports financiers, open data configurable. Rôles et permissions granulaires (agent instructeur, élu, DSI, auditeur).
API REST documentée (OpenAPI/Swagger) : endpoints publics pour les données ouvertes et endpoints sécurisés (JWT) pour les acteurs de l'écosystème. Interopérabilité avec les SI municipaux (annuaire, identité numérique).
Intégration Stripe (PCI-DSS SAQ-A). Les fonds transitent directement vers les restaurants (Stripe Connect) après déduction du seul frais de maintenance (1 %). Alternative virement SEPA disponible sans dépendance à un prestataire unique.
Workflow de statuts : PENDING → CONFIRMED → PREPARING → READY → PICKED_UP → DELIVERED. File de traitement Redis pour les événements temps réel. Notifications SMS/push à chaque changement de statut.
Géolocalisation HTML5 native dans la PWA coursier, sans SDK propriétaire. Calcul des distances via l'API Nominatim OpenStreetMap — aucune dépendance à Google Maps. Attribution des commandes par proximité et disponibilité déclarée.
Notifications push via Web Push API (Service Worker) pour la PWA coursiers. Email via SMTP municipal configurable. Architecture de queue Bull/Redis pour la fiabilité des envois, sans dépendance à un prestataire d'emailing externe.
Déployable sur infrastructure municipale existante, datacenter régional certifié SecNumCloud, ou cloud souverain (OVHcloud, Scaleway, Outscale). Aucune dépendance obligatoire à AWS, Azure ou GCP. Build Docker reproductible.
Authentification JWT (access 15 min + refresh 7j). Mots de passe hashés Argon2. Chiffrement AES-256-GCM des tokens OAuth. Rate limiting Nginx + NestJS Throttler. Conforme RGPD : données hébergées en UE, droit à l'effacement implémenté.
Restaurants ──────────────────────────────────────┐
↓
┌─────────────────────────────┐
│ Plateforme privée │
│ (Silicon Valley) │
└────────────┬────────────────┘
│
┌────────────────────────────┼────────────────────┐
↓ ↓ ↓
Actionnaires Données citoyens Hébergement
(dividendes) hors territoire AWS / USA
Commission : 25–30 % par commande
Gouvernance : fonds d'investissement privés
Transparence : nulle — données non communiquées Restaurants ──┐
Livreurs ────┼──→ Infrastructure publique locale
Citoyens ────┘ │
│
┌────────────────────┼────────────────────┐
↓ ↓ ↓
Données sur Hébergement Gouvernance
le territoire souverain municipale
(propriété (datacenter (conseil
publique) local) municipal)
Commission : 1 % (maintenance uniquement)
Gouvernance : élus + DSI + citoyens
Transparence : comptes publics, code ouvert Internet (HTTPS:443)
↓
┌───────────────────────────────────────────────────────────┐
│ HAProxy (SSL termination, certificat Let's Encrypt) │
└─────────────────────────┬─────────────────────────────────┘
↓ (réseau interne chiffré)
┌───────────────────────────────────────────────────────────┐
│ Nginx (reverse proxy, rate limiting 100 req/min API) │
│ │
│ /api/* → Backend NestJS :3000 │
│ /coursier-app/* → PWA Coursiers :80 │
│ /* → Frontend Next.js :3001 │
└─────────────────────────┬─────────────────────────────────┘
↓
┌───────────────────────────────────────────────────────────┐
│ Backend NestJS (API REST, TypeORM, Bull queues) │
│ │
│ Auth JWT ── Restaurants ── Orders ── Couriers │
│ ↓ ↓ ↓ ↓ │
│ Redis (cache, sessions, queues) │
│ MariaDB 11.5 (données persistantes, UTF8MB4, InnoDB) │
│ ↓ │
│ Worker (queue emails + cron jobs) │
└───────────────────────────────────────────────────────────┘
Tous les containers : Docker Compose · réseau bridge isolé
Données : volumes persistants · backup automatisé (mariadb-dump)
Déployable sur : OVHcloud · Scaleway · Outscale · Baremetal municipalUne blockchain publique comme Ethereum est inadaptée aux collectivités : coûts de transaction variables et imprévisibles, gouvernance hors de portée démocratique, dépendance à des acteurs privés spéculatifs. UrbaFood propose une architecture décentralisée sous maîtrise publique, sans cryptomonnaie.
Chaque nœud (serveur municipal, terminal CCAS, équipement de commerce) communique directement avec ses voisins via un protocole léger. Pas de point central unique défaillant.
Mairie, CCAS, bibliothèque, office de commerce, marché couvert : chaque équipement public peut héberger un nœud. Plus le réseau est dense, plus la résilience est élevée.
Les applications des coursiers et restaurateurs fonctionnent comme des nœuds légers : ils valident et propagent les transactions sans stocker l'intégralité de l'historique.
Commandes, réputation et paiements répliqués sur plusieurs nœuds. Si un serveur tombe, les données restent accessibles via les réplicas locaux, sans interruption de service.
Registre distribué des transactions (commandes, paiements, livraisons). Immuable et auditable par les élus et le DSI. Aucune cryptomonnaie : les unités sont des euros, traçables via Stripe.
Proof of Authority : seuls les nœuds autorisés par la municipalité valident les blocs. Consommation énergétique proche de zéro. Débit élevé. Adapté aux contraintes des collectivités.
┌──────────────────────────┐
│ Nœud principal │
│ Mairie / DSI │
│ (validateur primaire) │
└──────────┬───────────────┘
│
┌──────────────────────┼──────────────────────┐
↓ ↓ ↓
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ Nœud CCAS │ │ Nœud Office │ │ Nœud Médiathèq │
│ (validateur) │ │ de commerce │ │ (validateur) │
└────────┬────────┘ └────────┬─────────┘ └───────┬─────────┘
│ │ │
┌─────┴─────┐ ┌─────┴─────┐ ┌─────┴─────┐
↓ ↓ ↓ ↓ ↓ ↓
App App App App App App
Citoyen Restaurant Citoyen Coursier Citoyen Restaurant
Légende :
─── Connexion P2P chiffrée (TLS mutuel)
↓ Nœud léger (lecture + propagation, sans stockage complet)
Les validateurs forment le comité de consensus (PoA municipal)
Frais de transaction : 0 EUR (réseau privé, aucun gas fee)
Cryptomonnaie : aucune — devise : euro via Stripe / SEPAEn déléguant la livraison alimentaire à des plateformes privées, les collectivités cèdent non seulement une part de la valeur économique locale, mais aussi la maîtrise de données stratégiques — habitudes de consommation, fréquentation des commerces, données personnelles des citoyens — sans garantie sur leur hébergement ni leur utilisation.
25 à 30 % de commission : un restaurant réalisant 500 000 € de CA annuel via plateforme transfère 125 000 à 150 000 € vers des actionnaires extérieurs. Sur dix restaurants, c'est 1 à 1,5 M€ qui quittent le territoire chaque année.
Les plateformes agrègent les données de consommation pour affiner leur modèle publicitaire, vendre des études de marché et orienter leurs propres offres (dark kitchens, marques fantômes). La collectivité n'a aucun accès à ces données produites par ses citoyens.
Une fois les restaurants intégrés et les habitudes citoyennes formées, la collectivité ne peut plus reprendre la main sans provoquer une rupture de service. C'est le mécanisme classique du lock-in par réseau : plus il est grand, plus la dépendance est forte.
| Critère | Plateforme centralisée | UrbaFood décentralisé |
|---|---|---|
| Propriété des données | ❌ Plateforme privée (hors territoire) | ✅ Collectivité territoriale |
| Hébergement | ❌ Cloud extraterritorial (AWS, GCP, Azure) | ✅ Infrastructure souveraine (FR / UE certifiée) |
| Commission | ❌ 25–30 % par commande | ✅ 1 % (maintenance uniquement) |
| Gouvernance | ❌ Conseil d'administration privé | ✅ Conseil municipal + délibération publique |
| Transparence financière | ❌ Données non communiquées | ✅ Comptes publics trimestriels, open data |
| Résilience | ❌ Point de défaillance unique | ✅ Réseau distribué multi-nœuds |
| Auditabilité | ❌ Code propriétaire, boîte noire | ✅ Code open source, auditable à tout moment |
| Interopérabilité | ❌ API fermée, écosystème verrouillé | ✅ OpenAPI 3.0, standards ouverts |
| Coût de sortie | ❌ Rupture de service totale | ✅ Migration progressive sans perte de données |
| Évolutivité | ❌ Dépendante des décisions de l'éditeur | ✅ Fork et personnalisation libres |
| Contrôle démocratique | ❌ Aucun recours pour les citoyens | ✅ Délibération, audit, recours administratif |
| RGPD | ❌ Transferts hors UE fréquents | ✅ Hébergement UE, DPA signé, registre tenu |
| Dépendance fournisseur | ❌ Totale (lock-in contractuel) | ✅ Nulle (logiciel libre, multi-hébergeurs) |
| Emploi local | ❌ Emplois délocalisés, pas de retombée locale | ✅ DSI municipal, prestataires locaux, coursiers |
Un service public numérique doit continuer à fonctionner même en cas de panne partielle. UrbaFood est conçu pour maintenir la continuité de service face aux défaillances techniques, aux changements de prestataires et aux dégradations de connectivité.
Les données sont répliquées en temps réel sur au moins trois nœuds distincts. La perte d'un serveur est transparente pour les utilisateurs finaux.
Nginx et Docker Compose surveillent la santé des services toutes les 30 secondes. Redémarrage automatique en cas de défaillance détectée.
Le reverse proxy bascule automatiquement vers un nœud secondaire dès que le primaire ne répond plus (directive upstream max_fails configurable).
Le code appartient à la communauté, pas à l'opérateur. La collectivité peut reprendre le déploiement et le support sans négociation ni indemnité.
Chaque procédure est documentée dans le wiki public. Un nouveau DSI peut prendre en main le système en quelques heures, pas en plusieurs semaines.
Format SQL standard (MariaDB). Export complet en un seul commandement. Importable sur tout hébergeur compatible MySQL/MariaDB sans transformation.
Stripe peut être remplacé par Mollie, Adyen ou un virement SEPA direct. L'intégration paiement est modulaire et documentée comme telle.
Le docker-compose.yml fonctionne sur OVHcloud, Scaleway, Outscale ou un serveur baremetal municipal sans modification de code.
Remplacement de tout prestataire d'emailing par un SMTP interne ou souverain en modifiant quatre variables d'environnement. Zéro recodage.
L'application coursier fonctionne partiellement hors-ligne grâce à Workbox : consultation des livraisons en cours, mise en cache des données récentes.
Les mises à jour de statut (commande livrée, disponibilité) sont mises en file d'attente localement et synchronisées dès le retour de la connexion.
En mode décentralisé, les nœuds d'un même réseau local (LAN/WiFi municipal) communiquent entre eux sans transiter par Internet.
Un smart contract est un programme qui s'exécute automatiquement selon des règles définies à l'avance, sans qu'aucune partie puisse les modifier unilatéralement une fois déployé. Sur le réseau UrbaFood, ils garantissent l'équité des paiements et la transparence des évaluations sans nécessiter de tiers de confiance central.
Le citoyen valide son panier. Le montant est séquestré (escrow) — ni le restaurant ni la plateforme ne peuvent y accéder avant livraison. Contrat instancié sur le registre distribué.
Le restaurant confirme la commande dans le délai imparti (ex. 5 min). Sans confirmation dans les temps, le contrat s'annule automatiquement et le paiement est remboursé.
Le coursier marque la commande livrée. Le contrat libère automatiquement : 98 % au restaurant, 1 % à la caisse municipale. Trace immuable sur le registre distribué.
// Pseudo-code — contrat de commande
contract OrderContract {
state : PENDING | CONFIRMED | PREPARING | DELIVERED | CANCELLED
escrow : montant bloque jusqu'a confirmation de livraison
on confirm_by_restaurant() -> state = CONFIRMED
on delivery_confirmed() -> release_payment() -> state = DELIVERED
on timeout(5min, PENDING) -> refund_citizen() -> state = CANCELLED
on timeout(48h, CONFIRMED) -> arbitration() -> state = DISPUTED
}Transfert automatique vers le compte Stripe Connect du restaurant dès validation de la livraison. Relevé mensuel généré automatiquement. La grille tarifaire est publique et inscrite dans le contrat.
Rémunération calculée selon la grille tarifaire publiée (distance, type de véhicule). La formule de calcul est inscrite dans le contrat et non modifiable unilatéralement par l'opérateur.
1 % prélevé automatiquement sur chaque transaction, versé à la caisse municipale dédiée. Usage : maintenance infrastructure, support technique. Rapport trimestriel public obligatoire.
Seul un citoyen ayant effectivement reçu une commande peut noter le restaurant et le coursier. La preuve est fournie par le hash de la transaction liée. Impossible de générer de fausses notes.
Score calculé sur les 90 derniers jours (pondération décroissante). Un incident isolé n'affecte pas définitivement un acteur. Score récupérable pour les commerces qui améliorent leur service.
Détection des patterns anormaux (séquences de notes similaires, délai suspect). Les anomalies sont signalées pour révision manuelle par le modérateur municipal. Sanctions décidées par délibération.
Chaque euro dépensé sur UrbaFood reste dans l'économie locale. Avec 1 % de commission contre 25–30 % sur les plateformes privées, les restaurants économisent en moyenne 24 points de marge — directement réinvestis en emploi local et en qualité.
Logiciel libre sous licence AGPL-3.0 : la collectivité possède le code, peut l'auditer, le modifier et le transmettre à d'autres communes. Fin du cycle des renouvellements de licences et des dépendances à un éditeur unique.
Accès en temps réel aux données d'activité économique locale : fréquentation des restaurants, zones de livraison, tendances de consommation. Données précieuses pour piloter la politique commerciale et soutenir les commerces en difficulté.
UrbaFood structure l'emploi local : coursiers, développeurs territoriaux, agents de validation, modérateurs municipaux. Ces emplois sont ancrés dans le territoire et ne peuvent pas être délocalisés.
La plateforme valorise les producteurs locaux via des filtres dédiés (circuits courts, bio, label local). L'algorithme de mise en avant est transparent et délibéré collectivement — pas optimisé pour la marge de la plateforme.
Rapports financiers publics trimestriels, open data sur les commissions perçues et leur usage, registre des décisions de gouvernance publié. Un niveau de transparence impossible à obtenir auprès d'une société privée.
« UrbaFood n'est pas un projet de niche. C'est la démonstration qu'une collectivité peut, avec des moyens raisonnables et une approche open source, reprendre la maîtrise de son infrastructure économique numérique — exactement comme elle possède ses routes, ses écoles et ses réseaux d'eau. »
Nous accompagnons les collectivités dans l'évaluation, la mise en œuvre et l'exploitation d'UrbaFood. Une première consultation technique est gratuite et sans engagement.