SPB Git forge

spb/vrai-prix

Public

Vrai-Prix — l'évaluation du vrai prix des propriétés résidentielles au Québec.

60commits 1branches 0releases
12.3 MBsize
maindefault branch
17 days agolast push
TypeScript 90.2% JavaScript 3.5% Python 3.4% CSS 1.9% HTML 0.6%

docs: README à jour avec screenshot

Simon-Pierre Boucher committed 1 mo ago (Aug 18, 2026) parent f5636d4

2 changed files +94 −42

modified README.md +94 −42
@@ -4,8 +4,8 @@
4 4
5 5 **La vraie valeur de votre propriété, sans boîte noire.**
6 6
7 −Moteur d'évaluation immobilière transparent pour le Québec — 3,7 millions de propriétés,
8 −745 119 ventes réelles, chaque calcul montré en entier.
7 +Moteur d'évaluation immobilière **transparent** pour le Québec — **3 747 008 propriétés**,
8 +**745 119 ventes réelles (2021-2026)**, chaque calcul montré en entier.
9 9
10 10 ![Propriétés](https://img.shields.io/badge/propri%C3%A9t%C3%A9s-3%C2%A0747%C2%A0008-ff5148?style=flat-square)
11 11 ![Ventes](https://img.shields.io/badge/ventes_r%C3%A9elles-745%C2%A0119-ff5148?style=flat-square)
@@ -23,15 +23,16 @@ Moteur d'évaluation immobilière transparent pour le Québec — 3,7 millions d
23 23
24 24 **En production : [www.vrai-prix.com](https://www.vrai-prix.com)**
25 25
26 −<img src="docs/screenshots/accueil.png" alt="Accueil Vrai-Prix — La vraie valeur, sans boîte noire" width="920">
27 −
28 26 </div>
29 27
28 +![Aperçu de Vrai-Prix](docs/screenshot.png)
29 +
30 30 ---
31 31
32 32 ## Sommaire
33 33
34 34 - [Ce que fait Vrai-Prix](#ce-que-fait-vrai-prix)
35 +- [Fonctionnalités](#fonctionnalités)
35 36 - [Visite guidée](#visite-guidée)
36 37 - [Les chiffres qui comptent](#les-chiffres-qui-comptent)
37 38 - [Architecture](#architecture)
@@ -40,32 +41,39 @@ Moteur d'évaluation immobilière transparent pour le Québec — 3,7 millions d
40 41 - [SEO programmatique](#seo-programmatique--376-m-durls-indexables)
41 42 - [Structure du projet](#structure-du-projet)
42 43 - [Endpoints](#endpoints)
43 −- [Démarrage](#démarrage)
44 +- [Démarrage local](#démarrage-local)
45 +- [Déploiement](#déploiement)
46 +- [Développement remote-first](#développement-remote-first)
44 47 - [Design](#design)
45 48 - [Auteur](#auteur)
46 49
47 50 ## Ce que fait Vrai-Prix
48 51
49 −Vrai-Prix estime la valeur marchande de **n'importe quelle propriété du Québec** (unifamiliale, plex, condo, chalet, terrain) et montre *pourquoi* — chaque comparable, chaque ajustement en dollars, la pondération du modèle, la fourchette et l'indice de confiance. Le différenciateur est la **transparence totale** : pas de score magique, pas de boîte noire.
52 +Vrai-Prix estime la valeur marchande de **n'importe quelle propriété du Québec** (unifamiliale, plex, condo, chalet, terrain) et montre *pourquoi* — **chaque comparable, chaque ajustement en dollars**, la pondération du modèle, la fourchette et l'indice de confiance. Le différenciateur est la **transparence totale** : pas de score magique, **pas de boîte noire**. La méthodologie complète (normes **IAAO**) est publiée intégralement sur le site.
53 +
54 +Sous le capot : les **6 millésimes (2021-2026)** des rôles d'évaluation foncière géoréférencés du Québec (**MAMH**, données ouvertes) — soit **22 150 285 observations** — fusionnés spatialement avec **745 119 transactions réelles** (**99,88 %** d'appariement, distance médiane **0,6 m**), alimentant un **modèle hédonique LightGBM** et un **moteur de comparables ajustés**.
55 +
56 +## Fonctionnalités
50 57
51 58 | Fonctionnalité | Description |
52 59 |---|---|
53 −| 🔎 Recherche d'adresse | Plein-texte (FTS5) parmi 3 747 008 unités d'évaluation, tolérante aux fautes |
54 −| 💰 Estimation hybride | 65 % modèle hédonique + 35 % comparables ajustés |
55 −| 📊 Fourchette + confiance | P10–P90 par régression quantile, indice A–D obligatoire |
60 +| 🔎 **Estimation par adresse** | Recherche plein-texte (**FTS5**) parmi **3 747 008 unités d'évaluation**, tolérante aux fautes |
61 +| 🧮 **Plan B sans adresse** | **Estimation manuelle** (municipalité + caractéristiques) quand la propriété n'est pas au registre |
62 +| 💰 **Estimation hybride** | **65 % modèle hédonique + 35 % comparables ajustés** |
63 +| 📊 **Fourchette + confiance** | **P10–P90** par régression quantile, indice **A–D** obligatoire |
56 64 | 🏠 Portrait de la propriété | Façade SVG dessinée par les données du registre, terrain à l'échelle, composition de la valeur |
57 −| 🗺️ Vrai-Prix Maps | Recherche par carte 3D (Mapbox GL via le framework partagé **Ka Maps**) — grappes de valeurs estimées pilotées par le viewport |
65 +| 🗺️ **Vrai-Prix Maps** | Recherche par **carte 3D** (Mapbox GL via le framework partagé **Ka Maps**) — grappes de valeurs estimées pilotées par le viewport |
58 66 | 📐 Plan des comparables | Carte « plan d'arpenteur » maison (SVG pur, zéro tuile) — azimut et distance réels |
59 −| 📈 Historique 2021→2026 | Six millésimes d'estimations par propriété, badges YoY |
60 −| 🤖 Ka · agent IA | Agent conversationnel (Claude) branché sur 12 outils serveur : évaluation, comparables, stats, dossier d'expert |
61 −| 🏢 Parc immobilier | Évaluation multi-adresses agrégée (jusqu'à 40 propriétés) + rapport consolidé |
62 −| 📄 Rapports PDF | Standard (3 p.), professionnel bancaire (6 p.), parc (n+1 p.), statistique provincial — 100 % vectoriels |
63 −| 📉 Statistiques | Valeur totale de la province (**2,01 billions $**), palmarès des 200 municipalités |
64 −| 🏙️ Pages municipalités | 1 097 pages programmatiques (médiane, croissance, médianes par type) + ~5 900 pages municipalité × type |
65 −| 🔑 KA ID | Connexion unique du Groupe KA (SSO signé via le hub groupe-ka.com, session sans base d'utilisateurs) |
66 −| 🌐 Bilingue | FR (défaut) / EN, bascule instantanée côté client |
67 −| 📱 App iOS | Compagnon natif SwiftUI (onglet carte MapKit) — dépôt séparé |
68 −| ⚖️ Conformité | Loi 25, sélecteur de témoins, méthodologie publique intégrale |
67 +| 📈 Historique 2021→2026 | **Six millésimes** d'estimations par propriété, badges YoY |
68 +| 🤖 **Ka · agent IA** | Agent conversationnel (**Claude**) branché sur **12 outils serveur** : évaluation, comparables, stats, dossier d'expert |
69 +| 🏢 Parc immobilier | Évaluation multi-adresses agrégée (jusqu'à **40 propriétés**) + rapport consolidé |
70 +| 📄 Rapports PDF | Standard (3 p.), professionnel bancaire (6 p.), parc (n+1 p.), statistique provincial — **100 % vectoriels** |
71 +| 📉 **Statistiques** | Valeur totale de la province (**2,01 billions $**), palmarès des **200** municipalités |
72 +| 🏙️ Pages municipalités | **1 097** pages programmatiques (médiane, croissance, médianes par type) + **~5 900** pages municipalité × type |
73 +| 🔑 KA ID | Connexion unique du **Groupe KA** (SSO signé via le hub groupe-ka.com, session sans base d'utilisateurs) |
74 +| 🌐 Bilingue | **FR** (défaut) / **EN**, bascule instantanée côté client |
75 +| 📱 App iOS | Compagnon natif **SwiftUI** (onglet carte MapKit) — dépôt séparé |
76 +| ⚖️ **Méthodologie transparente** | Loi 25, sélecteur de témoins, méthodologie publique intégrale (7 sections, normes **IAAO**) |
69 77
70 78 ## Visite guidée
71 79
@@ -82,16 +90,16 @@ Vrai-Prix estime la valeur marchande de **n'importe quelle propriété du Québe
82 90
83 91 ## Les chiffres qui comptent
84 92
85 −Validation sur **102 943 ventes jamais vues** du modèle (holdout aléatoire) et test temporel strict (entraîné sans 2026, testé sur 68 364 ventes de 2026), selon la **norme IAAO sur études de ratios** :
93 +Validation sur **102 943 ventes jamais vues** du modèle (holdout aléatoire) et **test temporel strict** (entraîné sans 2026, testé sur **68 364 ventes de 2026**), selon la **norme IAAO sur études de ratios** :
86 94
87 95 | Métrique | Holdout | Test temporel 2026 | Cible IAAO |
88 96 |---|---|---|---|
89 97 | Erreur médiane (MdAPE) | **11,0 %** | 14,0 % | — |
90 −| À ±20 % du prix réel | 72,1 % | 66,7 % | — |
91 −| Ratio médian | 0,995 | 0,961 | 0,90–1,10 ✅ |
98 +| À ±20 % du prix réel | **72,1 %** | 66,7 % | — |
99 +| Ratio médian | **0,995** | 0,961 | 0,90–1,10 ✅ |
92 100 | COD | 22,7 (condos : **11,9** ✅) | 23,7 | ≤ 15–20 |
93 101 | PRD | 1,092 | 1,075 | 0,98–1,03 |
94 −| R² (log) | 0,789 | 0,743 | — |
102 +| R² (log) | **0,789** | 0,743 | — |
95 103
96 104 ## Architecture
97 105
@@ -120,36 +128,37 @@ Validation sur **102 943 ventes jamais vues** du modèle (holdout aléatoire) et
120 128
121 129 ### Stack
122 130
123 −- **Frontend / API** : Next.js 16 (App Router), TypeScript strict, Tailwind CSS 4
124 −- **Base** : SQLite (better-sqlite3) — 3,75 M unités, FTS5, index spatiaux *(non incluse dans ce dépôt)*
125 −- **Cartes** : [`@groupe-ka/ka-maps`](https://github.com/spboucher-ai) (framework carto partagé du Groupe KA, moteur Mapbox GL, style Standard 3D)
126 −- **Agent IA** : SDK Anthropic (Claude Haiku 4.5, streaming SSE, boucle agentique manuelle, prompt caching)
127 −- **Rapports** : pdfkit, 100 % vectoriels, polices embarquées (Space Grotesk / Inter / JetBrains Mono)
128 −- **Modèle** (pipeline externe) : LightGBM, scikit-learn, pandas, pyogrio/GDAL
129 −- **Tests** : Vitest (moteur d'estimation) + Playwright (mobile, captures d'écran)
131 +- **Frontend / API** : **Next.js 16** (App Router), **TypeScript strict**, **Tailwind CSS 4**
132 +- **Base** : **SQLite** (better-sqlite3) — **3,75 M unités**, **FTS5**, index spatiaux *(non incluse dans ce dépôt)*
133 +- **Cartes** : **`@groupe-ka/ka-maps`** (framework carto partagé du Groupe KA, moteur **Mapbox GL**, style Standard 3D)
134 +- **Agent IA** : **SDK Anthropic** (Claude Haiku 4.5, streaming SSE, boucle agentique manuelle, prompt caching)
135 +- **Rapports** : **pdfkit**, 100 % vectoriels, polices embarquées (Space Grotesk / Inter / JetBrains Mono)
136 +- **Modèle** (pipeline externe) : **LightGBM**, scikit-learn, pandas, pyogrio/GDAL
137 +- **Tests** : **Vitest** (moteur d'estimation) + **Playwright** (mobile, captures d'écran)
138 +- **Prod** : **PM2** + **ngrok** sur le nœud **M3U96a** du cluster MacLustr
130 139
131 140 ## Le moteur d'estimation (`src/lib/engine.ts`)
132 141
133 −1. **Comparables** : ventes candidates dans un rayon adaptatif (2,2 → 28 km), filtrées par type et superficie (±20 → ±40 %) ;
142 +1. **Comparables** : ventes candidates dans un rayon adaptatif (**2,2 → 28 km**), filtrées par type et superficie (±20 → ±40 %) ;
134 143 2. **Ajustements affichés en dollars** : conditions de marché (indice mensuel $/m² lissé 3 mois), superficie (50 % du $/m² du comparable, plafonné ±25 %), âge (0,5 %/an, plafonné ±10 %) ;
135 144 3. **Pondération gaussienne** : distance (σ 1 500 m), récence (σ 24 mois), similarité de superficie (σ 25 %) ;
136 −4. **Fusion** : 65 % modèle hédonique pré-calculé + 35 % médiane pondérée des comparables ;
137 −5. **Confiance** : nombre de comparables, dispersion, largeur de fourchette → A/B/C/D.
145 +4. **Fusion** : **65 % modèle hédonique** pré-calculé + **35 % médiane pondérée des comparables** ;
146 +5. **Confiance** : nombre de comparables, dispersion, largeur de fourchette → **A/B/C/D**.
138 147
139 −Chaque fiche montre le calcul en entier : les comparables retenus, chaque ajustement, les poids, la réconciliation. Le rapport PDF « professionnel » reprend la grille d'ajustement au format des évaluateurs (avec les encadrés « ceci n'est pas un rapport OEAQ »).
148 +Chaque fiche montre le calcul **en entier** : les comparables retenus, chaque ajustement, les poids, la réconciliation. Le rapport PDF « professionnel » reprend la grille d'ajustement au format des évaluateurs (avec les encadrés « ceci n'est pas un rapport OEAQ »).
140 149
141 150 ## Ka — l'agent IA
142 151
143 −Page [`/ka`](https://www.vrai-prix.com/ka) : un agent conversationnel branché en direct sur le registre et le moteur. Boucle agentique manuelle (12 tours max) avec **12 outils serveur** : `chercher_propriete` (FTS avec relaxation progressive), `evaluer_propriete`, `dossier_complet` (évaluation + marché + tendance + comparables + synthèse en un appel), `comparables_detailles`, `indice_marche`, `stats_municipalite`, `stats_provinciales`, `evaluer_parc`, `comparer_proprietes`, `estimation_manuelle`, `chercher_proprietes_secteur`, `liens_rapports` (réfs persistantes anti-hallucination pour les PDF). Streaming SSE, tableaux HTML dans le fil, clarification quand l'adresse est ambiguë.
152 +Page [`/ka`](https://www.vrai-prix.com/ka) : un agent conversationnel branché **en direct** sur le registre et le moteur. Boucle agentique manuelle (**12 tours max**) avec **12 outils serveur** : `chercher_propriete` (FTS avec relaxation progressive), `evaluer_propriete`, `dossier_complet` (évaluation + marché + tendance + comparables + synthèse en un appel), `comparables_detailles`, `indice_marche`, `stats_municipalite`, `stats_provinciales`, `evaluer_parc`, `comparer_proprietes`, `estimation_manuelle`, `chercher_proprietes_secteur`, `liens_rapports` (réfs persistantes anti-hallucination pour les PDF). **Streaming SSE**, tableaux HTML dans le fil, clarification quand l'adresse est ambiguë.
144 153
145 154 ## SEO programmatique — 3,76 M d'URLs indexables
146 155
147 156 Tout le contenu est servi **en HTML complet dès la première requête** (SSR), avec un maillage interne crawlable :
148 157
149 −- **`/municipalites`** → index A-Z des 1 097 municipalités ;
150 −- **`/municipalite/[slug]`** (1 097 pages) → médiane 2026, valeur totale, croissance 2021→2026, médianes par type, 24 fiches liées, municipalités voisines ;
151 −- **`/municipalite/[slug]/[type]`** (~5 900 pages) → `maison`, `plex`, `chalet`, `condo`, `terrain`, `maison-mobile`, `autre` ;
152 −- **`/estimation/[id]`** (3,75 M fiches) → title et meta description **uniques par fiche** (adresse + estimation), canonical, JSON-LD `SingleFamilyResidence`/`Residence`/`Place` + `BreadcrumbList` ;
158 +- **`/municipalites`** → index A-Z des **1 097 municipalités** ;
159 +- **`/municipalite/[slug]`** (**1 097 pages**) → médiane 2026, valeur totale, croissance 2021→2026, médianes par type, 24 fiches liées, municipalités voisines ;
160 +- **`/municipalite/[slug]/[type]`** (**~5 900 pages**) → `maison`, `plex`, `chalet`, `condo`, `terrain`, `maison-mobile`, `autre` ;
161 +- **`/estimation/[id]`** (**3,75 M fiches**) → title et meta description **uniques par fiche** (adresse + estimation), canonical, JSON-LD `SingleFamilyResidence`/`Residence`/`Place` + `BreadcrumbList` ;
153 162 - **Sitemaps** : `/sitemap-index.xml` → `/sitemap.xml` (7 043 pages) + `/estimation/sitemap/0-83.xml` (45 000 fiches chacun, générés à la volée depuis SQLite par plages de rowid) ;
154 163 - JSON-LD `Organization` + `WebSite` global, `robots.txt` propre, `noindex` sur les pages privées/paramétriques.
155 164
@@ -201,10 +210,11 @@ src/
201 210 | `GET /api/report/pro?id=` | Rapport détaillé format professionnel (6 pages) |
202 211 | `GET /api/report/portfolio?ids=` | Rapport de parc consolidé |
203 212 | `GET /api/report/stats` | Rapport statistique provincial |
213 +| `GET /api/stats` · `/api/stats/dashboard` | Agrégats provinciaux (métriques live du hub Groupe KA) |
204 214 | `GET /api/auth/ka/login` · `/callback` | SSO KA ID (hub groupe-ka.com) |
205 215 | `GET /api/auth/me` · `POST /api/auth/logout` | Session (cookie signé, sans table users) |
206 216
207 −## Démarrage
217 +## Démarrage local
208 218
209 219 ```bash
210 220 npm install
@@ -228,12 +238,54 @@ npm run build && npm run start
228 238
229 239 > **Captures d'écran** : `node scripts/screenshots.mjs` les régénère depuis la prod (Playwright).
230 240
241 +## Déploiement
242 +
243 +L'app tourne en production sur le cluster **MacLustr** :
244 +
245 +| | |
246 +|---|---|
247 +| **Nœud** | **M3U96a** (Mac Studio M3 Ultra, 32 cœurs / 96 Go) — `~/apps/vrai-prix` |
248 +| **Port** | **8090** (`next start -H 0.0.0.0 -p 8090`) |
249 +| **Domaine** | **[www.vrai-prix.com](https://www.vrai-prix.com)** (tunnel ngrok) |
250 +| **Processus PM2** | **`vrai-prix`** (app Next.js) + **`vrai-prix-ngrok`** (tunnel) |
251 +
252 +```bash
253 +# sur M3U96a, après un changement :
254 +cd ~/apps/vrai-prix
255 +npm run build
256 +pm2 restart vrai-prix
257 +pm2 logs vrai-prix --lines 30 # vérifier le démarrage
258 +```
259 +
260 +## Développement remote-first
261 +
262 +⚠️ **La source de vérité est le repo git sur le nœud M3U96a** (`~/apps/vrai-prix`), **pas** une copie laptop. Toute modification se fait sur le nœud via SSH : édition, `npm run build`, `pm2 restart vrai-prix`, puis commit + push **sur le nœud**.
263 +
264 +- Remote **`origin` = spbgit** (git perso, git.spboucher.ai) — sur **M3U96a** le remote pointe directement sur le chemin local **`/Users/simon-pierreboucher/srv/git/vrai-prix.git`** (bare repo) ;
265 +- Remote secondaire `github` → `github.com/spboucher-ai/vrai-prix` ;
266 +- Référence complète du workflow : `~/Desktop/cluster-skill/KA-REMOTE-DEV.md`.
267 +
268 +```bash
269 +ssh M3U96a
270 +cd ~/apps/vrai-prix
271 +# … modifier, builder, redémarrer …
272 +git add <fichiers> && git commit -m "…" && git push origin main
273 +```
274 +
231 275 ## Design
232 276
233 277 Identité « éditorial sharp » : papier grainé `#f5f3ee`, encre `#141814`, **accent rouge vif `#ff5148`**, bordeaux `#9e2a25` — bordures encre 1,5 px, ombres décalées, display uppercase (Space Grotesk), micro-étiquettes mono (JetBrains Mono), ticker marquee, visualisations SVG data-driven (façade du bâtiment, terrain à l'échelle, jauge de confiance, sparklines) — **zéro image bitmap dans l'app**.
234 278
235 279 ## Auteur
236 280
237 −**Simon-Pierre Boucher** — [contact@spboucher.ai](mailto:contact@spboucher.ai) · Groupe KA
281 +**Simon-Pierre Boucher** — [contact@spboucher.ai](mailto:contact@spboucher.ai)
238 282
239 283 *Estimations statistiques à titre indicatif — ne remplacent pas une évaluation par un évaluateur agréé (OEAQ). Voir [conditions](https://www.vrai-prix.com/conditions) et [méthodologie complète](https://www.vrai-prix.com/methodologie).*
284 +
285 +---
286 +
287 +<div align="center">
288 +
289 +Un service **Groupe Ka**
290 +
291 +</div>
added docs/screenshot.png +0 −0

Binary file not shown.