尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证正在加载完整 README。 以下为已保存的摘录。
Fiches territoriales — générateur automatisé de diagnostics territoriaux Application web (Next.js / TypeScript) qui produit, à partir d'un code postal ou d'un nom de commune, une fiche de diagnostic territorial sourcée, reproductible et exportable (PDF, DOCX, CSV, JSON, GeoJSON), en s'appuyant exclusivement sur des données publiques françaises.查看完整 README ↗
Application web (Next.js / TypeScript) qui produit, à partir d'un code postal ou d'un nom de commune, une fiche de diagnostic territorial sourcée, reproductible et exportable (PDF, DOCX, CSV, JSON, GeoJSON), en s'appuyant exclusivement sur des données publiques françaises.
Le rapport s'ouvre sur une fiche d'action (approche LFI) puis suit le plan du cahier des charges : présentation générale, profil sociodémographique, économie et emploi, services et équipements, mobilité, logement et cadre de vie, contexte électoral (strictement descriptif), analyse transversale, synthèse opérationnelle — complété d'une annexe méthodologique, d'un journal de collecte et d'une bibliographie numérotée.
Principe directeur : aucune valeur n'est estimée ni inventée. Une donnée indisponible est affichée « n.d. », listée parmi les données manquantes, et l'étape de collecte correspondante figure en échec dans le journal.
Prérequis : Node.js ≥ 20 et, pour l'export PDF, un Chromium/Chrome installé (détecté automatiquement, sinon renseigner CHROMIUM_PATH).
npm install
cp .env.example .env.local # facultatif : tous les réglages ont une valeur par défaut
npm run dev # http://localhost:3000
Production :
npm run build && npm start
L'application interroge les hôtes suivants (HTTPS) ; ils doivent être joignables depuis le serveur :
| Hôte | Usage |
|---|---|
geo.api.gouv.fr | contours, surfaces, centres, communes du département |
api.insee.fr | API Melodi (recensement, Filosofi, populations de référence) |
files.data.gouv.fr | DVF géolocalisé |
www.insee.fr | fichiers nationaux : BPE, bases IRIS, statistiques QPV |
data.geopf.fr | contours IRIS (WFS de la Géoplateforme IGN) |
eu.ftp.opendatasoft.com | horaires SNCF (GTFS) |
router.project-osrm.org (configurable) | temps de trajet routiers |
overpass-api.de (configurable) | équipements OpenStreetMap |
georisques.gouv.fr | risques, CatNat, ICPE |
data.education.gouv.fr | annuaire de l'éducation |
ressources.data.sncf.com | gares et fréquentation |
recherche-entreprises.api.gouv.fr | base SIRENE |
www.data.gouv.fr, tabular-api.data.gouv.fr, static.data.gouv.fr | résultats électoraux (commune, bureau de vote), Répertoire électoral unique |
tile.openstreetmap.org (navigateur) | fond des cartes interactives |
Le référentiel administratif (codes postaux, communes, EPCI, populations légales) est embarqué : la recherche fonctionne sans réseau.
Pour vérifier les sources : npm run check:sources (et npm run check:sources -- --insee 60159 pour lister les dimensions et modalités INSEE réellement servies).
60200), un code INSEE (ex. 60159, 2A004) ou un nom (Compiègne). Si plusieurs communes correspondent (code postal partagé, ou code postal identique au code INSEE d'une autre commune), choisir la bonne dans la liste. En circonscription, la ou les circonscriptions de la commune s'affichent (avec la part de sa surface quand elle est partagée).npm run generate -- 60200 # commune unique
npm run generate -- 60350 --commune 60491 # code postal ambigu
npm run generate -- 60159 --scope epci --out demo # périmètre intercommunal
Produit <id>.pdf, .docx, .html, .json, -indicateurs.csv, -series.csv.
.env.local)| Variable | Défaut | Rôle |
|---|---|---|
DATA_DIR | ./data | cache HTTP et rapports |
CACHE_TTL_HOURS | 720 | durée de validité du cache |
OFFLINE | 0 | 1 : aucune requête, cache et référentiel uniquement |
HTTP_TIMEOUT_MS | 20000 | délai maximal par requête |
INSEE_MIN_INTERVAL_MS | 2100 | espacement des requêtes INSEE (limite 30/min) |
OVERPASS_URL | overpass-api.de | instance Overpass |
CHROMIUM_PATH | auto | exécutable pour l'export PDF |
GENERATION_CONCURRENCY | 1 | générations simultanées (les suivantes attendent leur tour) |
HEAVY_CONCURRENCY | 2 | fichiers nationaux traités en même temps ; attente automatique au-delà de 60 % de la mémoire |
DOWNLOAD_STALL_MS | 120000 | abandon puis nouvel essai d'un téléchargement bloqué |
MEMORY_LIMIT_MB | auto | limite mémoire, si elle n'est pas lue dans le conteneur |
LLM_PROVIDER | none | anthropic pour la reformulation assistée (facultatif) |
ANTHROPIC_API_KEY, ANTHROPIC_MODEL | — | clé et modèle si LLM_PROVIDER=anthropic |
Chaque rapport commence par une fiche d'action rédigée sur le modèle des fiches « PEE · Développement territorial » (une « proposition de ciblage » par territoire) :
Les textes acceptent une mise en évidence minimale (**gras**), rendue dans l'interface, le PDF et le DOCX, et retirée des exports CSV.
Accès réservé : dès que la variable AUTH_USERS est renseignée, toutes les pages et API exigent une connexion (identifiant et mot de passe ; session de 30 jours ; 10 tentatives par quart d'heure). Pour ajouter une personne : npm run mot-de-passe -- prenom.nom (le mot de passe est saisi puis chiffré), copier la ligne affichée dans AUTH_USERS sur Railway (comptes séparés par ;), et définir une fois AUTH_SECRET (longue chaîne aléatoire). Retirer une ligne de AUTH_USERS coupe l'accès de la personne immédiatement. Bouton « Déconnexion » dans l'en-tête.
Rôles : variable AUTH_ROLES, par exemple marie:admin;paul:lecteur.
| Rôle | Peut |
|---|---|
admin | tout, y compris déposer et supprimer les données internes (page « Données internes ») |
editeur | générer et régénérer des fiches, saisir les retours du terrain et les lieux signalés |
lecteur | consulter et télécharger les fiches existantes |
Un compte absent de AUTH_ROLES est editeur. Tant qu'aucun admin n'est déclaré, tous les comptes restent administrateurs (aucun accès perdu lors de la mise à jour).
Retours du terrain : sous l'en-tête de la fiche et sous chaque partie (population, situation politique, actions), un encadré permet d'ajouter un retour qualitatif ; il est conservé à la régénération et repris dans le PDF et le Word. Les lieux d'action (marchés, associations…) se saisissent dans l'encadré dédié.
Fiche synthétique : le profil sociodémographique s'ouvre sur une phrase en langage courant, suivie d'un tableau limité aux indicateurs qui distinguent vraiment la commune du département (7 au plus) et de 2 ou 3 phrases qualitatives ; le profil politique s'ouvre sur un « En bref ». Le détail reste dans le diagnostic complet.
Feuilles de porte-à-porte : pour chaque bureau prioritaire, une page imprimable avec les rues et numéros à couvrir (Base adresse nationale, adresses rattachées au bureau par leur position dans les contours), une carte, le lieu de vote et une case « Fait » par voie. Bouton « PDF porte-à-porte » (ou …/export/pdf?porte=1). Désactivable avec DISABLE_SOURCES=ban.
Évolution du vote par bureau : européennes 2019 → 2024, présidentielle 2017 → 2022 (bureaux appariés par numéro, inscrits à ±25 %) et score de la gauche unie aux législatives 2024. Désactivable avec DISABLE_SOURCES=elections_historiques.
Lieux d'action signalés par les militants : marchés, associations, lieux de passage saisis dans la fiche (jours, horaires, adresse) ; chaque adresse est géolocalisée et rattachée à son bureau de vote ; conservés d'une régénération à l'autre et repris dans le PDF et le Word.
Vitesse et mémoire : les sources indépendantes sont interrogées en parallèle ; l'INSEE reste séquentiel (limite de débit). Les fichiers nationaux (contours des bureaux de vote, BPE, GTFS, IRIS, résultats électoraux) sont lus en flux et leurs extraits départementaux ou communaux sont gardés sur disque (data/cache/extracts/, 1 à 30 jours selon la source) : la fiche suivante dans le même département les réutilise sans relire le fichier national. Un extrait incomplet (sous-source en panne) n'est pas mis en cache. Sur Railway, monter un volume persistant sur /data pour que ce cache survive aux redéploiements. La page de progression et les journaux du serveur indiquent la mémoire utilisée à chaque étape.
Export court : bouton « PDF fiche d'action » (ou …/export/pdf?fiche=1, et <id>-fiche-action.pdf en ligne de commande) — la fiche d'action seule, quelques pages, comme le document de référence.
Fiche au format du document de référence (menu « Autres formats ») : la même fiche mise en page comme le document Word « Développement territorial » (Arial, titres soulignés, une couleur par proposition de ciblage, tableaux quadrillés, « en bref » en liste à puces). Disponible en PDF (…/export/pdf?fiche=1&style=yonne), en Word modifiable (…/export/docx?fiche=1) et en aperçu HTML (…/export/html?fiche=1&style=yonne).
Méthode de priorisation des bureaux : potentiel = moyenne de deux scores z calculés entre les bureaux de la commune — réservoir (part LFI des exprimés aux européennes 2024, moyennée avec la part de J.-L. Mélenchon au 1er tour de la présidentielle 2022 pour les bureaux appariés) et marge de mobilisation (taux d'abstention aux européennes) ; priorité 1 = un quart des bureaux, 4 au maximum ; priorité 2 = jusqu'à la moitié. La fiche présente les deux scrutins côte à côte : chiffres clés, cartes par bureau (vote LFI / participation 2024, vote Mélenchon / participation 2022), classement, graphique, quartiers et porte-à-porte.
Géographie des bureaux de vote (dans l'ordre) : fichier fourni data/interne/bv-<code INSEE>.geojson (contours officiels de la mairie, propriété bv ou numero), contours publiés sur data.gouv.fr, ou enveloppes approximatives calculées à partir des adresses du Répertoire électoral unique (INSEE).
Données internes (facultatives) — à déposer dans data/interne/ (jamais versionné) :
| Fichier | Colonnes | Usage |
|---|---|---|
parrains.csv | code_commune;parrains | colonne « Parrains » et ratio parrains / voix LFI vs département |
groupes.csv | code_commune;nom;membres;statut;description | encadré « Implantation militante » |
bv-<code>.geojson | polygones avec propriété bv | carte exacte des bureaux |
RES_STMT_COM*.csv / RES_NAT.csv | COMRES;MOISTA;_FREQ_;part_fem;AGE_m;ancien_m | demandeurs d'emploi (France Travail) par commune et par mois : phrase de la fiche, tableau et courbes (partie C et annexe) |
Demandeurs d'emploi : le fichier communal (≈ 230 Mo) se dépose depuis la page « Données internes » (compressé dans le navigateur, lu en flux sur le serveur, environ 20 s) ou se copie dans data/interne/ (importé au premier usage). Il est découpé une fois pour toutes en un fichier par département (data/interne/demandeurs-emploi/). Rupture de série en janvier 2025 (inscription automatique des allocataires du RSA et des jeunes suivis par une mission locale) : signalée dans les notes.
Exemples dans docs/exemples-interne/. Uniquement des agrégats par commune : aucun nom de personne.
Garde-fous : uniquement des agrégats publics (commune, bureau de vote) ; aucune donnée individuelle ; aucune variable d'origine ou de nationalité ; explications présentées comme hypothèses.
Sur le modèle des cartes du pôle, rendues en SVG (PDF, Word, PNG, et dans l'interface) :
Choisir « Ciblage d'un département » sur la page d'accueil (ou npm run generate -- <commune> --scope departement). L'application compare toutes les communes du département, sur le modèle de la fiche Yonne :
Bouton « Intercommunalité » : ciblage des communes membres (chaque commune de 500 habitants et plus, toutes si l'intercommunalité est très rurale), même score que le ciblage départemental, sans plafond par intercommunalité ni ville écartée d'office. Dans la Métropole du Grand Paris, l'intercommunalité retenue est l'établissement public territorial (ex. Ivry-sur-Seine → Grand-Orly Seine Bièvre, 24 communes), pas la métropole. Une intercommunalité à cheval sur deux départements (Grand-Orly : Val-de-Marne et Essonne) est traitée en entier : résultats et contours des deux départements.
Bouton « Circonscription » de l'accueil : même méthode que le ciblage départemental, limitée aux communes de la circonscription législative (contours data.gouv.fr). Une commune est retenue dès que 20 % de sa surface, ou son centre, est dans la circonscription ; les communes partagées sont signalées sous le classement (résultats de toute la commune). Les comparaisons (communes de taille comparable, moyennes) restent départementales et aucune grande ville n'est écartée d'office. Cartes et titres sont centrés sur la circonscription.
Catalogue « Mon Logement Étudiant » (Crous et hors Crous) relevé chaque mois par les militants. Dans la fiche d'action :
#F91616 sur la carte « affiche » ;Mise à jour : déposer le classeur Excel du mois dans Données internes (il remplace la copie intégrée), ou mettre à jour la copie intégrée : npm run import:residences -- chemin/catalogue.xlsx puis commit. Onglets lus : « Résidences » et « Adresses » (colonnes repérées par leur intitulé).
Page Données internes : dépôt des parrainages, des groupes (format simple) ou de l'export brut d'Action Populaire (colonnes reconnues par leur intitulé ; commune retrouvée par code postal et ville ; colonnes nominatives ignorées). Les fichiers restent dans data/interne/. En ligne, protéger l'application par une authentification : cette page permet de déposer et supprimer ces fichiers.
L'API de l'INSEE (Melodi) est limitée à 30 requêtes par minute ; une fiche en demandait plus de 120 (une par jeu de données et par territoire), soit plus de 4 minutes d'attente imposée. Les territoires (commune, intercommunalité, département, région, France, communes du périmètre, communes comparables) sont désormais demandés ensemble, jeu par jeu : environ 25 requêtes, pour exactement les mêmes données (vérifié par le test d'intégration : fiche identique avec et sans regroupement). Un territoire absent de la réponse groupée est redemandé seul ; si l'API refuse le regroupement, l'application revient d'elle-même à l'ancienne méthode. npm run check:sources indique si le regroupement est actif ; MELODI_BATCH=0 le désactive.
La BPE (≈ 136 Mo), les bases IRIS (≈ 70 Mo) et le GTFS SNCF sont téléchargés une fois puis mis en cache (CACHE_TTL_HOURS) ; leur lecture en flux limite la mémoire. Pour s'en passer : DISABLE_SOURCES=bpe,gtfs,iris. Les adresses des fichiers INSEE (qui changent à chaque millésime) sont surchargeables : INSEE_BPE_URL, INSEE_IRIS_POP_URL, INSEE_IRIS_LOGEMENT_URL, INSEE_IRIS_ACTIVITE_URL, INSEE_IRIS_FILOSOFI_URL, INSEE_QPV_FILOSOFI_URL, INSEE_QPV_RP_URL, SNCF_GTFS_URL, OSRM_URL.
Vercel n'est pas adapté à la génération des fiches : une génération dure plusieurs minutes, télécharge des fichiers nationaux de plusieurs centaines de Mo (résultats par bureau de vote, contours), a besoin d'environ 2 Go de mémoire, d'un cache persistant et de Chromium pour le PDF. Les fonctions serverless de Vercel sont limitées en durée, n'ont pas de disque persistant et arrêtent les traitements lancés en arrière-plan. Sur Vercel, l'application démarre (recherche de communes, consultation) mais refuse la génération avec un message explicite (ALLOW_SERVERLESS_GENERATION=1 pour forcer, à vos risques).
Hébergement recommandé : un serveur ou un conteneur (Railway, Render, Fly.io, ou un petit VPS), à partir du Dockerfile fourni :
/data (cache et fiches générées) ;3000 (ou variable PORT).Exemple sur Railway : New Project → Deploy from GitHub repo → le Dockerfile est détecté → Settings → Volumes : ajouter un volume monté sur /data → Networking : générer un domaine.
Si la page de génération indique « génération interrompue » : le serveur a redémarré en cours de route, le plus souvent faute de mémoire. Vérifier dans Railway l'onglet Metrics (pic de mémoire) et Deployments → Logs (Killed, out of memory), passer à une offre avec plus de mémoire (formule d'essai insuffisante) et relancer : grâce au volume /data, les fichiers déjà téléchargés ne le sont pas une seconde fois. Les gros fichiers nationaux sont téléchargés sur disque et lus en flux pour limiter la mémoire nécessaire.
Exemple sur un VPS (Debian/Ubuntu avec Docker) :
git clone <dépôt> fiches && cd fiches
docker build -t fiches .
docker run -d --restart unless-stopped -p 80:3000 -v fiches-data:/data --name fiches fiches
Pour protéger l'accès (fiches contenant des données internes), placer le service derrière une authentification (ex. accès restreint de la plateforme, ou proxy avec mot de passe).
src/
lib/
config.ts, cache.ts, http.ts Configuration ; cache disque ; client HTTP (délais, nouvelles
tentatives, coupe-circuit, repli sur cache périmé, hors ligne)
collectors/ COLLECTE — un connecteur par source
catalog.ts catalogue des sources (licences, accès, limites)
context.ts journal de collecte, données manquantes
admin.ts référentiel embarqué + geo.api.gouv.fr
insee.ts, insee-indicators.ts API Melodi : lecture générique des cubes + déclaration des indicateurs
dvf.ts, osm.ts, public-apis.ts, elections.ts
report/
collect.ts orchestration de la collecte (étapes isolées, progression)
assemble.ts NORMALISATION : indicateurs, séries, tableaux, graphiques, cartes
sections.ts plan A→I et rédaction par gabarits
build.ts, store.ts chaîne complète ; stockage JSON et tâches de fond
analysis/
stats.ts CALCULS déterministes (médiane, MAD, z robuste, TCAM, écarts…)
findings.ts moteur de constats (constat / atout / vigilance / hypothèse / piste / à vérifier)
llm/provider.ts abstraction LLM + garde-fou numérique (facultatif)
render/ RENDU : SVG (graphiques, cartes, carte nationale), HTML imprimable
export/ EXPORT : PDF (Chromium), DOCX (docx), CSV
app/ pages (accueil, progression, rapport, méthodologie) et routes API
components/ visionneuse, graphiques Recharts, cartes Leaflet
scripts/ generate.ts (CLI), check-sources.ts (diagnostic)
tests/ tests unitaires, d'intégration (API simulées) et e2e
Arbitrages
store.ts et cache.ts isolent l'interface pour une migration PostgreSQL/PostGIS.(x − médiane) / (1,4826 × MAD) ≥ 2 en valeur absolue parmi au moins 5 communes comparables.npm test # vitest : unitaires + intégration (API simulées, sans réseau)
npm run lint # vérification TypeScript
# e2e (serveur lancé) :
BASE_URL=http://localhost:3000 node tests/e2e/smoke.mjs
tests/stats.test.ts — calculs statistiques et règle de significativité.tests/connectors.test.ts — DVF (règles d'exclusion), lecture des cubes INSEE, agrégation électorale, classification OSM, référentiel réel (codes postaux simples et ambigus, communes nouvelles), garde-fou LLM.tests/integration.test.ts — chaîne complète avec API simulées (tests/fixtures/mock-apis.ts, valeurs fictives) : valeurs calculées vérifiées, cartes, graphiques, constats reliés aux preuves, exports PDF/DOCX/CSV, seconde génération servie par le cache.tests/degraded.test.ts — sources en panne, données non diffusées, mode hors ligne.tests/e2e/smoke.mjs — parcours navigateur : code postal ambigu → choix → génération → rapport → exports.Voir STATUS.md pour les résultats et l'état des lieux, SOURCES.md pour le détail des sources.
src/lib/collectors/insee-indicators.ts (codes candidats, puis expressions régulières sur codes et libellés). Utiliser npm run check:sources -- --insee <code> pour inspecter les modalités servies.ELECTIONS (src/lib/collectors/elections.ts) avec le slug data.gouv.fr du jeu ou l'identifiant de ressource.@etalab/decoupage-administratif à chaque nouveau millésime du COG (et POPULATION_VINTAGE dans admin.ts).data/cache/.Les données utilisées sont publiques et agrégées (Licence Ouverte 2.0, ODbL pour OpenStreetMap et SNCF, CC BY 4.0 pour le fond SVG national) ; les attributions figurent dans chaque rapport. L'application ne collecte aucune donnée personnelle. Le chapitre électoral est descriptif : aucune inférence individuelle, aucun classement de quartiers à des fins de ciblage.