docs: README ultra détaillé + visite guidée en 10 captures
11 changed files +271 −30
modified
README.md
+271 −30
@@ -1,29 +1,221 @@ | ||
| 1 | 1 | # House-Ka |
| 2 | 2 | |
| 3 | −**www.house-ka.com** — Homes-for-sale aggregator for Canada **outside Québec**, | |
| 4 | −Ontario first. A Groupe KA service, sister site of | |
| 5 | −[Immo-Ka](https://www.immo-ka.com) (Québec). | |
| 3 | +**[www.house-ka.com](https://www.house-ka.com)** — *Every home for sale. One place.* | |
| 6 | 4 | |
| 7 | −House-Ka continuously aggregates homes publicly listed by Canadian real-estate | |
| 8 | −brokerages and teams whose sites run the **RealtyPress** WordPress plugin on | |
| 9 | −the **CREA DDF** feed. Each site exposes its board's full inventory; a single | |
| 10 | −generic connector (`immoka/connectors/realtypress.py`) covers them all, and | |
| 11 | −cross-site duplicates are masked by DDF number (`external_id = ddf<id>`). | |
| 5 | +Homes-for-sale aggregator for Canada **outside Québec**, Ontario first — a | |
| 6 | +**Groupe KA** service and the English-language sister site of | |
| 7 | +[Immo-Ka](https://www.immo-ka.com) (Québec). House-Ka continuously aggregates | |
| 8 | +homes publicly listed by Canadian real-estate brokerages, teams and national | |
| 9 | +networks, with photos, details, maps, live mortgage rates and a direct link | |
| 10 | +back to each source's original listing. | |
| 11 | + | |
| 12 | +> House-Ka is an independent aggregator: it is not a brokerage, does not | |
| 13 | +> represent buyers or sellers, and is not affiliated with the sources it | |
| 14 | +> indexes. Prices and availability are those displayed by each source. | |
| 15 | + | |
| 16 | +## At a glance (live, 2026-08-28) | |
| 17 | + | |
| 18 | +| Metric | Value | | |
| 19 | +|---|---| | |
| 20 | +| Homes published (deduplicated) | **~258,000** | | |
| 21 | +| Cities & towns | **5,991** | | |
| 22 | +| Active sources | **28** CREA DDF brokerage feeds (247 offices) | | |
| 23 | +| Average asking price | ~$913,000 (from $360 to $79M) | | |
| 24 | +| Average data completeness | 77.6 / 100 | | |
| 25 | +| Coverage | 9 provinces + 2 territories (all of Canada except Québec & Nunavut) | | |
| 26 | +| Launched | 2026-08-27 | | |
| 27 | + | |
| 28 | +--- | |
| 29 | + | |
| 30 | +## Guided tour | |
| 31 | + | |
| 32 | +Ten screenshots of the live site (in `docs/screenshots/`). | |
| 33 | + | |
| 34 | +### 1 — Home: search every home in one place | |
| 35 | +[`https://www.house-ka.com/`](https://www.house-ka.com/) | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | +The landing page states the mission — *"Every home for sale. One place."* — | |
| 40 | +above the live counters (homes indexed, cities & towns, average and highest | |
| 41 | +price). A scrolling ticker streams per-source volumes in real time | |
| 42 | +(Century 21 Ontario, The Cody Group, Century 21 BC…). Below, the search bar | |
| 43 | +("Where do you want to live?") combines city, property type and price-range | |
| 44 | +filters with one-tap type chips (House, Land, Condo, Townhouse, Multi-family, | |
| 45 | +Mobile home, Farm), and the result header offers sorting plus a List / Map | |
| 46 | +toggle. The pine-green / cream / serif skin is deliberately distinct from | |
| 47 | +Immo-Ka's cherry theme. | |
| 48 | + | |
| 49 | +### 2 — Property page: full listing detail | |
| 50 | +[`https://www.house-ka.com/property/c21_ab%3Ac21123293118/2-amp-72-highways-rural-rocky-view-county`](https://www.house-ka.com/property/c21_ab%3Ac21123293118/2-amp-72-highways-rural-rocky-view-county) | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | +A listing detail page (`/property/{uid}/{slug}`) — here a $2,900,000 land | |
| 55 | +parcel in Rural Rocky View County, Alberta from the Century 21 Canada — | |
| 56 | +Alberta feed. Photo gallery on top, then asking price with the canonical type | |
| 57 | +badge, address with province, a favorites heart (KA ID accounts), breadcrumb | |
| 58 | +navigation, and a **Location** card rendered by Ka Maps with the price marker | |
| 59 | +and the listing's building/lot highlighted. The DOM order follows the Groupe | |
| 60 | +KA detail-page standard (gallery → price → description → details → analyses → | |
| 61 | +map), identical on mobile and desktop. | |
| 62 | + | |
| 63 | +### 3 — Live mortgage rates | |
| 64 | +[`https://www.house-ka.com/rates`](https://www.house-ka.com/rates) | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | +The `/rates` page publishes the rates **actually posted** by the big Canadian | |
| 69 | +institutions (banks, virtual lenders, monolines), collected continuously by | |
| 70 | +the shared Groupe KA mortgage engine. The market overview shows the best rate | |
| 71 | +per term (fixed 1/3/4/5/10 years, 5-year variable) with the median and 30-day | |
| 72 | +trend, plus every institution's prime rate. The comparison table lists each | |
| 73 | +product with its **kind** (posted or special offer), **freshness** and a link | |
| 74 | +to the **official source** — never an invented rate, never a stale one | |
| 75 | +without a warning. | |
| 76 | + | |
| 77 | +### 4 — Platform statistics & data quality | |
| 78 | +[`https://www.house-ka.com/stats`](https://www.house-ka.com/stats) | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | +The `/stats` dashboard exposes the platform's own numbers live: homes for | |
| 83 | +sale, cities, average price, source count — and, unusually for a listings | |
| 84 | +site, its full **data-quality layer**: active vs published listings, | |
| 85 | +quarantine size, average completeness score, and a per-source table with | |
| 86 | +listing counts, completeness and anomaly flags. Every listing gets a | |
| 87 | +completeness score (photos, description, specs, coordinates); listings | |
| 88 | +without a plausible price or a known city are quarantined until the next | |
| 89 | +enrichment pass completes them. | |
| 90 | + | |
| 91 | +### 5 — Sources by brokerage | |
| 92 | +[`https://www.house-ka.com/agencies`](https://www.house-ka.com/agencies) | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | +The `/agencies` registry lists every covered brokerage and team — 28 banners, | |
| 97 | +247 offices — with expandable per-banner listing counts (Century 21 Canada by | |
| 98 | +province, The Cody Group, Revel Realty, Grapevine…). Each source publishes | |
| 99 | +its board's full inventory through the CREA DDF feed; the same property | |
| 100 | +published on several sites is only counted once (deduplication by DDF | |
| 101 | +number). Clicking a source filters the search to its homes. | |
| 102 | + | |
| 103 | +### 6 — Contact | |
| 104 | +[`https://www.house-ka.com/contact`](https://www.house-ka.com/contact) | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | +The contact page, with the House-Ka identity and the Groupe KA footer linking | |
| 109 | +to the sister services. | |
| 110 | + | |
| 111 | +### 7 — Map view: the whole country on one map | |
| 112 | +[`https://www.house-ka.com/?view=map`](https://www.house-ka.com/?view=map) | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | +The split list/map view powered by **Ka Maps** (`@groupe-ka/ka-maps`, the | |
| 117 | +shared Groupe KA Mapbox framework). Clusters show the listing count with the | |
| 118 | +approximate median price underneath; "search this area" re-queries the | |
| 119 | +viewport, and the list panel stays in sync with the markers by construction | |
| 120 | +(single `/api/listings` search backend). 2D/3D toggle, drawing tool and | |
| 121 | +geolocation included. | |
| 122 | + | |
| 123 | +### 8 — Account: KA ID single sign-on | |
| 124 | +[`https://www.house-ka.com/account`](https://www.house-ka.com/account) | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | +The `/account` page plugs into **KA ID**, the central Groupe KA identity | |
| 129 | +(groupe-ka.com): one member identifier valid across the whole ecosystem. | |
| 130 | +Signed-in users get cross-site favorites ("My Ka universe"). The footer | |
| 131 | +presents the ecosystem: Groupe-Ka portal, Immo-Ka (homes for sale in Québec), | |
| 132 | +Lou-Ka (rentals in Québec), Vrai-Prix (Québec market-value estimates). | |
| 133 | + | |
| 134 | +### 9 — Terms of use | |
| 135 | +[`https://www.house-ka.com/terms`](https://www.house-ka.com/terms) | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | +Terms of use — including the independent-aggregator disclaimer and the rules | |
| 140 | +for source attribution and linking back to original listings. | |
| 141 | + | |
| 142 | +### 10 — Privacy policy | |
| 143 | +[`https://www.house-ka.com/privacy`](https://www.house-ka.com/privacy) | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | +Privacy policy: what is collected (KA ID account data, favorites), what is | |
| 148 | +not, and how the analytics distinguish human traffic. | |
| 149 | + | |
| 150 | +--- | |
| 151 | + | |
| 152 | +## Features | |
| 153 | + | |
| 154 | +- **Nationwide search** — by city/town (5,991 of them), property type, price | |
| 155 | + range and free-text query; quick type chips; newest-first and price | |
| 156 | + sorting; list or map view. | |
| 157 | +- **Programmatic SEO pages** — `/for-sale/{city}` and | |
| 158 | + `/for-sale/{city}/{type}` city pages plus `/type/{type}` pages, all | |
| 159 | + server-rendered with meta, JSON-LD and sitemaps (in English, `en_CA`). | |
| 160 | +- **Listing pages** — gallery, price, canonical type, specs, description, | |
| 161 | + nearby commerce banners adapted to each province, Ka Maps location card, | |
| 162 | + link to the original listing. | |
| 163 | +- **Live mortgage rates** — national Canadian rates with kind, freshness and | |
| 164 | + official source per product (shared `immoka/mortgage/` engine, see | |
| 165 | + `docs/mortgage-engine.md`). | |
| 166 | +- **Transparent statistics** — public `/stats` dashboard including the | |
| 167 | + quality layer (quarantine, completeness, anomaly flags per source). | |
| 168 | +- **KA ID accounts & favorites** — Groupe KA single sign-on, cross-site | |
| 169 | + favorites hub. | |
| 170 | +- **Data quality pipeline** — completeness scoring, quarantine, image audit, | |
| 171 | + coordinate guard covering all of Canada, cross-site dedup. | |
| 172 | + | |
| 173 | +## Data & sources | |
| 174 | + | |
| 175 | +All 28 active sources are Canadian brokerage / team / network sites whose | |
| 176 | +inventories come from the **CREA DDF** feed: | |
| 177 | + | |
| 178 | +- **RealtyPress connector** (`immoka/connectors/realtypress.py`) — one | |
| 179 | + generic connector covers every brokerage or team site running the | |
| 180 | + RealtyPress WordPress plugin (Revel Realty, The Cody Group, Grapevine, | |
| 181 | + Sutton Ottawa, Hanlon Realty…). Each site exposes its board's full | |
| 182 | + inventory; cross-site duplicates are masked by DDF number | |
| 183 | + (`external_id = ddf<id>`, dedup by `MIN(uid)`). | |
| 184 | +- **Century 21 Canada connector** (`immoka/connectors/c21_canada.py`) — one | |
| 185 | + provincial source per region: BC, AB, SK, MB, ON, NB, NS, PE, NL, YT, NT. | |
| 186 | + (Saskatchewan has no polygon API and is searched via ~30 cities; the | |
| 187 | + Alberta watcher uses adaptive sleep for cycles longer than 24 h.) | |
| 188 | + | |
| 189 | +DDF list cards carry no property type: most listings get their type when | |
| 190 | +their detail page is fetched (`IMMOKA_RP_DETAIL_LIMIT` per source per sync). | |
| 191 | +Sources are declared in `data/sources.json` and the site census lives in | |
| 192 | +`data/canada_agencies.json`; the checked-in `sources.json` documents the | |
| 193 | +initial registry. | |
| 194 | + | |
| 195 | +### Canonical property types (English) | |
| 196 | + | |
| 197 | +`House, Condo, Townhouse, Semi-detached, Duplex, Triplex, Multi-family, | |
| 198 | +Cottage, Mobile home, Land, Farm, Commercial, Parking` — | |
| 199 | +see `immoka/normalize.py`. | |
| 12 | 200 | |
| 13 | 201 | ## Architecture |
| 14 | 202 | |
| 15 | −Forked from Immo-Ka on 2026-08-27 (the Ontario expansion paused there moved | |
| 16 | −here). The Python package keeps its historical name `immoka`. | |
| 203 | +Forked from **Immo-Ka** on 2026-08-27 (the Ontario expansion paused there | |
| 204 | +moved here — see the immo-ka repo's `docs/ONTARIO-PAUSE.md`). The Python | |
| 205 | +package keeps its historical name `immoka`. | |
| 17 | 206 | |
| 18 | −- **Backend** — FastAPI + SQLite (`data/immoka.db`), same pipeline as Immo-Ka: | |
| 19 | − connectors → `ingest` → dedup → `quality` (relaxed publication rule: price + | |
| 20 | − city; type/description enrich over time via detail passes) → API. | |
| 207 | +- **Backend** — FastAPI + SQLite (`data/immoka.db`), same pipeline as | |
| 208 | + Immo-Ka: connectors → `ingest` → dedup → `quality` (relaxed publication | |
| 209 | + rule: price + city; type/description enrich over time via detail passes) → | |
| 210 | + API. Sync loop runs every 240 minutes under PM2. | |
| 21 | 211 | - **Frontend** — React/Vite, **English**, pine/cream/serif skin (deliberately |
| 22 | − different from Immo-Ka's cherry). Routes: `/`, `/property/{uid}[/{slug}]`, | |
| 23 | − `/for-sale/{city}[/{type}]`, `/type/{type}`, `/rates`, `/agencies`, `/stats`. | |
| 24 | − Map = Ka Maps (`@groupe-ka/ka-maps`, expected at `../../ka-maps`). | |
| 25 | −- **SEO** — `immoka/seo.py` renders server-side HTML (meta, JSON-LD, sitemaps) | |
| 26 | − in English. | |
| 212 | + different from Immo-Ka's cherry). SPA routes: `/`, `/property/{uid}[/{slug}]`, | |
| 213 | + `/rates`, `/agencies`, `/stats`, `/account`, `/contact`, `/terms`, | |
| 214 | + `/privacy`; SEO routes `/for-sale/{city}[/{type}]` and `/type/{type}` are | |
| 215 | + resolved server-side. Map = Ka Maps (`@groupe-ka/ka-maps`, expected at | |
| 216 | + `../../ka-maps`). | |
| 217 | +- **SEO** — `immoka/seo.py` renders server-side HTML (meta, JSON-LD, | |
| 218 | + sitemaps, `robots.txt`) in English. | |
| 27 | 219 | - **Mortgage engine** — shared with Immo-Ka (`immoka/mortgage/`), national |
| 28 | 220 | Canadian rates. See `docs/mortgage-engine.md`. |
| 29 | 221 | - **Removed vs Immo-Ka** — everything Québec-only: Hydro-Québec estimates, |
@@ -31,33 +223,70 @@ here). The Python package keeps its historical name `immoka`. | ||
| 31 | 223 | Vrai-Prix, movers/inspectors directories, PDF listing sheets, all QC |
| 32 | 224 | connectors. |
| 33 | 225 | |
| 34 | −## Canonical property types (English) | |
| 226 | +### Repository layout | |
| 35 | 227 | |
| 36 | −`House, Condo, Townhouse, Semi-detached, Duplex, Triplex, Multi-family, | |
| 37 | −Cottage, Mobile home, Land, Farm, Commercial, Parking` — | |
| 38 | −see `immoka/normalize.py`. DDF list cards carry no type: most listings get | |
| 39 | −their type when their detail page is fetched (`IMMOKA_RP_DETAIL_LIMIT` per | |
| 40 | −source per sync). | |
| 228 | +``` | |
| 229 | +run.py CLI entry point (sync / watch / serve / list / geocode / mortgage-sync) | |
| 230 | +immoka/ Python package (historical name kept from the Immo-Ka fork) | |
| 231 | + web.py FastAPI app: API + SEO HTML + SPA fallback | |
| 232 | + ingest.py, quality.py, normalize.py, schema.py, db.py | |
| 233 | + seo.py English server-side SEO (meta, JSON-LD, sitemaps) | |
| 234 | + geocode.py, imgaudit.py, stats.py, commerces.py, poi.py | |
| 235 | + auth.py, kaid.py, favorites.py, hubfav.py, hubprofile.py (KA ID SSO + favorites) | |
| 236 | + mortgage/ shared Groupe KA mortgage-rate engine (+ /api/mortgage) | |
| 237 | + connectors/ realtypress.py, c21_canada.py, base.py, jsonld.py, _detailutil.py, _resilient.py | |
| 238 | +frontend/ React/Vite SPA (src/pages: Home, Listing, Rates, Stats, Agencies, Account, Contact, Legal) | |
| 239 | +scripts/ scouting & maintenance (scout_canada_rp*.py, gen_connector_docs.py, …) | |
| 240 | +docs/ mortgage-engine.md, ontario-agencies.md, screenshots/ | |
| 241 | +data/ SQLite DB + live registries (not committed) | |
| 242 | +``` | |
| 243 | + | |
| 244 | +## API | |
| 245 | + | |
| 246 | +| Route | Description | | |
| 247 | +|---|---| | |
| 248 | +| `GET /api/listings` | search (city, type, price, text, bbox/polygon, sort, pagination) | | |
| 249 | +| `GET /api/listings/{uid}` | full listing detail | | |
| 250 | +| `GET /api/listings.geojson` | map markers/clusters feed | | |
| 251 | +| `GET /api/facets` | cities, property types, sources facets | | |
| 252 | +| `GET /api/agencies` | brokerage/office registry with counts | | |
| 253 | +| `GET /api/stats` | live platform + quality statistics | | |
| 254 | +| `GET /api/stats/catalog`, `/dashboard`, `/report` | stats module (kacharts/kapdf, custom reports via `POST /api/stats/report/custom`) | | |
| 255 | +| `GET /api/mortgage` | live mortgage rates | | |
| 256 | +| `GET /api/commerces` | nearby commerce banners per province | | |
| 257 | +| `/api/auth`, `/api/favorites` | KA ID session + favorites | | |
| 258 | +| `GET /api/sources`, `POST /api/sync` | connector registry & manual sync | | |
| 259 | +| `GET /api/seo/resolve`, `/sitemap.xml`, `/sitemaps/{name}`, `/robots.txt` | SEO plumbing | | |
| 41 | 260 | |
| 42 | 261 | ## Run |
| 43 | 262 | |
| 44 | 263 | ```bash |
| 45 | 264 | python run.py sync [source ...] # sync listings |
| 46 | −python run.py watch [minutes] # sync loop (default 60 min) | |
| 265 | +python run.py watch [minutes] # sync loop (default 60 min; prod uses 240) | |
| 47 | 266 | python run.py serve [port] # API + frontend (default 8098) |
| 48 | 267 | python run.py list # registered connectors |
| 49 | 268 | python run.py geocode [n] # geocode listings missing coordinates |
| 50 | 269 | python run.py mortgage-sync # collect mortgage rates |
| 51 | 270 | ``` |
| 52 | 271 | |
| 53 | −`.env`: `IMMOKA_BASE_URL=https://www.house-ka.com`, | |
| 54 | −`IMMOKA_RP_DETAIL_LIMIT=<n>` (detail pages fetched per source per sync). | |
| 272 | +`.env` (see `.env.example`, never committed): `IMMOKA_BASE_URL=https://www.house-ka.com`, | |
| 273 | +`IMMOKA_RP_DETAIL_LIMIT=<n>` (detail pages fetched per source per sync), | |
| 274 | +plus optional scraping/SSO/mortgage-engine settings. | |
| 55 | 275 | |
| 56 | 276 | ## Deployment |
| 57 | 277 | |
| 58 | −M4M64b, `~/apps/house-ka`, PM2 (`house-ka-web` :8098, `house-ka-sync`, | |
| 59 | −`house-ka-ngrok` → www.house-ka.com). Remote-first: the repo on the node is | |
| 60 | −the source of truth, `origin` = spbgit (`gitsrv:house-ka.git`). | |
| 278 | +Node **M4M64b**, `~/apps/house-ka`, PM2: | |
| 279 | + | |
| 280 | +| Process | Role | | |
| 281 | +|---|---| | |
| 282 | +| `house-ka-web` | `run.py serve` on port **8098** | | |
| 283 | +| `house-ka-sync` | `run.py watch 240` (sync loop every 4 h) | | |
| 284 | +| `house-ka-ngrok` | tunnel → **www.house-ka.com** | | |
| 285 | + | |
| 286 | +Remote-first: the repo **on the node** is the source of truth (never the | |
| 287 | +laptop copies); `origin` = spbgit, the personal git server | |
| 288 | +(`gitsrv:srv/git/house-ka.git`, bare repos on M3U96a). Edit over SSH, build, | |
| 289 | +`pm2 restart`, then commit & push from the node (agent forwarding). | |
| 61 | 290 | |
| 62 | 291 | ## Adding sources (rest of Canada) |
| 63 | 292 | |
@@ -65,3 +294,15 @@ RealtyPress sites exist across Canada. Census & instructions: | ||
| 65 | 294 | `docs/ontario-agencies.md` (method transposes to any province). Add the site |
| 66 | 295 | to `data/canada_agencies.json` + an entry in `data/sources.json`, then |
| 67 | 296 | `python run.py sync <id>`. The coordinate guard covers all of Canada. |
| 297 | + | |
| 298 | +## Groupe KA ecosystem | |
| 299 | + | |
| 300 | +House-Ka is one of the Groupe KA platforms ([groupe-ka.com](https://www.groupe-ka.com)): | |
| 301 | +Immo-Ka (homes for sale, Québec), Lou-Ka (rentals, Québec), Rent-Ka (rentals, | |
| 302 | +Canada outside Québec), Vrai-Prix (market-value estimates), Auto-Ka, Food-Ka, | |
| 303 | +Resto-Ka, Sorti-Ka, Job-Ka, Trouve-Ka, Crea-Ka, Fabri-Ka — all sharing KA ID, | |
| 304 | +the ka-ui design system, Ka Maps and the stats/PDF modules. | |
| 305 | + | |
| 306 | +## Contact | |
| 307 | + | |
| 308 | +Simon-Pierre Boucher — contact@spboucher.ai — © 2026 Groupe-Ka | |
added
docs/screenshots/01-accueil.jpg
+0 −0
Binary file not shown.
added
docs/screenshots/02-property-c21_ab-3Ac21123293118-2-amp-72-highways-rural-rocky.jpg
+0 −0
Binary file not shown.
added
docs/screenshots/03-rates.jpg
+0 −0
Binary file not shown.
added
docs/screenshots/04-stats.jpg
+0 −0
Binary file not shown.
added
docs/screenshots/05-agencies.jpg
+0 −0
Binary file not shown.
added
docs/screenshots/06-contact.jpg
+0 −0
Binary file not shown.
added
docs/screenshots/07-accueil.jpg
+0 −0
Binary file not shown.
added
docs/screenshots/08-account.jpg
+0 −0
Binary file not shown.
added
docs/screenshots/09-terms.jpg
+0 −0
Binary file not shown.
added
docs/screenshots/10-privacy.jpg
+0 −0
Binary file not shown.