SPB Git forge

spb/toit-ka

Public

Toit-Ka — louer ou acheter un toit au Québec, un seul endroit (fusion Lou-Ka × Immo-Ka) — www.toit-ka.com

4commits 1branches 0releases
2.0 MBsize
maindefault branch
25 days agolast push
Python 40.2% TypeScript 39% CSS 20.2% HTML 0.7%

chore: repo toit-ka raccroché à spbgit + README ultra détaillé (FR) + visite guidée en 10 captures

Simon-Pierre Boucher committed 1 mo ago (Aug 29, 2026) parent a95d48a

13 changed files +321 −122

modified .gitignore +17 −2
@@ -1,8 +1,23 @@
1 1 # Author: Simon-Pierre Boucher — Contact: contact@spboucher.ai — Project: Toit-Ka
2 −.env
2 +# Données (répliques prod + BD unifiée = plusieurs Go) — jamais dans git
3 3 data/
4 +*.db
5 +*.db-shm
6 +*.db-wal
7 +*.sqlite*
8 +# Secrets
9 +.env
10 +.env.*
11 +# Dépendances / environnements
4 12 frontend/node_modules/
5 −frontend/dist/
13 +node_modules/
14 +.venv/
15 +venv/
6 16 __pycache__/
7 17 *.pyc
18 +# Build & artefacts
19 +frontend/dist/
20 +frontend/tsconfig.tsbuildinfo
21 +*.log
8 22 .DS_Store
23 +.claude/
modified README.md +304 −119
@@ -4,163 +4,348 @@
4 4 Project: Toit-Ka
5 5 -->
6 6
7 −# Toit-Ka — rent or buy a roof in Québec, one place
8 −
9 −![Listings](https://img.shields.io/badge/listings-85%20503-e07a3f?style=flat-square)
10 −![For rent](https://img.shields.io/badge/for%20rent-22%20881-d9f26b?style=flat-square&labelColor=141814)
11 −![For sale](https://img.shields.io/badge/for%20sale-62%20622-e23744?style=flat-square&labelColor=141814)
12 −![Sources](https://img.shields.io/badge/sources-229%2B-181410?style=flat-square)
13 −![Avg rent](https://img.shields.io/badge/avg%20rent-%241%20732%2Fmo-1c5c41?style=flat-square)
14 −![Avg price](https://img.shields.io/badge/avg%20price-%24683%20945-b3202b?style=flat-square)
7 +# Toit-Ka — louer ou acheter un toit au Québec, au même endroit
8 +
9 +![Annonces](https://img.shields.io/badge/annonces-226%20094-e07a3f?style=flat-square)
10 +![À louer](https://img.shields.io/badge/%C3%A0%20louer-68%20925-d9f26b?style=flat-square&labelColor=141814)
11 +![À vendre](https://img.shields.io/badge/%C3%A0%20vendre-157%20169-e23744?style=flat-square&labelColor=141814)
12 +![Sources](https://img.shields.io/badge/sources-500%2B-181410?style=flat-square)
13 +![Loyer moyen](https://img.shields.io/badge/loyer%20moyen-1%20834%20%24%2Fmois-1c5c41?style=flat-square)
14 +![Prix moyen](https://img.shields.io/badge/prix%20moyen-%E2%89%88904%20k%24-b3202b?style=flat-square)
15 15 ![Backend](https://img.shields.io/badge/backend-FastAPI%20%2B%20SQLite-009688?style=flat-square)
16 16 ![Frontend](https://img.shields.io/badge/frontend-React%2018%20%2B%20Vite%20%2B%20TS-61dafb?style=flat-square&labelColor=20232a)
17 −![Maps](https://img.shields.io/badge/maps-Ka%20Maps%20(Mapbox%20GL%203D)-4264fb?style=flat-square)
18 −![Lang](https://img.shields.io/badge/lang-fran%C3%A7ais%20(QC)-blue?style=flat-square)
17 +![Cartes](https://img.shields.io/badge/cartes-Ka%20Maps%20(Mapbox%20GL%203D)-4264fb?style=flat-square)
18 +![Langue](https://img.shields.io/badge/langue-fran%C3%A7ais%20(QC)-blue?style=flat-square)
19 19
20 −**Toit-Ka** ([www.toit-ka.com](https://www.toit-ka.com)) is the merger of two
21 −Québec real-estate aggregators into a single platform where users search **for
22 −rent OR for sale** in one place:
20 +**Toit-Ka** ([www.toit-ka.com](https://www.toit-ka.com)) est la **fusion de deux
21 +agrégateurs immobiliers québécois en une seule plateforme** : on y cherche un
22 +logement **à louer OU une propriété à vendre**, au même endroit, avec la même
23 +recherche, les mêmes cartes et le même vocabulaire :
23 24
24 −- **[Lou-Ka](https://www.lou-ka.com)** — ~23,000 rental listings aggregated from
25 − 200+ property managers, brokers and platforms;
26 −- **[Immo-Ka](https://www.immo-ka.com)** — ~63,000 for-sale properties aggregated
27 − from 29 networks (RE/MAX, Via Capitale, Sutton, Proprio Direct, Centris feeds…).
25 +- **[Lou-Ka](https://www.lou-ka.com)** — locatif : ~69 000 annonces de logements
26 + agrégées depuis 400+ gestionnaires immobiliers, courtiers et plateformes ;
27 +- **[Immo-Ka](https://www.immo-ka.com)** — vente : ~157 000 propriétés agrégées
28 + depuis les grands réseaux (RE/MAX, Via Capitale, Sutton, Proprio Direct,
29 + flux Centris…).
28 30
29 −Toit-Ka **does not scrape anything itself**: it consumes read-only replicas of
30 −both production databases and unifies them through a normalization ETL. The two
31 −original sites keep running untouched. Every listing card links back to the
32 −original ad at the source.
31 +Point capital : **Toit-Ka ne scrape rien lui-même**. Il consomme des
32 +**réplicas en lecture seule** des deux bases de données de production et les
33 +unifie via un ETL de normalisation. Les deux sites d'origine continuent de
34 +tourner sans être touchés, et chaque fiche renvoie vers l'annonce originale
35 +chez la source.
33 36
34 −## Screenshots
37 +> Chiffres au 2026-08-28 (`/api/stats`) : **226 094 annonces publiées**
38 +> (68 925 à louer · 157 169 à vendre), ~500 sources héritées, loyer moyen
39 +> 1 834 $/mois, prix affiché moyen ≈ 904 000 $.
35 40
36 −*Captured 2026-08-25 (mobile 390×844 · desktop 1440×900).*
41 +---
37 42
38 −### Mobile
43 +## Identité : le design bi-accent
39 44
40 −<table>
41 − <tr>
42 − <td align="center"><img src="docs/screenshots/mobile/home.webp" width="240" alt="Home mobile"><br><sub><b>Home — rent OR buy, one search</b></sub></td>
43 − <td align="center"><img src="docs/screenshots/mobile/resultats.webp" width="240" alt="Results mobile"><br><sub><b>Listings in Montréal</b></sub></td>
44 − <td align="center"><img src="docs/screenshots/mobile/annonce.webp" width="240" alt="Listing mobile"><br><sub><b>Listing page — links back to the source ad</b></sub></td>
45 − </tr>
46 − <tr>
47 − <td align="center"><img src="docs/screenshots/mobile/stats.webp" width="240" alt="Stats mobile"><br><sub><b>Market statistics</b></sub></td>
48 − <td align="center" colspan="2"><img src="docs/screenshots/mobile/menu-mobile.webp" width="240" alt="Mobile menu"><br><sub><b>Full-screen mobile nav (KA Nav v2)</b></sub></td>
49 − </tr>
50 −</table>
45 +Toit-Ka réunit deux univers qui avaient chacun leur couleur. Plutôt que d'en
46 +choisir une, le site adopte un **système bi-accent** piloté par un unique
47 +attribut `html[data-mode]` :
48 +
49 +| Accent | Couleur | Rôle |
50 +|---|---|---|
51 +| **Lime électrique** | héritée de Lou-Ka | mode **Louer** : boutons, pastilles de carte, chips, stats |
52 +| **Rouge** | hérité d'Immo-Ka | mode **Acheter** : mêmes composants, autre univers |
53 +| **Terracotta** | propre à Toit-Ka | la marque elle-même (logo, badges, éléments neutres) |
54 +
55 +Le **toggle central Louer / Acheter** de la page d'accueil est le cœur de
56 +l'expérience : il bascule instantanément les filtres, les paliers de prix, les
57 +chips rapides, les statistiques et l'accent visuel de tout le site. Le socle
58 +graphique est le style « éditorial tranché » du Groupe Ka : Space Grotesk /
59 +Inter / JetBrains Mono, bordures encre, ombres décalées, mobile-first,
60 +français (Québec).
61 +
62 +---
63 +
64 +## Visite guidée (10 captures)
65 +
66 +*Captures du 2026-08-28 sur www.toit-ka.com (desktop 1440×900 · mobile 390×844).*
67 +
68 +### 1. Accueil — un toit, deux univers
69 +
70 +![Accueil](docs/screenshots/visite/01-accueil.jpg)
71 +
72 +La page d'accueil avec le **toggle central Louer / Acheter**, la barre de
73 +recherche par ville et les compteurs live des deux univers. L'accent de la
74 +page suit le mode sélectionné.
75 +
76 +### 2. Fiche d'annonce — propriété à vendre
77 +
78 +![Fiche annonce achat](docs/screenshots/visite/02-annonce-immo-3Aabbeyandolivier-3A11701844-5334-rue-waverly-m.jpg)
79 +
80 +Une fiche complète en mode *Acheter* (5334, rue Waverly, Montréal) : galerie
81 +photo, prix, caractéristiques, description, carte — et le **lien vers
82 +l'annonce originale** chez la source. L'URL canonique
83 +`/annonce/{uid}/{slug}` est rendue côté serveur pour le SEO.
84 +
85 +### 3. Accueil en mode Louer — l'accent lime
86 +
87 +![Accueil mode Louer](docs/screenshots/visite/03-accueil.jpg)
88 +
89 +La même page d'accueil après bascule du toggle (`?tx=louer`) : filtres,
90 +paliers de prix et chips s'adaptent à l'univers locatif et tout le site passe
91 +à l'accent lime hérité de Lou-Ka.
92 +
93 +### 4. Statistiques de marché
94 +
95 +![Statistiques](docs/screenshots/visite/04-stats.jpg)
96 +
97 +La page `/stats` : volumes par univers, loyers et prix moyens, top villes et
98 +top typologies, calculés en direct sur la base unifiée `toitka.db`.
99 +
100 +### 5. Profil — KA ID
101 +
102 +![Profil](docs/screenshots/visite/05-profil.jpg)
103 +
104 +Le profil membre via **KA ID**, l'identité unique du Groupe Ka
105 +(groupe-ka.com) : connexion partagée et favoris centralisés dans
106 +« Mon univers Ka », communs aux 12 sites de l'écosystème.
107 +
108 +### 6. Conditions d'utilisation
109 +
110 +![Conditions](docs/screenshots/visite/06-conditions.jpg)
111 +
112 +La page `/conditions` : cadre d'utilisation, statut d'agrégateur et renvoi
113 +systématique aux annonces originales.
114 +
115 +### 7. Politique de confidentialité
116 +
117 +![Confidentialité](docs/screenshots/visite/07-confidentialite.jpg)
118 +
119 +La page `/confidentialite` : données collectées, cookies, droits des membres
120 +KA ID.
121 +
122 +### 8. Accueil — sections thématiques (1/2)
51 123
52 −### Desktop
124 +![Accueil section 1](docs/screenshots/visite/08-accueil-section-1.jpg)
125 +
126 +En défilant l'accueil : sélections d'annonces par univers et raccourcis vers
127 +les grandes villes, chaque bloc portant l'accent de son univers.
128 +
129 +### 9. Accueil — sections thématiques (2/2)
130 +
131 +![Accueil section 2](docs/screenshots/visite/09-accueil-section-2.jpg)
132 +
133 +Suite de l'accueil : typologies populaires (3½, 4½, condo, maison, plex…),
134 +statistiques et maillage interne vers les pages SEO par ville et par type.
135 +
136 +### 10. Accueil mobile
137 +
138 +![Accueil mobile](docs/screenshots/visite/10-accueil-mobile.jpg)
139 +
140 +L'accueil sur téléphone (390×844) : toggle, recherche et compteurs au-dessus
141 +du pli, navigation plein écran (KA Nav v2), conforme au socle mobile du
142 +Groupe Ka (zones tactiles, safe-area, anti-zoom).
143 +
144 +### Galerie complémentaire (2026-08-25)
53 145
54 146 <table>
55 147 <tr>
56 − <td align="center"><img src="docs/screenshots/desktop/home.webp" width="420" alt="Home desktop"><br><sub><b>Home — 136,000+ listings, rent + sale unified</b></sub></td>
57 − <td align="center"><img src="docs/screenshots/desktop/resultats.webp" width="420" alt="Results desktop"><br><sub><b>City results — dual-accent design (rent/sale)</b></sub></td>
148 + <td align="center"><img src="docs/screenshots/mobile/home.webp" width="200" alt="Accueil mobile"><br><sub><b>Accueil mobile</b></sub></td>
149 + <td align="center"><img src="docs/screenshots/mobile/resultats.webp" width="200" alt="Résultats mobile"><br><sub><b>Résultats à Montréal</b></sub></td>
150 + <td align="center"><img src="docs/screenshots/mobile/annonce.webp" width="200" alt="Fiche mobile"><br><sub><b>Fiche annonce</b></sub></td>
151 + <td align="center"><img src="docs/screenshots/mobile/stats.webp" width="200" alt="Stats mobile"><br><sub><b>Statistiques</b></sub></td>
152 + <td align="center"><img src="docs/screenshots/mobile/menu-mobile.webp" width="200" alt="Menu mobile"><br><sub><b>Menu plein écran</b></sub></td>
58 153 </tr>
59 154 <tr>
60 − <td align="center"><img src="docs/screenshots/desktop/annonce.webp" width="420" alt="Listing desktop"><br><sub><b>Listing page</b></sub></td>
61 − <td align="center"><img src="docs/screenshots/desktop/stats.webp" width="420" alt="Stats desktop"><br><sub><b>Statistics</b></sub></td>
155 + <td align="center" colspan="2"><img src="docs/screenshots/desktop/home.webp" width="420" alt="Accueil desktop"><br><sub><b>Accueil desktop</b></sub></td>
156 + <td align="center" colspan="2"><img src="docs/screenshots/desktop/resultats.webp" width="420" alt="Résultats desktop"><br><sub><b>Résultats — design bi-accent</b></sub></td>
157 + <td align="center"><img src="docs/screenshots/desktop/stats.webp" width="220" alt="Stats desktop"><br><sub><b>Stats desktop</b></sub></td>
62 158 </tr>
63 159 </table>
64 160
65 −## Architecture
161 +---
162 +
163 +## Fonctionnalités
164 +
165 +- **Deux univers, une plateforme** : toggle central **Louer / Acheter** ;
166 + filtres, paliers de prix, chips rapides et stats adaptés à l'univers actif.
167 +- **Recherche unifiée** : par ville (canonique), prix, type (3½…6½+, Studio,
168 + Chambre, Condo, Maison, Plex, Terrain…), chambres/salles de bain,
169 + superficie, animaux, meublé, texte libre.
170 +- **Vue liste + carte 3D** (Ka Maps / Mapbox GL) : marqueurs par univers
171 + (pastilles lime pour le locatif, encre pour la vente), « chercher dans
172 + cette zone », aperçus React au clic.
173 +- **Fiche complète** : galerie + lightbox, caractéristiques, description,
174 + mini-carte avec anneaux de marchabilité, **lien vers l'annonce originale**.
175 +- **SEO programmatique rendu côté serveur** : `/louer/{ville}`,
176 + `/acheter/{ville}`, `/{tx}/{ville}/{type}`, `/{tx}/type/{type}` avec loyers
177 + et prix moyens/médians, fils d'Ariane, JSON-LD, sitemaps, slugs canoniques
178 + 301, 410 pour les annonces retirées.
179 +- **KA ID (SSO Groupe Ka)** + favoris centralisés « Mon univers Ka ».
180 +- **Page /stats** live sur la base unifiée.
181 +- Mobile-first, 100 % français (Québec).
182 +
183 +---
184 +
185 +## Architecture — un agrégateur d'agrégateurs, sans scraping
66 186
67 187 ```
68 −M3U96b (prod) M4M64a (prod)
69 − lou-ka louka.db immo-ka immoka.db
70 − │ sqlite3 .backup + rsync (LAN) │ ← read-only, every 30 min
71 − ▼ ▼
72 − M3U96a ~/apps/toit-ka
73 − data/replicas/{louka,immoka}.db
188 +M3U96b (prod) M4M64a (prod)
189 + lou-ka louka.db immo-ka immoka.db
190 + │ sqlite3 .backup + rsync (LAN 192.168.2.x) │ ← lecture seule, toutes les 30 min
191 + ▼ ▼
192 + M3U96a ~/apps/toit-ka
193 + data/replicas/{louka,immoka}.db (toitka/replicate.py)
74 194 │ ETL (toitka/etl.py)
75 − │ · inherited visibility rules (Centris dedup, plausible prices)
76 − │ · canonical city mapping (toitka/villes.py — 3,300+ raw variants)
77 − │ · unified type vocabulary + HTML-entity repair
195 + │ · règles de visibilité héritées (dédup Centris, prix plausibles)
196 + │ · villes canoniques (toitka/villes.py — ~3 300 variantes brutes)
197 + │ · typologie unifiée + réparation des entités HTML
78 198 ▼
79 − data/toitka.db — one `listings` table, `transaction_type ∈ {louer, acheter}`
199 + data/toitka.db — une seule table `listings`, `transaction_type ∈ {louer, acheter}`
80 200 │
81 − FastAPI (toitka/web.py) ── JSON API + server-side SEO rendering (seo.py)
201 + FastAPI (toitka/web.py) ── API JSON + rendu SEO côté serveur (toitka/seo.py)
82 202 │
83 − React 18 SPA (frontend/) ── Louer/Acheter toggle drives the site accent
203 + SPA React 18 (frontend/) ── toggle Louer/Acheter → accent du site
84 204 │
85 − ngrok ── https://www.toit-ka.com
205 + ngrok ── https://www.toit-ka.com (port local 8097)
86 206 ```
87 207
88 −### The city-normalization engine (`toitka/villes.py`)
89 −
90 −The two corpora carried **~3,300 distinct raw city strings** for roughly 1,000
91 −real municipalities. Deterministic rules + a slug-grouping election pass fix,
92 −among others: orphan parentheses (`Brossard )`), never-closed parentheses
93 −(`Gatineau (Hôpital`), duplicated names (`Gatineau (Gatineau)`), boroughs
94 −glued in both orders (`Montréal (Ville-Marie)` vs `Ville-Marie (…)`), merged
95 −municipalities (`Saint-Hubert (Longueuil)`), English variants (`Québec City`,
96 −`Montreal Downtown`, `City Of Montréal`), lost accents/hyphens
97 −(`Trois Rivieres`, `Mont Tremblant`), mojibake (`Montrã©al`) and marketing
98 −labels (`Longueuil / South Shore`). The full raw→canonical mapping is persisted
99 −in the `city_map` table for auditing (`python3 run.py villes`).
100 −
101 −### Dual-accent design system
102 −
103 −Single "sharp editorial" design system (Space Grotesk / Inter / JetBrains Mono,
104 −ink borders, offset shadows) with an accent that **follows the universe**:
105 −Lou-Ka electric lime in *Louer* mode, Immo-Ka red in *Acheter* mode, terracotta
106 −for the Toit-Ka brand itself. The switch is one `html[data-mode]` attribute.
107 −
108 −## Features
109 −
110 −- Home page with a central **Louer / Acheter toggle** — filters, price steps,
111 − quick chips and stats all adapt to the selected universe.
112 −- Search by city (canonical), price, type (3½…6½+, Studio, Condo, Maison,
113 − Plex, Terrain…), bedrooms/bathrooms, area, pets, furnished, free text.
114 −- List + **3D map view** (Ka Maps / Mapbox GL) with per-universe markers
115 − (lime rent pills, ink sale pills), "search this area", React previews.
116 −- Full listing page: gallery + lightbox, specs, description, walkability rings
117 − mini-map, link to the original ad.
118 −- **Programmatic SEO** rendered server-side: `/louer/{ville}`,
119 − `/acheter/{ville}`, `/{tx}/{ville}/{type}`, `/{tx}/type/{type}` with average
120 − and median rent/price, breadcrumbs, JSON-LD, sitemaps, 301 canonical slugs,
121 − 410 for withdrawn listings.
122 −- **KA ID single sign-on** (groupe-ka.com identity hub) + favorites stored
123 − centrally in "Mon univers Ka".
124 −- Mobile-first, French (Québec).
125 −
126 −## Repository layout
208 +### Pourquoi zéro scraping ?
209 +
210 +Lou-Ka et Immo-Ka font déjà le travail dur (des centaines de connecteurs,
211 +files de quarantaine, audits d'images, dédup). Toit-Ka **hérite** de ce
212 +travail : `toitka/replicate.py` tire, toutes les 30 minutes, un snapshot
213 +cohérent de chaque BD de prod (`sqlite3 .backup` côté source puis `rsync` via
214 +le LAN du cluster), en **lecture seule** — aucune écriture, aucun verrou,
215 +aucune charge sur les sites de prod. Le pipeline est idempotent : chaque passe
216 +reconstruit l'état publié et gère le cycle de vie (nouvelles annonces,
217 +retraits → 410).
218 +
219 +### Le moteur de normalisation des villes (`toitka/villes.py`)
220 +
221 +Les deux corpus totalisaient **~3 300 chaînes de villes brutes distinctes**
222 +pour environ 1 000 municipalités réelles. Des règles déterministes plus une
223 +passe d'élection par regroupement de slugs corrigent, entre autres :
224 +parenthèses orphelines (`Brossard )`), parenthèses jamais fermées
225 +(`Gatineau (Hôpital`), noms dupliqués (`Gatineau (Gatineau)`), arrondissements
226 +collés dans les deux sens (`Montréal (Ville-Marie)` vs `Ville-Marie (…)`),
227 +municipalités fusionnées (`Saint-Hubert (Longueuil)`), variantes anglaises
228 +(`Québec City`, `Montreal Downtown`, `City Of Montréal`), accents/traits
229 +d'union perdus (`Trois Rivieres`, `Mont Tremblant`), mojibake (`Montrã©al`) et
230 +libellés marketing (`Longueuil / South Shore`). Le mapping complet
231 +brut → canonique est persisté dans la table `city_map` pour audit
232 +(`python3 run.py villes`).
233 +
234 +### La typologie unifiée (`toitka/typologie.py`)
235 +
236 +Le locatif parle en « pièces et demie » (3½, 4½…), la vente en catégories
237 +(condo, maison, plex, terrain…). `typologie.py` fond les deux vocabulaires en
238 +un seul référentiel de types, utilisé par les filtres, les stats et les pages
239 +SEO par type — pour que « 4½ à Montréal » et « condo à Québec » vivent dans le
240 +même moteur de recherche.
241 +
242 +---
243 +
244 +## API & routes
245 +
246 +### API JSON (FastAPI — `toitka/web.py`)
247 +
248 +| Route | Description |
249 +|---|---|
250 +| `GET /api/listings` | recherche paginée (tx, ville, prix, type, chambres, sdb, superficie, animaux, meublé, texte…) |
251 +| `GET /api/listings/{uid}` | détail d'une annonce (uid préfixé `lou:` / `immo:` selon l'origine) |
252 +| `GET /api/listings.geojson` | flux GeoJSON pour la carte (bbox, filtres) |
253 +| `GET /api/facets` | facettes live (villes, types, paliers de prix) selon l'univers |
254 +| `GET /api/stats` | statistiques agrégées par univers + journal des passes ETL |
255 +| `GET /api/health` | santé (`ok`, nb d'annonces, timestamp du dernier ETL) |
256 +| `GET /api/seo/resolve` | résolution slug → entité pour le routage SPA |
257 +| `GET /api/auth/*` | SSO KA ID (JWT HS256, stdlib uniquement) |
258 +| `GET/POST/DELETE /api/favorites/*` | favoris centralisés « Mon univers Ka » |
259 +
260 +### Routes SEO rendues côté serveur (`toitka/seo.py`)
261 +
262 +| Route | Contenu |
263 +|---|---|
264 +| `/louer/{ville}` · `/acheter/{ville}` | page ville par univers (moyennes, médianes, annonces, JSON-LD) |
265 +| `/{tx}/{ville}/{type}` | page ville × type |
266 +| `/{tx}/type/{type}` | page type provinciale |
267 +| `/annonce/{uid}/{slug}` | fiche annonce (canonique 301 si slug obsolète, **410** si retirée) |
268 +| `/robots.txt` · `/sitemap.xml` · `/sitemaps/{name}` | indexation programmatique |
269 +
270 +Les autres chemins servent la SPA React (catch-all `/{full_path:path}`).
271 +
272 +---
273 +
274 +## Structure du dépôt
127 275
128 276 ```
129 −run.py CLI: serve | etl | watch | replicate | villes
277 +run.py CLI unique : serve | etl | watch | replicate | villes
278 +requirements.txt FastAPI + uvicorn (volontairement minimal)
130 279 toitka/
131 − db.py unified schema (toitka.db) + read-only source connections
132 − villes.py canonical city mapping engine
133 − typologie.py unified type vocabulary (rent + sale)
134 − etl.py replicas -> toitka.db (visibility rules, lifecycle)
135 − replicate.py LAN pull of production snapshots (sqlite .backup + rsync)
136 − web.py FastAPI JSON API + SPA serving
137 − seo.py server-side SEO rendering, robots.txt, sitemaps
138 − auth.py KA ID SSO (JWT HS256, stdlib only)
139 − hubprofile.py member profile read from the Groupe KA hub
140 − hubfav.py favorites.py central favorites ("Mon univers Ka")
141 −frontend/ React 18 + Vite + TypeScript SPA (dual-accent theme)
280 + db.py schéma unifié (toitka.db) + connexions sources lecture seule
281 + villes.py moteur de canonicalisation des villes (~3 300 variantes → city_map)
282 + typologie.py vocabulaire de types unifié (locatif + vente)
283 + etl.py répliques -> toitka.db (règles de visibilité, cycle de vie)
284 + replicate.py tirage LAN des snapshots de prod (sqlite .backup + rsync)
285 + web.py API JSON FastAPI + service de la SPA
286 + seo.py rendu SEO côté serveur, robots.txt, sitemaps
287 + auth.py SSO KA ID (JWT HS256, stdlib uniquement)
288 + hubprofile.py profil membre lu depuis le hub Groupe KA
289 + hubfav.py favorites.py favoris centralisés (« Mon univers Ka »)
290 +frontend/ SPA React 18 + Vite + TypeScript (thème bi-accent)
291 + src/pages/ Home, Category, Listing, Stats, Profil, Legal
292 + src/components/ ListingCard, MapView, PropertyMap, Icons
293 + src/kamaps/ adaptateur Ka Maps (Mapbox GL 3D)
294 +docs/screenshots/ visite/ (10 JPG 2026-08-28) + mobile/ + desktop/ (webp 2026-08-25)
295 +data/ (ignoré par git) réplicas + toitka.db — plusieurs Go
142 296 ```
143 297
144 −## Running locally
298 +> Le frontend dépend de `@groupe-ka/ka-maps` en `file:../../ka-maps` : le
299 +> framework cartographique partagé du Groupe Ka doit être présent à côté du
300 +> repo (`~/apps/ka-maps` sur le nœud) pour `npm install`.
301 +
302 +---
303 +
304 +## Lancer en local
145 305
146 306 ```bash
147 −# point the ETL at local copies of the source DBs (.env)
148 −python3 run.py etl # build data/toitka.db
149 −python3 run.py serve 8097 # http://localhost:8097
150 −cd frontend && npm install && npm run build # SPA served by the backend
307 +# 1. Config : .env pointe l'ETL vers des copies locales des BD sources
308 +# (jamais commité — voir .gitignore)
309 +# 2. Construire la base unifiée
310 +python3 run.py etl # répliques -> data/toitka.db
311 +# ou en continu :
312 +python3 run.py watch 30 # replicate (si configuré) + etl toutes les 30 min
313 +
314 +# 3. Backend + SPA
315 +python3 run.py serve 8097 # http://localhost:8097
316 +cd frontend && npm install && npm run build # la SPA est servie par le backend
151 317 ```
152 318
153 −## Production (MacLustr cluster)
319 +---
320 +
321 +## Production (cluster MacLustr)
322 +
323 +| Élément | Valeur |
324 +|---|---|
325 +| Nœud | **M3U96a** — `~/apps/toit-ka` |
326 +| Port | **8097** |
327 +| PM2 | `toit-ka-web` (uvicorn :8097) · `toit-ka-etl` (`run.py watch` — replicate + ETL toutes les 30 min) · `toit-ka-ngrok` |
328 +| Tunnel | `ngrok http --url=www.toit-ka.com 8097` |
329 +| Santé | `GET /api/health` → `{"ok": true, "listings": …, "last_etl": …}` |
330 +| Sources | lou-ka (M3U96b) et immo-ka (M4M64a), snapshots lecture seule via LAN |
331 +| Dépôt | **spbgit** (git perso du cluster) — `~/srv/git/toit-ka.git` sur M3U96a |
332 +
333 +Développement **remote-first** comme toutes les apps Ka : la source de vérité
334 +est le repo git sur le nœud, pas une copie laptop.
335 +
336 +---
337 +
338 +## Écosystème Groupe Ka
154 339
155 −- Node **M3U96a**, `~/apps/toit-ka`, PM2: `toit-ka-web` (port 8097),
156 − `toit-ka-etl` (replicate + ETL every 30 min), `toit-ka-ngrok`
157 − (`ngrok http --url=www.toit-ka.com 8097`).
158 −- Health: `GET /api/health`.
340 +Toit-Ka est une application **[Groupe-Ka](https://www.groupe-ka.com)**, aux
341 +côtés de Lou-Ka (location), Immo-Ka (vente), Vrai-Prix, Auto-Ka, Food-Ka,
342 +Resto-Ka, Sorti-Ka, Job-Ka, Trouve-Ka, Créa-Ka, Fabri-Ka et des déclinaisons
343 +canadiennes (House-Ka, Rent-Ka). Identité partagée **KA ID**, favoris
344 +centralisés, design system ka-ui commun.
159 345
160 −## Author
346 +## Auteur
161 347
162 348 **Simon-Pierre Boucher** — [contact@spboucher.ai](mailto:contact@spboucher.ai)
163 349
164 −Toit-Ka is a **Groupe-Ka** application ([groupe-ka.com](https://www.groupe-ka.com)).
165 −Listing data belongs to its respective sources; every card links to the
166 −original ad.
350 +Les données d'annonces appartiennent à leurs sources respectives ; chaque
351 +fiche renvoie vers l'annonce originale.
added docs/screenshots/visite/01-accueil.jpg +0 −0

Binary file not shown.

added docs/screenshots/visite/02-annonce-immo-3Aabbeyandolivier-3A11701844-5334-rue-waverly-m.jpg +0 −0

Binary file not shown.

added docs/screenshots/visite/03-accueil.jpg +0 −0

Binary file not shown.

added docs/screenshots/visite/04-stats.jpg +0 −0

Binary file not shown.

added docs/screenshots/visite/05-profil.jpg +0 −0

Binary file not shown.

added docs/screenshots/visite/06-conditions.jpg +0 −0

Binary file not shown.

added docs/screenshots/visite/07-confidentialite.jpg +0 −0

Binary file not shown.

added docs/screenshots/visite/08-accueil-section-1.jpg +0 −0

Binary file not shown.

added docs/screenshots/visite/09-accueil-section-2.jpg +0 −0

Binary file not shown.

added docs/screenshots/visite/10-accueil-mobile.jpg +0 −0

Binary file not shown.

deleted frontend/tsconfig.tsbuildinfo +0 −1
@@ -1 +0,0 @@
1 −{"root":["./src/app.tsx","./src/account.tsx","./src/api.ts","./src/main.tsx","./src/vite-env.d.ts","./src/components/icons.tsx","./src/components/listingcard.tsx","./src/components/mapview.tsx","./src/components/propertymap.tsx","./src/kamaps/adapter.ts","./src/kamaps/config.ts","./src/kamaps/theme.ts","./src/pages/category.tsx","./src/pages/home.tsx","./src/pages/legal.tsx","./src/pages/listing.tsx","./src/pages/profil.tsx","./src/pages/stats.tsx"],"version":"5.9.3"}
\ No newline at end of file
2