SPB Git forge

spb/rent-ka

Public
8commits 1branches 0releases
7.4 MBsize
maindefault branch
19 days agolast push
Python 68.8% TypeScript 18.6% CSS 8.7% JavaScript 3.3% HTML 0.6%
10.4 KB

# SPEC — Transformation lou-ka → Rent-Ka (LOCKED DECISIONS)

Rent-Ka = English rental-listings aggregator for ALL of Canada EXCEPT Québec (Ontario first — 5,861 ON listings already seeded in the node DB; national expansion via platform client registries comes right after launch). Sister sites: Lou-Ka (QC rentals), House-Ka (ROC homes for sale).

# Identity

  • Site name: Rent-Ka · wordmark Rent·Ka · domain www.rent-ka.com
  • BASE_URL = "https://www.rent-ka.com", SITE_NAME = "Rent-Ka"
  • FastAPI: title "Rent-Ka API", description "Rental listings aggregator — Canada (outside Québec)"
  • Tagline (frontend + SEO): "Apartments and homes for rent across Canada."
  • UA: RentKaBot/1.0 (+https://www.rent-ka.com/bot; contact@spboucher.ai) (replaces every LouKaBot)
  • Language: en-CA everywhere (backend SEO strings, frontend copy, <html lang="en-CA">)
  • Python package: rename louka/rentka/ (all imports, uvicorn.run("rentka.web:app", ...))
  • DB path: data/rentka.db (db.py DB_PATH)
  • Env prefix: LOUKA_*RENTKA_* everywhere. LOUKA_ONTARIO gate is DELETED (not renamed). LOUKA_BASE_URLRENTKA_BASE_URL.
  • kaid site id: kaid.init("rent-ka"); hubfav URL https://www.rent-ka.com/listing/{uid}; KA_CLIENT_ID default "rent-ka".
  • ecosystem.json (frontend/src/ka/ecosystem.json): ADD entry (backend web.py:940/983 looks it up — required): {"id":"rent-ka","wordmark":"Rent·Ka","domain":"www.rent-ka.com","accent":"#2456e6","accentSoft":"#e9efff","accentDeep":"#1738a8","onAccent":"#ffffff","tagline":"Rentals across Canada"}

# Routes (English — backend seo.py/web.py AND frontend App.tsx/KAID_CONF must match)

  • Listing page: /listing/{uid} (was /logement/{uid})
  • Cities index: /cities (was /villes); city page: /city/{slug} and /city/{slug}/{type_slug}
  • Keep: /stats, /sources, /contact, /bot, /g/{sourceId}
  • /confidentialite/privacy, /conditions/terms
  • /profil/profile, /favoris/favorites, /bienvenue/welcome, /gestion/manage, /passerelle/:uid/gateway/:uid, /juste-valeur/fair-value, /ka-scores stays /ka-scores
  • DELETED routes/pages: /court-terme* (short-term subsystem), /demenageurs (movers, QC dataset)
  • web.py _CLIENT_ROUTES = {"profile","favorites","manage","welcome","bot","contact","fair-value","ka-scores"}, _CLIENT_PREFIXES = ("u/","gateway/")
  • Sitemaps: sitemap-pages.xml, sitemap-cities.xml, sitemap-listings-{n}.xml (drop sitemap-ct-*)
  • index.html KAID_CONF: {card:"a[href^='/listing/']",detail:"^/listing/(.+)$",entity:"listing"}

# Canonical unit types (English enum — replaces the QC "n½" system)

Studio | 1 bedroom | 2 bedrooms | 3 bedrooms | 4 bedrooms | 5+ bedrooms | Loft | Penthouse | Condo | Townhouse | House | Room

  • normalize.normalize_unit_type: map French AND English input INTO this enum (reverse of today: → "1 bedroom", → "2 bedrooms", (n-2) bedrooms, 6½+ → "4 bedrooms"; "bachelor" → Studio; "maison de ville|townhouse|mdv" → Townhouse; "chambre|room" → Room)
  • bedrooms_from_unit_type: Studio/Loft→0, Room→1, "n bedroom(s)"→n, "5+ bedrooms"→5, Penthouse/Condo/Townhouse/House→None
  • Slugs (seo.slugify): "1-bedroom", "2-bedrooms", "5-plus-bedrooms", "studio", "room", … (kill the ½ → -1-2 special case)
  • quality.py rule 5: unit != "Room" (was "Chambre")

# Geography / scope

  • Scope = Canada minus QC. quality.evaluate: DELETE pause-ontario rule; ADD if d.get("province") == "QC": reasons.append("outside-scope-quebec").
  • schema.Listing default province: "ON" (connectors should set explicitly; platform registries gain an optional per-client "province" key, default "ON").
  • schema.finalize + geocode: per-province bbox dict for all 12 (BC,AB,SK,MB,ON,NB,NS,PE,NL,YT,NT,NU), fallback = Canada bbox (41.6–83.2 N, −141.0…−52.5 E).
  • geocode.py: REMOVE all Adresses Québec (MERN) code, _BBOX_QUEBEC, _VILLES_QUEBEC; keep Nominatim (1 r/s) as primary; run_batch() becomes a loop over Nominatim resolve() (keep the batch CLI signature working). state= full province name from a PROVINCE_NAMES dict. Cache keys: prefix "{prov.lower()}|" for every province.
  • web.py /api/stats: replace the _VILLES_GM Montréal buckets with per-province counts: response gains "provinces": {"ON": n, "BC": n, ...} (keep "total"/existing top-level keys the frontend Ticker needs — frontend Ticker will read provinces).
  • web.py: expose province in listing JSON (list + detail + geojson props) and as a filter param province= on /api/listings & /api/search; add it to /api/facets.

# Features KEPT (translate UI strings to English where user-facing)

core pipeline (schema/db/ingest/normalize/dedup/quality/seo/web), fairvalue, kascores + environment + poi (pure OSM, national), building ("Building passport"), recycled ("Re-listed units"), history, imgcheck, managers (+serpapi_client), marketstats, statsdash, statsfiche (prune deleted-layer panels), kapdf (shared, keep verbatim), hiver.py → keep, rename user-facing label to "Winter Score" (works Canada-wide), KA ID/accounts/auth/profile/hubfav/hubprofile (site id rent-ka), fixtures.py, textmine.py → KEEP and make BILINGUAL: keep French regexes, add English equivalents for the high-value facts (heat/hydro/electricity/water included, parking, pets, furnished, laundry, A/C, elevator, balcony, dishwasher, no smoking, lease length, available date).

# Features DELETED (backend module + web.py route + pdfgen section + statsextra block + frontend component)

  • hydro.py (/api/hydro, HydroEstimation.tsx) — Hydro-Québec
  • rdl.py (/api/rdl, RegistreLoyers.tsx) — QC rent registry
  • tal.py (/api/tal, HistoriqueTAL.tsx) — QC tribunal
  • gaz.py (/api/gaz, EssenceProche.tsx) — gazquebec
  • air.py (/api/air, QualiteAir.tsx) — RSQAQ (maybe AQHI later)
  • inondation.py (/api/inondation, RisqueInondation.tsx) — BDZI
  • quartier.py (quartier block in /api/listings/{uid}, QuartierBlock.tsx) — QC census DB (rebuild later)
  • commerces.py (/api/commerces, CommercesProches.tsx) + transit.db — QC banners/transit
  • coutreel.py (/api/listings/{uid}/cout-reel, CoutReel.tsx) — backbone was Hydro-Québec
  • demenageurs.py (+ /demenageurs SSR + Demenageurs.tsx + data/demenageurs.json)
  • shortterm/ ENTIRELY (+ data/sources_ct.json, data/hotels_engines.json, ct_web router, seo ctdb import + /court-terme SSR + sitemap-ct, frontend Ct*.tsx, CourtTerme*.tsx, ctapi.ts, kamaps/ctAdapter.ts)
  • MetroLignes.tsx usage in MapView.tsx + MapSearch.tsx (Montréal métro overlay)
  • ingest.watch: remove hydro.precompute and tal.precompute steps (keep the rest incl. quartier→REMOVE too since module deleted)

# Connectors

  • KEEP the 65 ON connectors: remove the _ONTARIO = ... line and every disabled = not _ONTARIO / "disabled": not _ONTARIO (connector simply enabled). Platform generators (rentcafe/appfolio/rentsyncgw/buildium/liftsystem) keep reading their data/*.json registries; add support for optional per-client "province" (default "ON").
  • KEEP + WIDEN the 11 national connectors (akelius, boardwalk, capreit, centurion, cogir, hazelview, interrent, metcap, minto, morguard, realstar): invert the gate — ROC is the default, DELETE the QC branches/city lists entirely; cover every non-QC province the landlord operates in (their sites list cities — keep existing ON lists, extend with the connector's own city discovery when it has one; set province per city).
  • KEEP national portals (not gated): apartments_com, rentals_ca, zumper, kijiji, fb_marketplace + actors/. Change their default regions/cities env fallbacks from QC to ROC metros: Toronto, Ottawa, Mississauga, Hamilton, London, Kitchener-Waterloo, Windsor, Vancouver, Victoria, Surrey, Burnaby, Calgary, Edmonton, Winnipeg, Saskatoon, Regina, Halifax, Moncton, Fredericton, Charlottetown, St. John's. (env names now RENTKA_*)
  • DELETE all other (~300) QC-only connector modules AND their data/sources.json entries. sources.json keeps: the 65 ON entries (status back to "actif", note_pause removed), the national/portal entries, minus all QC ones. Update _comment.
  • KEEP helpers: base.py, _resilient.py, _detailutil.py; DELETE _livya.py/_planpoint.py if only QC connectors import them (check first).
  • tests/: keep test_{normalize,quality,search,fairvalue,kascores,textmine}.py UPDATED to the new enum/rules; delete test fixtures + recorded cassettes of deleted connectors (tests/fixtures is 842 MB — purge everything belonging to deleted sources).

# Frontend design (DIFFERENT from Lou-Ka orange and House-Ka pine/Fraunces)

  • Keep the shared KA token system (frontend/src/ka/tokens.css UNTOUCHED — shared asset).
  • styles.css overrides: accent = cobalt --accent:#2456e6; --accent-soft:#e9efff; --accent-deep:#1738a8; --on-accent:#ffffff
  • Display font: "Bricolage Grotesque" (Google Fonts, weights 400..800) replaces Space Grotesk in index.html + --font-display override in styles.css. Body stays Inter.
  • Header wordmark Rent·Ka (the ·Ka styled with accent), tagline "Apartments and homes for rent across Canada."
  • The frontend should feel like its OWN site, not a translated Lou-Ka: new Home hero (search + "Browse by province" section with the province counts from /api/stats.provinces, featured cities grid), reordered nav, English MobileTabBar (Search/Map/Saved/Profile). Keep the detail-page section ORDER standard (gallery → price/address → description → amenities → practical details → analyses → map → KA Scores → footer; DOM order = visual order on ALL breakpoints, NEVER order:/column-reverse — Groupe KA standard 2026-08-19).
  • Listing page keeps (in order): gallery, price+FairValueBadge, description, amenities, practical details, PriceAnalysis, HistoriqueLouka→"Listing history", ImmeubleBloc→"Building passport", GestionnaireBloc→"Property manager", recycled block, ListingMap3D, KaScoresBlock, HiverScore→"Winter Score". All QC blocks removed (list above).
  • Ticker: per-province counts (ON · BC · AB · …) from /api/stats.provinces.
  • Footer: keep KaFooter with siteId="rent-ka" (entry added to ecosystem.json).
  • ALL user-facing text in English (en-CA). Currency format $1,495. Dates en-CA.

# Deployment (for reference — done on node M4M36 afterwards)

  • pm2: rent-ka-web (run.py serve 8125), rent-ka-sync (run.py watch 60), rent-ka-ngrok (ngrok http --url=www.rent-ka.com 8125)
  • git origin gitsrv:srv/git/rent-ka.git