Feuille de route
Info-Mairie — Feuille de route
v0.1 — MVP Cagnes-sur-Mer ✅
Pipeline d'ingestion ✅
- [x] Scraper ville.cagnes.fr (122 séances, 265 PDFs)
- [x] Téléchargement PDFs avec cache SHA-256
- [x] Parsing PDF (PyMuPDF)
- [x] Chunking paragraph-aware (1000 chars, 200 overlap)
- [x] Embeddings OpenAI text-embedding-3-small (1536 dims)
- [x] Ingestion complète : 12 118 chunks, mars 2004 → déc 2025
Backend FastAPI ✅
- [x] API séances (liste + détail)
- [x] API élus (OpenDataSoft)
- [x] API recherche (pgvector)
- [x] API chat RAG (Claude streaming SSE)
- [x] Recherche hybride (vector + full-text, RRF)
Frontend Next.js ✅
- [x] Page d'accueil (hero + recherche + features)
- [x] Liste des séances (badges OJ/PV/Délib)
- [x] Détail séance (liens PDFs)
- [x] Chat IA (streaming, suggestions)
Infrastructure ✅
- [x] Supabase cloud (PostgreSQL + pgvector)
- [x] Repo GitHub privé
- [x] Blog "Dialogue avec Jean-Claude" (9 articles)
v0.2 — Mise en ligne 🚧
Résumés IA par séance ✅
- [x] Colonne
resumesur tableseances - [x] Script de génération batch (
pipeline/summarize.py) - [x] Affichage résumé sur page détail séance (ReactMarkdown)
- [x] Résumé structuré : points clés, décisions, chiffres
- [x] Audit liens morts + nettoyage données corrompues
- [x] Protection pipeline contre redirections HTML
Page "A propos" + Blog dev ✅
- [x] Page
/a-propos: présentation du projet par Jean-Claude (narrateur IA) - [x] Mention explicite "initiative citoyenne indépendante"
- [x] Section
/blog: 27 articles "Dialogue avec Jean-Claude" - [x] Rendu markdown statique (SSG) avec gray-matter + react-markdown
- [x] Navigation entre articles, tags, dates
- [x] Footer avec liens A propos + Blog dev
Déploiement Vercel ✅
- [x] Frontend Next.js sur Vercel
- [x] Backend FastAPI sur Vercel (serverless Python)
- [x] Variables d'environnement en prod
- [x] Security middleware (rate limiting, headers, request logging)
- [x] CORS sécurisé (regex pour *.vercel.app)
- [x] Fix env vars (.strip() contre \n parasites)
- [ ] Domaine custom (info-mairie.fr ?)
Polish frontend ✅
- [x] Responsive mobile (navbar, footer, cards, chat adaptés)
- [x] SEO / meta tags / Open Graph (chaque page avec metadata unique)
- [x] Filtrage par année sur la page séances + affichage 2004-2025
- [x] Sources cliquables dans le chat (liens vers les séances utilisées)
- [x] Page fiche commune (
/commune) - [x] Loading states et error handling avancés (skeletons, ErrorBoundary, ErrorDisplay)
v0.3 — Multi-commune
Architecture
- [ ] Sélecteur de commune dans le header
- [ ] Scraper modulaire (strategy pattern déjà prévu)
- [ ] Intégration Webdelib (Nice métropole = ~50 communes)
Communes cibles
- [ ] Nice (YouTube + Webdelib)
- [ ] Antibes, Grasse, Cannes (WordPress PDFs)
- [ ] Communes Métropole Nice Côte d'Azur
Pipeline
- [x] OCR pour anciens PDFs scannés (Google Vision API)
- [x] GitHub Actions cron pour ingestion automatique
- [x] Détection de nouvelles séances (
pipeline/check_new.py)
v0.4 — Transparence & Accountability
Suivi des présences élus ✅
- [x] Extraction automatique présents/absents/pouvoirs depuis les PV
- [x] Table
presencesen base (élu × séance → statut) - [x] Taux de présence par élu (score global)
- [x] Fiche élu : initiales, fonction, score présence, historique
- [x] Page trombinoscope (tous les élus, groupés par fonction, barre présence)
- [x] Affichage des présents sur la page détail séance (chips colorés)
- [x] 118 séances parsées, 4 989 présences, 2 165 matchées aux élus actuels
Analyse des votes — L'opposition-mètre ✅
- [x] Extraction des résultats de vote par délibération (unanimité, majorité, voix contre, abstentions)
- [x] Table
votesen base : délibération × élu → pour/contre/abstention/non-votant - [x] Vue globale par délibération : taux d'unanimité, sujets les plus contestés
- [x] Détection automatique du type de vote (unanimité, main levée, scrutin nominatif)
- [x] Page
/votes— tableau de bord des votes avec stats - [ ] Vue par séance : pour chaque délibération, qui a voté quoi (tableau coloré)
- [ ] Vue globale par élu : score de conformisme — vote-t-il toujours avec la majorité ?
- [ ] Identifier l'opposition réelle vs le conseil "godillot" (score d'indépendance)
- [ ] Intégration fiche élu : historique de vote, sujets sur lesquels il/elle a voté contre
Démographie du conseil ✅
- [x] Récupérer
date_de_naissanceetdate_debut_mandatdepuis l'API OpenDataSoft - [x] Ancienneté au conseil : depuis combien d'années l'élu siège
- [x] Pyramide des âges du conseil municipal (visualisation CSS)
- [x] Âge moyen, médian, doyen, benjamin
- [x] Parité homme/femme avec répartition par fonction (maire, adjoints, conseillers)
- [x] Durée cumulée en poste : élus +10 ans, +20 ans
Score d'activité par élu ✅
- [x] Score composite : présence (40%) + interventions (40%) + régularité (20%)
- [x] Classement des élus par activité (
/api/elus/ranking) - [x] Badge visuel sur fiche élu : "Très actif", "Actif", "Présent mais discret", "Peu impliqué", "Très peu actif"
- [x] Composant ActivityBreakdown avec détail des 3 composantes
- [ ] Comparaison par mandat : l'élu était-il plus actif avant/après une date ?
Analyse des interventions ✅
- [x] Extraction automatique des interventions depuis les PV (regex speaker detection, format
.-) - [x] 4 376 interventions extraites, 69 orateurs, 2 409 matchés aux élus actuels
- [x] Fréquence d'intervention par élu — stats sur fiche élu
- [x] Nombre de mots par élu (proxy du temps de parole)
- [x] Affichage stats interventions sur fiche élu (InterventionCard, pagination)
- [x] Top speakers API endpoint
- [x] Intervention en contexte : page
/interventions/[id]avec interventions ±5 autour - [x] Résumé IA caché : génération à la demande + cache en base (
intervention_summaries) - [x] InterventionCards cliquables sur fiche élu (linkable, highlighted, showOrateur)
- [ ] Sujets de prédilection par élu (classification Claude)
- [ ] Nuage de mots par élu — quels thèmes reviennent le plus
Suivi des promesses/projets — Timeline thématique
- [ ] Extraction auto des projets/sujets récurrents depuis les PV (urbanisme, écoles, budget...)
- [x] Classification thématique automatique des délibérations (Claude) —
pipeline/classify_deliberations.py - [ ] Timeline visuelle des projets : voir l'évolution d'un sujet à travers les séances
- [ ] Page
/projets— vue thématique plutôt que chronologique - [ ] Statut automatique : annoncé → budgété → en cours → terminé → abandonné ?
- [ ] Carte des projets — géolocaliser les projets mentionnés sur un plan de la ville
Analyse budgétaire ✅
- [x] Extraction des montants par délibération (
pipeline/extract_budgets.py) - [x] Répartition thématique du budget sur page commune
- [ ] Évolution annuelle — où va l'argent, quelles priorités changent
v0.5 — Recherche avancée & Engagement
Qualité de recherche & RAG 🚧
- [x] Query expansion / reformulation LLM : Claude reformule la question avec synonymes avant recherche
- [x] Expansion automatique dans le chat : le RAG chat utilise query expansion par défaut
- [x] System prompt dynamique : stats live (dernière séance, nombre total, période couverte)
- [x] Détection requêtes temporelles : "dernier conseil" → injection contexte dernière séance + présences
- [ ] Contextual Retrieval (Anthropic) : enrichissement sémantique de chaque chunk via Haiku avant embedding (+49% recall) 🔜
- [ ] Reranking : après la recherche hybride, re-scorer les résultats avec un modèle cross-encoder
- [ ] Synonymes français : dictionnaire de synonymes courants injecté dans la requête full-text
- [ ] Filtres contextuels : le LLM détecte automatiquement les filtres implicites
- [ ] Feedback loop : si le RAG ne trouve rien, reformuler automatiquement et retenter
Recherche avancée (UI)
- [ ] Filtres par date, type de document, thématique
- [ ] Recherche par élu (interventions, votes)
- [ ] Recherche par montant (budget > 100k€)
Blog citoyen auto-généré
- [ ] Génération automatique d'articles à chaque nouvelle séance ingérée
- [ ] Résumé vulgarisé des décisions, votes, montants
- [ ] Fil d'actualité de la ville (pas besoin de poser des questions)
- [ ] Ton journalistique, accessible, objectif
- [ ] Page
/actualitesou/newssur le site
Alertes & Ingestion automatique 🚧
- [x] Cron hebdomadaire (GitHub Actions) : scrape le site de la mairie pour détecter nouvelles séances
- [x] Ingestion automatique : download → parse → chunk → embed → présences → interventions → votes → classify → budget
- [x] Script
pipeline/check_new.py: détection + pipeline complet - [ ] Notification email/push aux abonnés quand une nouvelle séance est publiée
- [ ] Dashboard admin : statut de l'ingestion, erreurs, dernières séances ajoutées
Engagement citoyen
- [ ] Alertes email/push (nouvelle séance publiée)
- [ ] Partage de résultats (liens profonds, Open Graph)
- [ ] Export PDF des résumés
- [ ] Comparaison entre communes (quand multi-commune actif)
- [ ] Historique de recherche / favoris (localStorage, zero compte)
Ingestion réseaux sociaux
- [ ] Scraper les pages Facebook publiques des mairies (posts, événements)
- [ ] Stocker avec source différenciée (type = "facebook", "website", etc.)
- [ ] Cron horaire pour détecter les nouveaux posts
- [ ] Intégration dans le RAG : Jean-Claude cherche dans les PV ET les réseaux
- [ ] Vision long terme : un seul site-bookmark = toute la vie de la ville
Analytics & Vie privée
- [ ] Vercel Analytics (zero cookie, privacy-first)
- [ ] Mention "Zéro cookie" en footer ✅
- [ ] Aucune donnée personnelle collectée
Scraping presse locale
- [ ] Nice-Matin / France 3 Côte d'Azur — articles mentionnant la commune
- [ ] Ingestion avec source différenciée (type = "presse")
- [ ] Enrichissement du RAG : Jean-Claude peut croiser PV et actualités
Revue municipale Agora
- [ ] Scraper les numéros du magazine Agora (revue trimestrielle de Cagnes-sur-Mer)
- [ ] Probablement hébergé sur Calameo/Issuu — extraire les PDFs
- [ ] OCR si nécessaire, chunker et ingérer comme source différenciée (type = "agora")
- [ ] Enrichissement du RAG : Jean-Claude peut croiser PV, presse et communication municipale
Connaissance de la ville — Contexte géographique & historique 🚧
Problème : Jean-Claude ne connaît pas la ville. Si un citoyen demande "des travaux en centre-ville", il ne sait pas que La Villette = centre-ville, que le Cros-de-Cagnes = bord de mer, que le Haut-de-Cagnes = village médiéval. Sans ce contexte, le RAG passe à côté de résultats pertinents.
Principe : zéro génération IA. Uniquement des données factuelles vérifiables, scrapées depuis des sources officielles ou communautaires fiables. Chaque chunk porte un
source_type+source_urlpour traçabilité.
Phase 1 — Wikipédia FR (immédiat) 🚧
- [ ] Scraper l'article Wikipédia "Cagnes-sur-Mer" (géographie, quartiers, histoire, patrimoine, démographie, personnalités)
- [ ] Chunker par section (chaque section = 1+ chunks avec titre de section comme métadonnée)
- [ ] Embedder et ingérer avec
source_type = "wikipedia",source_url = "https://fr.wikipedia.org/wiki/Cagnes-sur-Mer" - [ ] Tester : "où est La Villette ?" → Jean-Claude doit répondre avec contexte géographique
Phase 2 — Site officiel ville.cagnes.fr
- [ ] Scraper les pages quartiers, équipements, histoire, projets en cours
- [ ] Ingérer avec
source_type = "site_officiel" - [ ] Enrichissement : noms de rues, écoles, parcs, équipements sportifs, marchés
Phase 3 — PLU métropolitain (gold) ⭐
- [ ] Récupérer le PLUm de la Métropole Nice Côte d'Azur (documents publics, consultables en ligne)
- [ ] Versionnage temporel : stocker chaque version du PLU avec sa date d'entrée en vigueur et sa date de fin
- [ ] Ingérer le règlement par zone (UA, UB, UC, UD, AU, N, A...) avec les règles de constructibilité
- [ ] Ingérer le PADD (Projet d'Aménagement et de Développement Durable)
- [ ] Ingérer les OAP (Orientations d'Aménagement et de Programmation) par secteur
- [ ] Requête temporelle : "Ce projet voté le 15/03/2023 respecte-t-il le PLU en vigueur à cette date ?"
- [ ] Croiser délibérations urbanisme × zonage PLU × règlement applicable
Phase 4 — Données géographiques
- [ ] OpenStreetMap : extraire quartiers, POIs, rues de Cagnes-sur-Mer (API Overpass)
- [ ] IGN/Géoportail : toponymes officiels, relief, limites communales
- [ ] Cadastre : parcelles, zonage (cadastre.gouv.fr)
Phase 5 — Sources complémentaires
- [ ] Archives départementales des Alpes-Maritimes (histoire documentée)
- [ ] Données INSEE (IRIS = découpage infra-communal avec stats socio-démographiques par quartier)
- [ ] DREAL PACA : risques naturels (PPRI, PPR incendie) — utile pour les délibérations environnement
Architecture technique
- Nouveau
source_typedans la tabledocuments:"wikipedia","site_officiel","plu","osm", etc. - Chaque chunk porte :
source_type,source_url,source_date(date de consultation/version) - Le RAG cherche dans TOUS les types de sources (PV + contexte ville) par défaut
- Le system prompt de Jean-Claude mentionne qu'il a accès au contexte géographique et historique
- Pour le PLU : champ
date_debutetdate_finpour filtrer par période d'application
Données complémentaires
- [ ] Budgets municipaux (extraction structurée)
- [ ] Délibérations individuelles (pas juste les PV)
- [ ] Liens avec data.gouv.fr quand disponible
v0.5b — Spécial Élections Municipales 2026 🗳️
Élections à Cagnes-sur-Mer : 15 et 22 mars 2026 5 candidats identifiés à ce stade
Candidats connus (Cagnes-sur-Mer)
| Candidat | Site de campagne | Notes | |----------|-----------------|-------| | Louis Nègre | louisnegre2026.fr | Maire sortant, "dernier mandat", 10 engagements | | Bryan Masson | bryanmasson2026.fr | Site Wix | | Touzeau-Menoni | À identifier | | | Pierre Piacentini | À identifier | | | Garoyan | À identifier | |
Scraping des programmes
- [ ] Scraper les sites de campagne des candidats (textes, engagements, équipes)
- [ ] Stocker les programmes par candidat avec source et date de scraping
- [ ] Gérer les sites Wix/SPA : headless browser (Playwright) si nécessaire
- [ ] Actualiser régulièrement (les programmes évoluent avant le scrutin)
Page candidats sur Info-Mairie
- [ ] Page
/elections— vue d'ensemble : date du scrutin, liste des candidats, liens vers programmes - [ ] Fiche par candidat (
/elections/{slug}) : programme, équipe, engagements - [ ] Lien vers le site officiel du candidat + mention "données publiques"
- [ ] Affichage neutre et équitable : même format pour chaque candidat
Analyse IA des programmes
- [ ] Comparaison programme vs bilan : Jean-Claude compare les promesses d'un candidat avec ce qui a été voté/fait au conseil (20 ans de PV)
- [ ] Détection d'incohérences : un candidat promet X mais a voté contre X au conseil ?
- [ ] Faisabilité budgétaire : croiser les montants promis avec les budgets historiques de la commune
- [ ] Thématiques comparées : tableau comparatif des candidats par thème (urbanisme, sécurité, culture, etc.)
- [ ] Chat RAG enrichi : "Que propose [candidat] sur les écoles ?" → réponse sourcée depuis le programme + historique PV
Garde-fous éthiques
- [ ] Neutralité absolue : pas de classement, pas de recommandation, pas d'opinion
- [ ] Sources vérifiables : chaque affirmation cite la source (programme du candidat, PV de séance, vote)
- [ ] Transparence méthodologique : page expliquant comment l'analyse est faite
- [ ] Droit de réponse : formulaire de contact pour les candidats qui contestent une analyse
- [ ] Mentions légales : respect de la période de réserve électorale
v0.5c — Agora citoyenne 🏛️ ✅
Espace public de dialogue entre citoyens, modéré par Jean-Claude.
Concept ✅
- [x] Page
/agora— grille de 8 catégories (Urbanisme, Budget, Vie quotidienne, Éducation, Culture & Sport, Environnement, Sécurité, Divers) - [x] Page
/agora/[category]— liste de threads, tri récent/populaire, nouveau sujet - [x] Page
/agora/[category]/[thread]— détail, replies, votes, formulaire réponse - [x] Jean-Claude auto-reply — après création d'un thread, RAG → Claude → réponse automatique avec sources
- [x] Votes up/down anonymes (hash IP SHA-256, unique par thread/reply)
- [x] Anti-spam : honeypot, validation longueur
- [x] Backend : 7 endpoints CRUD (categories, threads, replies, votes)
- [x] Migration SQL avec trigger auto-update stats
À venir
- [ ] Jean-Claude modération temps réel (injures, diffamation)
- [ ] Tags thématiques auto-générés par discussion
- [ ] Résumé IA des discussions longues
- [ ] Inscription légère (email vérifié) pour anti-abus avancé
v0.5d — Connaissance juridique française 📜
Jean-Claude cite la loi. Il sait que le maire a des obligations légales. Uniquement RAG — jamais de génération juridique sans source.
Phase 1 — CGCT (Code général des collectivités territoriales)
- [ ] Ingestion via API Légifrance (AIFE) — articles du CGCT en vigueur
- [ ] Chunking par article avec préfixe
[CGCT — L.2121-7 — Réunion du conseil municipal] - [ ] source_type = "legislation", source_url = lien Légifrance
- [ ] Le RAG croise PV + article de loi : "Le maire a-t-il le droit de..." → PV + texte de loi
Phase 2 — Code de l'urbanisme
- [ ] Articles pertinents : PLU, permis de construire, droit de préemption (L.421-1 à L.424-9)
- [ ] Croiser avec délibérations urbanisme
Phase 3 — CRPA (Code des relations entre le public et l'administration)
- [ ] Droits des citoyens : accès aux documents, délais de réponse, transparence
- [ ] Permettre "quels sont mes droits si la mairie ne répond pas ?"
Phase 4 — Code de la commande publique
- [ ] Marchés publics, appels d'offres, seuils
- [ ] Croiser avec délibérations budget/marchés
Architecture
- [ ] Pipeline
ingest_legifrance.py— API AIFE ou scraping Légifrance - [ ] Chunking par article avec métadonnées (code, section, numéro article, date version)
- [ ] Versionnage : chaque article a une
date_vigueurpour requêtes temporelles - [ ] source_type = "legislation" dans la table documents
v0.5e — Simplification des démarches 📋 (futur)
Jean-Claude aide les citoyens à comprendre les procédures administratives. Sources : service-public.fr (API), démarches-simplifiées, site mairie.
Concept
- [ ] "Comment obtenir un permis de construire ?" → étapes, documents nécessaires, délais
- [ ] Ingestion service-public.fr — fiches pratiques par démarche
- [ ] Croiser avec contexte local : "À Cagnes, le service urbanisme est au..."
- [ ] Page
/demarches— guide des démarches courantes, filtré par commune
Un litige ? Une question ? Besoin d'aide ?
- [ ] CTA "Prendre rendez-vous avec un avocat" — orientation vers les consultations juridiques gratuites de la ville
- [ ] Détection automatique : si Jean-Claude identifie un litige potentiel dans la conversation → suggestion proactive
- [ ] Annuaire des permanences juridiques gratuites (mairie, maison de justice, CDAD)
- [ ] Liens vers les avocats du barreau local (API annuaire des barreaux si dispo)
- [ ] Disclaimer clair : "Jean-Claude informe, il ne conseille pas. Pour un avis juridique, consultez un professionnel."
v0.6 — Intelligence & Insights
Détection d'anomalies
- [ ] Alerter quand un montant est anormalement élevé par rapport à l'historique
- [ ] Détecter les délibérations qui passent sans débat (unanimité silencieuse sur gros montants)
- [ ] Identifier les élus dont le taux de présence chute brusquement
Comparaisons inter-communes
- [ ] Benchmarking : budget/habitant, taux de présence moyen, fréquence des séances
- [ ] Classement des communes les plus transparentes (nombre de PV publiés, délais de publication)
- [ ] Partage de données entre communes pour enrichir le RAG
v0.7 — Monétisation & SaaS
Le produit est gratuit pour les citoyens dans sa version de base. La valeur ajoutée (juridique, multi-commune, API) peut être monétisée.
Tiers & Gating
| Tier | Cible | Prix | Inclus | |------|-------|------|--------| | Citoyen (gratuit) | Grand public | 0€ | PV, présences, interventions, élus, Wikipedia, Agora, chat (X questions/jour) | | Citoyen+ | Citoyen engagé | ~3-5€/mois | Chat illimité, recherche juridique croisée (PV + loi), alertes personnalisées, export PDF | | Élu / Candidat | Candidats municipaux | ~20€/mois | Analyse comparative programmes vs bilan, dashboard élection, données historiques complètes | | Collectivité | Mairies, interco | ~200-500€/mois | Multi-commune, API access, dashboard analytics, support, marque blanche possible | | Cabinet / Avocat | Professionnels du droit | ~50-100€/mois | Recherche juridique avancée (codes + jurisprudence), requêtes temporelles, volume illimité |
Features premium (backlog)
- [ ] Middleware de gating : vérification du tier avant chaque endpoint (header API key ou session)
- [ ] Compteur de questions : X questions/jour gratuit, au-delà → upgrade
- [ ] Recherche juridique croisée : PV + article de loi + jurisprudence → tier payant
- [ ] Requêtes temporelles historiques : "la loi en 2018 ?" → fetcher les versions anciennes des articles (articleVersions API)
- [ ] CTA avocat : orientation vers consultations juridiques → affiliation ou partenariat barreaux
- [ ] Export PDF : résumés de séance, fiches élu, analyses → watermarked avec tier
- [ ] Alertes personnalisées : nouvelle séance, mot-clé détecté, élu suivi → email/push
- [ ] API publique : endpoints documentés avec rate limiting par tier
- [ ] Dashboard collectivité : stats d'utilisation, questions fréquentes des citoyens, insights
- [ ] Marque blanche : le produit sous la marque de la collectivité
- [ ] Stripe integration : paiement, abonnements, factures
Modèle de revenus potentiels
- [ ] B2C : abonnement citoyen+ (volume = beaucoup de petits montants)
- [ ] B2B : licence collectivité (peu de clients, gros tickets)
- [ ] B2B2C : la collectivité paie pour que ses citoyens aient accès premium
- [ ] Affiliation : CTA avocat / notaire / service juridique en ligne
- [ ] Freemium : le gratuit génère du trafic, le payant génère du revenu
Dernière mise à jour : 11 février 2026 (v0.7 Monétisation + v0.5d Légifrance + Contextual Retrieval + Agora)