SPB Git forge

spb/immo-ka

Public

Immo-Ka — agrégateur des propriétés à vendre au Québec (73 connecteurs, ~40 000 annonces, React+FastAPI)

112commits 1branches 0releases
125.4 MBsize
maindefault branch
13 days agolast push
Python 47.5% HTML 27.9% TypeScript 15.5% CSS 7.2% JavaScript 2%

docs: refonte du README (pastilles + captures d écran à jour)

Simon-Pierre Boucher committed 1 mo ago (Aug 24, 2026) parent f0ecbc9

3 changed files +85 −235

modified README.md +85 −235
@@ -1,271 +1,121 @@
1 −<div align="center">
2 −
3 1 # Immo·Ka
4 2
5 −### **Toutes les propriétés à vendre du Québec. Un seul endroit.**
6 −
7 −**[www.immo-ka.com](https://www.immo-ka.com)**
8 −
9 −![Aperçu de Immo-Ka](docs/screenshot.png)
10 −
11 −![Python](https://img.shields.io/badge/Python-3.14-141814?style=for-the-badge&logo=python&logoColor=c7f230)
12 −![FastAPI](https://img.shields.io/badge/FastAPI-API_+_SSR-141814?style=for-the-badge&logo=fastapi&logoColor=c7f230)
13 −![React](https://img.shields.io/badge/React_18-Vite_+_TS-141814?style=for-the-badge&logo=react&logoColor=c7f230)
14 −![Ka Maps](https://img.shields.io/badge/Ka_Maps-Mapbox_3D-141814?style=for-the-badge&logo=mapbox&logoColor=c7f230)
15 −![SQLite](https://img.shields.io/badge/SQLite-WAL-141814?style=for-the-badge&logo=sqlite&logoColor=c7f230)
16 −
17 −![Propriétés](https://img.shields.io/badge/propri%C3%A9t%C3%A9s_actives-57_900%2B-e23744?style=flat-square)
18 −![Connecteurs](https://img.shields.io/badge/connecteurs-95-e23744?style=flat-square)
19 −![Bannières](https://img.shields.io/badge/banni%C3%A8res-22-e23744?style=flat-square)
20 −![Sous-agences](https://img.shields.io/badge/sous--agences-159-e23744?style=flat-square)
21 −![Villes](https://img.shields.io/badge/villes-2_825-e23744?style=flat-square)
22 −![MàJ](https://img.shields.io/badge/mise_%C3%A0_jour-automatique-e23744?style=flat-square)
23 −![SEO](https://img.shields.io/badge/SEO-rendu_serveur_+_sitemaps-e23744?style=flat-square)
24 −
25 −</div>
26 −
27 −---
28 −
29 −## Description
3 +**Toutes les propriétés à vendre du Québec — maisons, condos, plex et terrains — réunies au même endroit, toujours à jour.**
30 4
31 −**Immo-Ka** est un **agrégateur immobilier indépendant** : toutes les **maisons, condos, plex et terrains à vendre au Québec**, réunis au même endroit. Chercher une propriété au Québec, c'est normalement jongler entre les sites de RE/MAX, Royal LePage, Sutton, Via Capitale, Century 21 et des dizaines d'autres bannières — chacun avec sa navigation, ses filtres, son format. **Immo-Ka retourne le problème** : **un connecteur dédié par agence de courtage** visite chaque source, **normalise chaque propriété vers un schéma unique** (`PropertyListing`), **déduplique par numéro Centris**, et détecte les changements en continu — avec **lien direct vers l'annonce originale**. **Toujours à jour, automatiquement.**
5 +[![Site](https://img.shields.io/website?url=https%3A%2F%2Fwww.immo-ka.com&style=flat-square&label=www.immo-ka.com)](https://www.immo-ka.com)
6 +![Nœud](https://img.shields.io/badge/n%C5%93ud-M4M64a-1f6feb?style=flat-square)
7 +![Port](https://img.shields.io/badge/port-8096-555?style=flat-square)
8 +![PM2](https://img.shields.io/badge/process-PM2-2b037a?style=flat-square)
9 +![Python](https://img.shields.io/badge/Python-FastAPI-3776ab?style=flat-square&logo=python&logoColor=white)
10 +![React](https://img.shields.io/badge/React_18-Vite_%2B_TS-61dafb?style=flat-square&logo=react&logoColor=black)
11 +![SQLite](https://img.shields.io/badge/SQLite-WAL-003b57?style=flat-square&logo=sqlite&logoColor=white)
12 +![Ka Maps](https://img.shields.io/badge/Ka_Maps-Mapbox_GL_3D-4264fb?style=flat-square)
13 +![Groupe KA](https://img.shields.io/badge/Groupe-KA-b7f000?style=flat-square)
32 14
33 −> Les sites d'agences n'offrent pas de webhooks. Immo-Ka reproduit l'équivalent :
34 −> **synchronisation périodique + hash de contenu** → ajouts, **changements de prix** et
35 −> retraits (propriété vendue) détectés automatiquement, avec **délai de grâce** contre
36 −> les ratés ponctuels et **détection de dérive** par source.
15 +**Immo-Ka** est un **agrégateur immobilier indépendant** pour la province de Québec. Chercher une propriété, c'est normalement jongler entre les sites de RE/MAX, Royal LePage, Sutton, Via Capitale, Century 21, DuProprio et des dizaines d'autres bannières — chacun avec sa navigation, ses filtres et son format. Immo-Ka retourne le problème : **un connecteur dédié par source** (105 connecteurs enregistrés — flux centraux de bannières, sous-agences en plan B, plateformes sans courtier) visite chaque site, **normalise chaque annonce vers un schéma unique** (`PropertyListing`), **déduplique par numéro Centris** et détecte les changements en continu, avec lien direct vers l'annonce originale.
37 16
38 −C'est le pendant « à vendre » de [Lou-Ka](https://www.lou-ka.com) (location) — même architecture, schéma adapté à la vente. Immo-Ka fait partie de l'univers **Groupe KA** (Lou-Ka, Auto-Ka, Fabri-Ka, Food-Ka, Ora-Ka, Vrai-Prix…) : compte **KA ID** unique et **favoris partagés** entre toutes les plateformes.
17 +Les sites d'agences n'offrent pas de webhooks : Immo-Ka en reproduit l'équivalent par **synchronisation périodique + hash de contenu** — ajouts, changements de prix et retraits (propriété vendue) détectés automatiquement, avec délai de grâce contre les ratés ponctuels. Couverture (métriques de l'agrégat) : **57 900+ propriétés actives**, **22 bannières**, **159 sous-agences**, **2 825 villes**. C'est le pendant « à vendre » de [Lou-Ka](https://www.lou-ka.com) (location), branché sur le moteur d'estimation [Vrai-Prix](https://www.vrai-prix.com) et sur le compte unique **KA ID** du Groupe KA.
39 18
40 −**Fiches enrichies** : galerie photo complète · caractéristiques Centris · pièces & dimensions · **estimation de valeur Vrai-Prix** (fourchette + confiance + analyse) · **rôle d'évaluation foncière** (valeur au rôle terrain/bâtiment, année de construction et superficies officielles — jointes localement depuis les 3,7 M d'unités de la base Vrai-Prix) · **jours sur le marché** · **statistiques de quartier** (recensement StatCan, proximité, îlot de chaleur) · **carte 3D Ka Maps** · historique de prix · favoris **KA ID** · **référencement programmatique** (une page indexable par ville et par type, HTML complet rendu côté serveur).
19 +## Captures d'écran
41 20
42 −## Aperçu
43 −
44 −| Accueil — moteur de recherche | Grille de résultats |
45 −|---|---|
46 −| ![Accueil Immo-Ka](docs/screenshots/home.png) | ![Grille de propriétés](docs/screenshots/grille.png) |
47 −
48 −| Carte Ka Maps — grappes de prix en direct | Fiche — galerie, Vrai-Prix, courtier |
49 −|---|---|
50 −| ![Carte interactive](docs/screenshots/carte.png) | ![Fiche propriété](docs/screenshots/listing.png) |
51 −
52 −| Fiche — pièces, emplacement, quartier | Page ville indexable (`/a-vendre/quebec`) |
53 −|---|---|
54 −| ![Quartier et emplacement](docs/screenshots/listing-quartier.png) | ![Page ville](docs/screenshots/ville.png) |
55 −
56 −| Statistiques du marché agrégé | Agences — 22 bannières, 159 sous-agences |
57 −|---|---|
58 −| ![Statistiques](docs/screenshots/stats.png) | ![Agences](docs/screenshots/agences.png) |
59 −
60 −<div align="center">
61 −
62 −| Mobile |
63 −|---|
64 −| <img src="docs/screenshots/mobile.png" alt="Version mobile" width="360" /> |
65 −
66 −</div>
21 +<p align="center">
22 + <img src="docs/screenshots/immo-ka-desktop.png" width="640" alt="Accueil — desktop">
23 + <img src="docs/screenshots/immo-ka-mobile.png" width="200" alt="Accueil — mobile">
24 +</p>
67 25
68 26 ## Fonctionnalités
69 27
70 −| | Fonctionnalité | Détails |
71 −|---|---|---|
72 −| 🔎 | **Recherche & filtres** | texte libre (adresse, ville, n° MLS), ville + secteur, type, agence, prix, chambres, salles de bain, superficie ; tri prix/récence ; **état dans l'URL** (partageable) |
73 −| 🗺 | **Carte Ka Maps** | framework carto maison du Groupe KA (moteur **Mapbox GL 3D**) : grappes de prix, marqueurs colorés selon l'écart au Vrai-Prix, « rechercher en déplaçant la carte », popups éditoriales, bascule 2D/3D |
74 −| 🏠 | **Fiche complète** | galerie + lightbox (jusqu'à **40+ photos 1600 px**), fiche technique à rangées, tableau des caractéristiques Centris, pièces & dimensions par étage, inclusions, description, mini-carte d'emplacement (5/15 min à pied) |
75 −| 💰 | **Vrai-Prix** | **estimation de valeur marchande** (modèle hédonique + comparables du moteur [Vrai-Prix](https://github.com/spboucher-ai/vrai-prix)) : jauge P10–P90, marqueurs estimation/prix demandé, verdict (sur-évalué / aligné / sous l'estimation), lien vers l'analyse détaillée |
76 −| 📈 | **Historique de prix** | baisses et hausses du prix demandé horodatées (table `price_log`) |
77 −| 🏘 | **Quartier** | aire de diffusion du recensement (± 500 habitants) : revenu médian, loyer moyen, âge médian, % locataires, % français, proximité épiceries/parcs/soins (**StatCan**), îlot de chaleur (**INSPQ**) |
78 −| 📊 | **Stats** | volumes par type et par agence, prix moyens, **écart prix demandé vs estimation Vrai-Prix par bannière** (médiane, P25–P75, % sur-évalués) + **rapport PDF Groupe-KA** |
79 −| 🏢 | **Agences** | registre éclaté par bannière → sous-agence (bureau), avec compte d'annonces **dédupliqué** |
80 −| ♥ | **Favoris & KA ID** | connexion « Se connecter avec **KA ID** » (SSO du hub groupe-ka.com, JWT HS256), favoris stockés au hub — le même cœur ♥ suit l'utilisateur sur **toutes les plateformes Ka** |
81 −| 💬 | **KA Agent** | bulle de chat Groupe KA intégrée (widget `ka-agent.js`) |
82 −| 🔍 | **SEO programmatique** | HTML complet **rendu serveur** sur chaque route, une page indexable par ville / type / ville+type, sitemaps, données structurées — voir section dédiée |
83 −
84 −## Couverture (métriques en direct)
85 −
86 −**57 900+ propriétés actives** · **26 sources** avec annonces · **22 bannières** · **159 sous-agences** · **2 825 villes** · prix moyen ≈ **683 000 $**
87 −
88 −| Source | Annonces | Méthode technique |
89 −|---|---:|---|
90 −| RE/MAX Québec | ~21 300 | Meilisearch public + sharding FSA postal + page détail enrichie |
91 −| DuProprio | ~7 300 | API interne JSON (sans courtier) |
92 −| Kijiji Québec | ~7 000 | flux annonces immobilier à vendre (filtre anti-prix-bidon < 5 000 $) |
93 −| LesPAC Québec | ~4 100 | listing + fiche détail (adresse civique, galerie basephoto) |
94 −| Via Capitale | ~4 100 | portail central (Firecrawl stealth, pagination `criteresJson`) |
95 −| Groupe Sutton | ~3 100 | sitemap `sitemap_inscription.cfm` → n° Centris |
96 −| Proprio Direct | ~2 500 | API interne JSON |
97 −| Century 21 Québec | ~1 600 | sous-agences source.immo (« All Quebec ») |
98 −| Domicilia (réseau Humania) | ~1 400 | API du réseau |
99 −| Ubee · Vendirect · Engel & Völkers | ~3 400 | plateformes + property-sitemap → JSON-LD |
100 −| Royal LePage | ~900 | recherche par ville filtrée QC + sharding + dédup MLS |
101 −| Barnes · Profusion (Christie's) · KW · M Immobilier · Sotheby's · L'Expert PM | ~1 200 | Algolia, WordPress JSON-LD, HTML SSR, Centris |
102 −| Sous-agences RE/MAX · Via Capitale · Century 21 | *backup* | 60+ connecteurs `*_ag_*` auto-générés, dédup par n° Centris |
103 −
104 −Les sous-agences servent de plan B : si le flux central d'une bannière tombe, elles prennent le relais **sans double-comptage** (déduplication pré-calculée par numéro Centris, colonne `dup_hidden`).
105 −
106 −## Stack technique
107 −
108 −- **Backend** : **Python 3.14** · **FastAPI** (API JSON + rendu SEO serveur + service du frontend) · **SQLite en mode WAL** (accès concurrents lecture/écriture)
109 −- **Frontend** : **React 18 + Vite + TypeScript** · react-router · design system **ka-ui** (badge + footer communs du Groupe KA)
110 −- **Cartographie** : **Ka Maps** — framework carto partagé du Groupe KA sur moteur **Mapbox GL 3D**
111 −- **Ingestion** : **92 connecteurs** (API JSON internes — Meilisearch, Algolia, source.immo, wp-json —, JSON-LD, sitemaps, **Firecrawl** pour les sites SPA/anti-bot)
112 −- **Enrichissement** : géocodage avec cache, POI de proximité, quartier **StatCan/INSPQ**, estimations **Vrai-Prix** + **rôle d'évaluation** (jointure d'adresse locale : valeurs officielles, année, superficies — en repli des colonnes quand la source ne les donne pas)
113 −- **Auth** : **SSO KA ID** (JWT HS256 du hub groupe-ka.com, stdlib pure)
114 −- **Exploitation** : **PM2** + tunnel **ngrok**
115 −
116 −### Architecture
28 +- **Recherche & filtres** — texte libre (adresse, ville, n° MLS), ville + secteur, type, agence, prix, chambres, salles de bain, superficie ; tri par prix ou récence ; état encodé dans l'URL (partageable).
29 +- **Carte Ka Maps** — framework carto maison du Groupe KA (moteur Mapbox GL 3D) : grappes de prix, marqueurs colorés selon l'écart au Vrai-Prix, « rechercher en déplaçant la carte », bascule 2D/3D.
30 +- **Fiche complète** — galerie + lightbox, caractéristiques Centris, pièces & dimensions par étage, inclusions, description, mini-carte d'emplacement.
31 +- **Estimation Vrai-Prix** — valeur marchande estimée (modèle hédonique + comparables) : jauge P10–P90, verdict sur-évalué / aligné / sous l'estimation.
32 +- **Rôle d'évaluation foncière** — valeur au rôle terrain/bâtiment, année de construction et superficies officielles, jointes localement depuis la base Vrai-Prix.
33 +- **Historique de prix** — baisses et hausses du prix demandé horodatées (table `price_log`) + jours sur le marché.
34 +- **Quartier** — aire de diffusion du recensement : revenu médian, loyer moyen, % locataires, proximité épiceries/parcs/soins (StatCan), îlot de chaleur (INSPQ).
35 +- **Couches territoriales** — registre des loyers, zones inondables (BDZI), qualité de l'air, prix de l'essence, commerces et transport en commun, **estimation Hydro-Québec précalculée** lors de la sync.
36 +- **Stats** — tableau de bord `/stats` : volumes par type et bannière, écart prix demandé vs estimation Vrai-Prix, panneaux territoire + rapport PDF Groupe-KA.
37 +- **Agences** — registre par bannière → sous-agence, comptes d'annonces dédupliqués.
38 +- **KA ID & favoris** — SSO du hub groupe-ka.com (JWT HS256), favoris partagés sur toutes les plateformes Ka ; widget de chat **KA Agent** intégré.
39 +- **SEO programmatique** — HTML complet rendu côté serveur, une page indexable par ville / type / ville+type, sitemaps et données structurées.
40 +
41 +## Architecture
42 +
43 +| Composant | Rôle |
44 +|---|---|
45 +| `immoka/connectors/` | 105 connecteurs enregistrés (API JSON internes — Meilisearch, Algolia, source.immo, wp-json —, JSON-LD, sitemaps, Firecrawl pour les sites SPA/anti-bot) |
46 +| `immoka/ingest.py` + `normalize.py` + `schema.py` | boucle de sync : normalisation vers `PropertyListing`, upsert par hash de contenu, dédup Centris (`dup_hidden`), délai de grâce sur les retraits |
47 +| `immoka/web.py` + `seo.py` | FastAPI : API JSON, rendu SEO serveur, service du build frontend |
48 +| Enrichissement | `geocode.py`, `poi.py`, `quartier.py`, `vraiprix.py`/`vraiprix_local.py`, `hydro.py`, `inondation.py`, `air.py`, `gaz.py`, `commerces.py`, `quality.py`/`imgaudit.py` (couche qualité + quarantaine) |
49 +| Base de données | **SQLite en mode WAL** : `data/immoka.db` (annonces) + bases annexes (`quartier.db`, `vraiprix.db`, `hydro.db`, `air.db`, `gaz.db`, `commerces.db`, `inondation.db`, `transit.db`, `rdl.db`) |
50 +| Frontend | React 18 + Vite + TypeScript, react-router, design system ka-ui, cartes `@groupe-ka/ka-maps` (Mapbox GL 3.28) |
117 51
118 −```mermaid
119 −flowchart LR
120 − subgraph Sources["Agences & plateformes du Québec"]
121 − S1["RE/MAX · Sutton · Via Capitale<br/>Century 21 · Royal LePage · Proprio Direct<br/>DuProprio · Kijiji · LesPAC · E&V · Barnes<br/>… 92 connecteurs"]
122 − end
123 − subgraph ImmoKa["Immo-Ka"]
124 − C["Connecteurs<br/><i>1 adaptateur / source</i>"] --> N["Normalisation<br/><i>schéma PropertyListing</i>"]
125 − N --> D[("SQLite WAL<br/>hash + diff + dédup Centris<br/>+ géocodage + POI + quartier")]
126 − D --> A["API FastAPI<br/>listings · facets · geojson · stats"]
127 − D --> SEO["Rendu SEO serveur<br/><i>immoka/seo.py</i><br/>HTML + JSON-LD + sitemaps"]
128 − A --> F["React 18 + Vite + Ka Maps<br/>liste · carte · fiche · stats"]
129 − SEO --> G["🕷 Moteurs de recherche"]
130 − end
131 − W["⏱ Watcher (PM2)"] -.-> C
132 − S1 --> C
133 − F --> U["🔑 Acheteur"]
134 − H["🌐 Hub groupe-ka.com<br/>KA ID · favoris"] <--> F
135 −```
52 +**Processus PM2 (production)** :
136 53
137 −| Couche | Rôle | Fichiers |
54 +| Processus | Commande | Rôle |
138 55 |---|---|---|
139 −| **Connecteurs** | 1 module par source : API JSON interne (Meilisearch, Algolia, source.immo, wp-json), JSON-LD, sitemap, ou Firecrawl pour les sites SPA/anti-bot ; registres auto-générateurs pour les bannières à sous-agences | `immoka/connectors/*.py` |
140 −| **Schéma** | `PropertyListing` : adresse, secteur, ville, région, type canonique, prix, chambres/SdB, superficies, année, MLS, courtier, pièces (dimensions), **toutes les photos**, caractéristiques structurées | `immoka/schema.py`, `immoka/normalize.py` |
141 −| **Diff engine** | upsert par hash de contenu, délai de grâce (2 syncs), détection de dérive par source, historique de prix, **déduplication inter-agences par n° Centris** + **dédup inter-sources par adresse** (même adresse normalisée + type + prix ±1 %, garde-fou apt/unité) | `immoka/db.py`, `immoka/ingest.py` |
142 −| **Enrichissement** | géocodage avec cache, commodités de proximité (POI), statistiques de quartier StatCan/INSPQ, estimations Vrai-Prix + rôle d'évaluation (year_built/lot_sqft en repli, provenance `details.*_source`) | `immoka/geocode.py`, `immoka/poi.py`, `immoka/quartier.py`, `immoka/vraiprix*.py` |
143 −| **API** | filtres ville/secteur/région/type/agence/prix/chambres/superficie, facettes, stats, GeoJSON borné par bbox pour la carte | `immoka/web.py` |
144 −| **SEO** | rendu HTML serveur par route, pages programmatiques, sitemaps, robots.txt, 301/410/404 | `immoka/seo.py` |
145 −| **Auth & favoris** | SSO KA ID (JWT HS256 du hub, stdlib pure), profil hub, favoris centraux | `immoka/auth.py`, `immoka/hubprofile.py`, `immoka/hubfav.py`, `immoka/favorites.py` |
146 −| **Frontend** | React 18 + Vite + TS + react-router + Ka Maps : accueil (liste/carte), fiche, pages ville/type, Stats, Agences, profil KA | `frontend/` |
147 −
148 −## Référencement (SEO)
149 −
150 −Le SPA React est doublé d'un **rendu HTML côté serveur** (`immoka/seo.py`, branché sur le catch-all FastAPI) : chaque URL livre son contenu complet dès la première requête, **sans exécution JavaScript** — React prend le relais au montage.
151 −
152 −- **Chaque page** a un `<title>`, une meta description, un canonical et des balises `og:`/`twitter:` uniques, plus le contenu réel (H1, stats, liste d'annonces avec liens) directement dans le HTML initial.
153 −- **Pages programmatiques** alignées sur les recherches réelles : `/a-vendre/{ville}` (**1 589 pages**), `/a-vendre/{ville}/{type}` (**2 702 pages**), `/type/{type}` (21 pages) — statistiques (nombre, prix médian/moyen), liste paginée (48/page), maillage interne (types de la ville, villes voisines), seuil de qualité (≥ 3 annonces).
154 −- **Fiches** : URL stable et lisible `/propriete/{uid}/{slug-adresse-ville}` (301 depuis l'uid nu), JSON-LD `RealEstateListing` + `Offer` (prix CAD, adresse, géolocalisation, photos) + `BreadcrumbList`.
155 −- **Cycle de vie propre** : propriété retirée/vendue → **410 Gone** avec liens de sortie ; uid inconnu → **404** réel. Fini les soft-404.
156 −- **`sitemap.xml`** : index + sous-sitemaps (**57 900+ fiches**, villes, villes-types, types, pages) avec `lastmod`, régénérés automatiquement. **`robots.txt`** propre.
157 −- Le slug est calculé par le **même algorithme** en Python (`seo.py`) et en TypeScript (`api.ts`) — les liens du SPA et du serveur coïncident.
158 −
159 −## API
56 +| `immo-ka-web` | `.venv/bin/python run.py serve 8096` | API + frontend + SSR SEO |
57 +| `immo-ka-sync` | `.venv/bin/python run.py watch 240` | resynchronisation des sources aux 4 h |
58 +| `immo-ka-ngrok` | `ngrok http --url=www.immo-ka.com 8096` | tunnel vers le domaine public |
160 59
161 −Toutes les réponses sont en **JSON**, compressées (gzip), CORS ouvert.
60 +## Structure du repo
162 61
163 −| Endpoint | Description |
62 +| Répertoire | Contenu |
164 63 |---|---|
165 −| `GET /api/listings` | recherche paginée — filtres `city`, `sector`, `region`, `property_type`, `source`, `price_min/max`, `bedrooms_min`, `bathrooms_min`, `area_min`, `q`, `sort`, `limit`, `offset` |
166 −| `GET /api/listings/{uid}` | fiche complète : photos, caractéristiques, pièces, historique de prix, `days_on_market` (+ `details.listed_at` si la source la donne), POI, quartier, Vrai-Prix + rôle d'évaluation |
167 −| `GET /api/listings.geojson` | marqueurs de carte allégés, bornés par `bbox=ouest,sud,est,nord` |
168 −| `GET /api/facets` | valeurs distinctes (villes, secteurs, types, sources) pour les filtres |
169 −| `GET /api/sources` · `GET /api/agencies` | registre des sources et arbre bannière → sous-agences |
170 −| `GET /api/stats` | totaux, prix moyens, écarts Vrai-Prix par bannière, journal des syncs |
171 −| `GET /api/seo/resolve` | slug de page programmatique → valeurs exactes |
172 −| `GET /sitemap.xml` · `/sitemaps/*.xml` · `/robots.txt` | référencement |
173 −| `POST /api/sync` | déclenche une synchronisation (toutes les sources ou une seule) |
64 +| `immoka/` | paquet Python : connecteurs, ingestion, API/SSR, enrichissements, stats |
65 +| `frontend/` | SPA React 18 + Vite + TypeScript (pages, composants, ka-maps, ka-ui) |
66 +| `data/` | bases SQLite (immoka.db + bases annexes) et registres d'agences JSON |
67 +| `docs/` | captures d'écran, docs des connecteurs, rapports de validation |
68 +| `scripts/` | outillage (génération des docs connecteurs, rafraîchissement Via Capitale, validation du rendu) |
69 +| `run.py` / `requirements.txt` | point d'entrée CLI (`sync`, `watch`, `serve`, `list`, `geocode`, `poi`, `quartier`, …) et dépendances backend |
174 70
175 −## Structure du projet
71 +## Développement (remote-first)
176 72
177 −```
178 −immo-ka/
179 −├── run.py # point d'entrée : list · sync · serve · watch
180 −├── immoka/
181 −│ ├── web.py # API FastAPI + service du frontend + catch-all SEO
182 −│ ├── seo.py # rendu HTML serveur, sitemaps, robots, slugs
183 −│ ├── schema.py # PropertyListing (schéma normalisé)
184 −│ ├── normalize.py # types canoniques, extraction chambres/SdB
185 −│ ├── db.py # SQLite WAL : upsert, diff, dédup Centris, price_log
186 −│ ├── ingest.py # orchestration des syncs
187 −│ ├── geocode.py · poi.py · quartier.py # enrichissement
188 −│ ├── vraiprix.py · vraiprix_local.py # estimations de valeur
189 −│ ├── auth.py · hubprofile.py · hubfav.py · favorites.py # KA ID + favoris
190 −│ └── connectors/ # 92 connecteurs (31 modules + registres auto-générés)
191 −├── frontend/ # React 18 + Vite + TS
192 −│ └── src/
193 −│ ├── pages/ # Home · Listing · Category · Stats · Sources · Profil
194 −│ ├── components/ # ListingCard · MapView · PropertyMap · QuartierBlock · Icons
195 −│ └── kamaps/ # intégration Ka Maps (Groupe KA)
196 −├── data/
197 −│ ├── sources.json # registre des sources (50 entrées, statuts)
198 −│ └── immoka.db # SQLite (non versionnée)
199 −└── docs/screenshots/ # captures de ce README
200 −```
73 +La **source de vérité est le repo git sur le nœud M4M64a** (`~/apps/immo-ka`) — immo-ka n'a **aucune copie laptop**. Toute modification se fait sur le nœud via SSH : édition, build, redémarrage, puis commit/push depuis le nœud (agent forwarding actif).
201 74
202 −## Démarrage local
75 +- Remote `origin` = **spbgit**, le git perso ([git.spboucher.ai](https://git.spboucher.ai)) : alias SSH **`gitsrv`** configuré sur le nœud → `gitsrv:srv/git/immo-ka.git` (bare repo hébergé sur M3U96a).
203 76
204 77 ```bash
78 +ssh M4M64a
79 +cd ~/apps/immo-ka
80 +
81 +# Backend
205 82 python3 -m venv .venv && .venv/bin/pip install -r requirements.txt
206 83
207 −# frontend
84 +# Frontend
208 85 cd frontend && npm install && npm run build && cd ..
209 86
210 −# (optionnel) sites JavaScript / anti-bot
211 −echo "FIRECRAWL_API_KEY=fc-votre-cle" > .env
87 +# Ingestion et service
88 +.venv/bin/python run.py list # lister les connecteurs
89 +.venv/bin/python run.py sync # synchroniser (ou : sync <source> …)
90 +.venv/bin/python run.py serve 8096 # API + frontend
212 91
213 −.venv/bin/python run.py list # 92 connecteurs enregistrés
214 −.venv/bin/python run.py sync # toutes les agences (ou: sync remax_quebec sutton)
215 −.venv/bin/python run.py serve 8090 # API + frontend + SEO → http://localhost:8090
216 −.venv/bin/python run.py watch 180 # synchronisation en boucle (minutes)
217 −```
218 −
219 −Vérifier le rendu SEO en local :
92 +# Après un changement en prod
93 +pm2 restart immo-ka-web # (ou immo-ka-sync selon le changement)
220 94
221 −```bash
222 −curl -s localhost:8090/a-vendre/quebec | grep '<title>'
223 −curl -s localhost:8090/sitemap.xml
95 +git add <fichiers> && git commit && git push origin main
224 96 ```
225 97
226 −## Ajouter une agence
227 −
228 −1. Créer `immoka/connectors/<id>.py` : sous-classe de `BaseConnector`, définir `source_id`, implémenter `fetch() -> list[PropertyListing]`. Le registre est **auto-découvrant** — aucun fichier partagé à modifier.
229 −2. Ajouter l'entrée dans `data/sources.json`.
230 −3. Tester : `.venv/bin/python run.py sync <id>`.
231 −
232 −Pour une bannière à sous-agences (RE/MAX, Via Capitale, Century 21), un module génère un connecteur par sous-agence depuis un registre JSON — nommer les `source_id` en `<banniere>_ag_<slug>` active automatiquement la déduplication.
233 −
234 98 ## Déploiement
235 99
236 −Déployé sur le cluster **MacLustr**, nœud **M4M64a** (`~/apps/immo-ka`), **port 8096**, exposé sur **[www.immo-ka.com](https://www.immo-ka.com)** via **PM2** :
237 −
238 −| Processus PM2 | Rôle |
239 −|---|---|
240 −| **`immo-ka-web`** | API + frontend + rendu SEO (`run.py serve 8096`) |
241 −| **`immo-ka-sync`** | watcher de synchronisation (`run.py watch`) |
242 −| **`immo-ka-ngrok`** | tunnel ngrok → **www.immo-ka.com** |
243 −
244 −Base **SQLite en mode WAL** pour les accès concurrents lecture/écriture. Variables d'environnement sur le nœud (`.env`) : `KA_SSO_SECRET`, `KA_HUB_URL`, `IMMOKA_BASE_URL`, `AUTH_SECRET`, `FIRECRAWL_API_KEY`.
245 −
246 −## Développement remote-first
100 +En production sur le **nœud M4M64a** du cluster MacLustr (`~/apps/immo-ka`), servi sur le **port 8096** et exposé via un tunnel **ngrok** sur **[www.immo-ka.com](https://www.immo-ka.com)**. Trois processus PM2 : `immo-ka-web` (serveur), `immo-ka-sync` (boucle de sync aux 4 h), `immo-ka-ngrok` (tunnel). La base `data/` de prod est resynchronisée en continu — ne jamais l'écraser.
247 101
248 −⚠️ **La source de vérité est le repo git sur le nœud M4M64a** (`~/apps/immo-ka`) — **il n'existe aucune copie laptop**. Toute modification se fait **sur le nœud via SSH** : édition, build frontend, `pm2 restart immo-ka-web`, puis `git add/commit/push` **depuis le nœud**.
102 +## Écosystème Groupe KA
249 103
250 −- **Remote `origin` = spbgit** (le git perso — **git.spboucher.ai**, bare repo `~/srv/git/immo-ka.git` sur M3U96a), joignable via l'**alias SSH `gitsrv`** configuré sur le nœud. **Pas GitHub.**
251 −- Le push fonctionne grâce à l'**agent forwarding** actif pendant une session SSH depuis le laptop.
252 −- Référence complète (ports, PM2, gotchas gitsrv) : `~/Desktop/cluster-skill/KA-REMOTE-DEV.md`.
104 +- [groupe-ka.com](https://www.groupe-ka.com) — portail
105 +- [lou-ka.com](https://www.lou-ka.com) — logements à louer
106 +- [immo-ka.com](https://www.immo-ka.com) — propriétés à vendre
107 +- [vrai-prix.com](https://www.vrai-prix.com) — estimation immobilière
108 +- [auto-ka.com](https://www.auto-ka.com) — véhicules
109 +- [fabri-ka.com](https://www.fabri-ka.com) — produits québécois
110 +- [food-ka.com](https://www.food-ka.com) — épicerie/alimentation
111 +- [resto-ka.com](https://www.resto-ka.com) — restaurants
112 +- [sorti-ka.com](https://www.sorti-ka.com) — sorties et événements
113 +- [job-ka.com](https://www.job-ka.com) — emplois
114 +- [crea-ka.com](https://www.crea-ka.com) — créateurs
115 +- [trouve-ka.com](https://www.trouve-ka.com) — petites annonces
116 +- [api-ka.com](https://www.api-ka.com) — API de données
253 117
254 118 ---
255 119
256 −## Auteur
257 −
258 −**Immo-Ka est une application du [Groupe-Ka](mailto:contact@groupe-ka.com)**
259 −📧 [contact@groupe-ka.com](mailto:contact@groupe-ka.com) ·
260 −[info@groupe-ka.com](mailto:info@groupe-ka.com) (demandes d'information) ·
261 −[admin@groupe-ka.com](mailto:admin@groupe-ka.com) (retraits & renseignements personnels)
262 −
263 −Développé par **Simon-Pierre Boucher** — [contact@spboucher.ai](mailto:contact@spboucher.ai)
264 −
265 −*Agrégateur indépendant — les annonces proviennent des sites publics des agences de courtage et sont rafraîchies automatiquement ; chaque fiche renvoie vers l'annonce originale de l'agence. Conditions d'utilisation et politique de confidentialité : `/conditions` et `/confidentialite` sur [www.immo-ka.com](https://www.immo-ka.com).*
266 −
267 −<div align="center">
268 −
269 −**Un service <a href="https://www.groupe-ka.com">Groupe Ka</a>**
270 −
271 −</div>
120 +© Groupe KA — Simon-Pierre Boucher · contact@spboucher.ai
121 +Ce repo vit sur **spbgit** ([git.spboucher.ai](https://git.spboucher.ai)).
added docs/screenshots/immo-ka-desktop.png +0 −0

Binary file not shown.

added docs/screenshots/immo-ka-mobile.png +0 −0

Binary file not shown.