feat(house-ka): House-Ka dans l ecosysteme + client KA ID
- sso.ts : client house-ka (redirect https://www.house-ka.com/, secret env KA_SSO_SECRET_HOUSE_KA ajoute a .env.local — backup fait) - ecosystem.json : 15e site (accent pin #0f6b4f, tagline Canada hors Quebec) -> footer, page statut et listes de sites l incluent automatiquement - portail : carte plateforme House-Ka (apres Immo-Ka, cartes renumerotees), ligne du tableau, chips live, figures marquee - live.ts : metriques houseka (total/sources/villes/prix moyen) + totaux - mon-ka / compte / recherche : accents, URLs et domaine house-ka
9 changed files +82 −13
modified
public/ka-agent.js
+1 −1
@@ -587,4 +587,4 @@ | ||
| 587 | 587 | ask(); |
| 588 | 588 | }); |
| 589 | 589 | })(); |
| 590 | −/*KA_ANALYTICS*/(function(){try{if(window.__kaAn)return;window.__kaAn=1;var k="KA_VID",v=localStorage.getItem(k);if(!v){v=Date.now().toString(36)+Math.random().toString(36).slice(2,8);localStorage.setItem(k,v);}var b=function(){var i=new Image();i.src="https://www.administration-ka.com/collect?site=groupe-ka&vid="+v+"&p="+encodeURIComponent(location.pathname)+"&t="+Date.now();};b();setInterval(b,60000);}catch(e){}})(); | |
| 590 | +/*KA_ANALYTICS*/(function(){try{if(window.__kaAnL)return;window.__kaAnL=1;window.__kaSite="groupe-ka";var s=document.createElement('script');s.async=1;s.src="https://www.administration-ka.com/ka-a.js";(document.head||document.documentElement).appendChild(s);}catch(e){}})(); | |
modified
src/app/compte/page.tsx
+2 −0
@@ -35,6 +35,7 @@ export const dynamic = "force-dynamic"; | ||
| 35 | 35 | const PLATFORM_URLS: Record<string, string> = { |
| 36 | 36 | "lou-ka": "https://www.lou-ka.com", |
| 37 | 37 | "immo-ka": "https://www.immo-ka.com", |
| 38 | + "house-ka": "https://www.house-ka.com", | |
| 38 | 39 | "vrai-prix": "https://www.vrai-prix.com", |
| 39 | 40 | valoplex: "https://www.valoplex.com", |
| 40 | 41 | "auto-ka": "https://www.auto-ka.com", |
@@ -66,6 +67,7 @@ function fmtDate(iso: string | null): string { | ||
| 66 | 67 | const APP_ACCENTS: Record<string, string> = { |
| 67 | 68 | "lou-ka": "#d9f26b", |
| 68 | 69 | "immo-ka": "#e23744", |
| 70 | + "house-ka": "#0f6b4f", | |
| 69 | 71 | "vrai-prix": "#ff5148", |
| 70 | 72 | valoplex: "#ff9f45", |
| 71 | 73 | "auto-ka": "#ff5a2a", |
modified
src/app/figures.tsx
+1 −0
@@ -14,6 +14,7 @@ export const FIG_PLATFORMS: { | ||
| 14 | 14 | }[] = [ |
| 15 | 15 | { name: "Lou·Ka", accent: "#ff6a00", domain: "lou-ka.com" }, |
| 16 | 16 | { name: "Immo·Ka", accent: "#e23744", domain: "immo-ka.com" }, |
| 17 | + { name: "House·Ka", accent: "#0f6b4f", domain: "house-ka.com" }, | |
| 17 | 18 | { name: "Vrai-Prix", accent: "#ff5148", domain: "vrai-prix.com" }, |
| 18 | 19 | { name: "ValoPlex", accent: "#ff9f45", domain: "valoplex.com" }, |
| 19 | 20 | { name: "Auto·Ka", accent: "#ff5a2a", domain: "auto-ka.com" }, |
modified
src/app/mon-ka/page.tsx
+1 −0
@@ -28,6 +28,7 @@ export const dynamic = "force-dynamic"; | ||
| 28 | 28 | const APP_ACCENTS: Record<string, string> = { |
| 29 | 29 | "lou-ka": "#d9f26b", |
| 30 | 30 | "immo-ka": "#e23744", |
| 31 | + "house-ka": "#0f6b4f", | |
| 31 | 32 | "vrai-prix": "#ff5148", |
| 32 | 33 | valoplex: "#ff9f45", |
| 33 | 34 | "auto-ka": "#ff5a2a", |
modified
src/app/page.tsx
+43 −11
@@ -81,6 +81,26 @@ const PRODUCTS: Product[] = [ | ||
| 81 | 81 | }, |
| 82 | 82 | { |
| 83 | 83 | num: "03", |
| 84 | + markLeft: "House", | |
| 85 | + markBoxed: "Ka", | |
| 86 | + accent: "#0f6b4f", | |
| 87 | + inkbox: "#14201a", | |
| 88 | + field: "Immobilier — Canada", | |
| 89 | + domain: "www.house-ka.com", | |
| 90 | + url: "https://www.house-ka.com", | |
| 91 | + tagline: "Every home for sale in Canada. One place.", | |
| 92 | + description: | |
| 93 | + "Le jumeau anglophone d'Immo·Ka pour le reste du Canada — toutes les provinces sauf le Québec. Réseaux nationaux (Century 21) et sites de courtage branchés au flux CREA DDF, agrégés à la source, normalisés et géolocalisés ; chaque fiche renvoie à l'inscription originale du courtier.", | |
| 94 | + chips: ["260 000+ fiches", "10 provinces & territoires", "30 connecteurs"], | |
| 95 | + features: [ | |
| 96 | + "Recherche unifiée en anglais : ville, type, prix, chambres", | |
| 97 | + "Vue carte pan-canadienne (Ka Maps), grappes pondérées par prix", | |
| 98 | + "Taux hypothécaires réels des banques + calculateur canadien", | |
| 99 | + "Commerces de proximité adaptés à chaque province", | |
| 100 | + ], | |
| 101 | + }, | |
| 102 | + { | |
| 103 | + num: "04", | |
| 84 | 104 | markLeft: "Vrai", |
| 85 | 105 | markBoxed: "Prix", |
| 86 | 106 | accent: "#ff5148", |
@@ -100,7 +120,7 @@ const PRODUCTS: Product[] = [ | ||
| 100 | 120 | ], |
| 101 | 121 | }, |
| 102 | 122 | { |
| 103 | − num: "04", | |
| 123 | + num: "05", | |
| 104 | 124 | markLeft: "Valo", |
| 105 | 125 | markBoxed: "Plex", |
| 106 | 126 | accent: "#ff9f45", |
@@ -120,7 +140,7 @@ const PRODUCTS: Product[] = [ | ||
| 120 | 140 | ], |
| 121 | 141 | }, |
| 122 | 142 | { |
| 123 | − num: "05", | |
| 143 | + num: "06", | |
| 124 | 144 | markLeft: "Auto", |
| 125 | 145 | markBoxed: "Ka", |
| 126 | 146 | accent: "#ff5a2a", |
@@ -140,7 +160,7 @@ const PRODUCTS: Product[] = [ | ||
| 140 | 160 | ], |
| 141 | 161 | }, |
| 142 | 162 | { |
| 143 | − num: "06", | |
| 163 | + num: "07", | |
| 144 | 164 | markLeft: "Fabri", |
| 145 | 165 | markBoxed: "Ka", |
| 146 | 166 | accent: "#C4532E", |
@@ -160,7 +180,7 @@ const PRODUCTS: Product[] = [ | ||
| 160 | 180 | ], |
| 161 | 181 | }, |
| 162 | 182 | { |
| 163 | − num: "07", | |
| 183 | + num: "08", | |
| 164 | 184 | markLeft: "Food", |
| 165 | 185 | markBoxed: "Ka", |
| 166 | 186 | accent: "#d9f26b", |
@@ -180,7 +200,7 @@ const PRODUCTS: Product[] = [ | ||
| 180 | 200 | ], |
| 181 | 201 | }, |
| 182 | 202 | { |
| 183 | − num: "08", | |
| 203 | + num: "09", | |
| 184 | 204 | markLeft: "Resto", |
| 185 | 205 | markBoxed: "Ka", |
| 186 | 206 | accent: "#ffc53d", |
@@ -201,7 +221,7 @@ const PRODUCTS: Product[] = [ | ||
| 201 | 221 | isNew: true, |
| 202 | 222 | }, |
| 203 | 223 | { |
| 204 | − num: "09", | |
| 224 | + num: "10", | |
| 205 | 225 | markLeft: "Sorti", |
| 206 | 226 | markBoxed: "Ka", |
| 207 | 227 | accent: "#ff6a00", |
@@ -222,7 +242,7 @@ const PRODUCTS: Product[] = [ | ||
| 222 | 242 | isNew: true, |
| 223 | 243 | }, |
| 224 | 244 | { |
| 225 | − num: "10", | |
| 245 | + num: "11", | |
| 226 | 246 | markLeft: "Créa", |
| 227 | 247 | markBoxed: "Ka", |
| 228 | 248 | accent: "#7da2ff", |
@@ -243,7 +263,7 @@ const PRODUCTS: Product[] = [ | ||
| 243 | 263 | isNew: true, |
| 244 | 264 | }, |
| 245 | 265 | { |
| 246 | − num: "11", | |
| 266 | + num: "12", | |
| 247 | 267 | markLeft: "Job", |
| 248 | 268 | markBoxed: "Ka", |
| 249 | 269 | accent: "#6fd0e0", |
@@ -333,17 +353,17 @@ const BOTS: Bot[] = [ | ||
| 333 | 353 | |
| 334 | 354 | const MANIFESTO = [ |
| 335 | 355 | { |
| 336 | − num: "01", | |
| 356 | + num: "13", | |
| 337 | 357 | title: "Zéro boîte noire", |
| 338 | 358 | body: "Un score magique n'est pas une réponse. Chaque estimation montre ses comparables, ses ajustements en dollars et sa fourchette d'incertitude. Si le calcul ne peut pas être montré, il ne sort pas.", |
| 339 | 359 | }, |
| 340 | 360 | { |
| 341 | − num: "02", | |
| 361 | + num: "14", | |
| 342 | 362 | title: "Données réelles", |
| 343 | 363 | body: "Rôles d'évaluation foncière, ventes publiées, annonces vérifiées à la source. Aucun prix inventé : quand la donnée n'existe pas, on affiche qu'elle n'existe pas. Validé sur des ventes jamais vues, pas promis.", |
| 344 | 364 | }, |
| 345 | 365 | { |
| 346 | − num: "03", | |
| 366 | + num: "15", | |
| 347 | 367 | title: "Indépendance", |
| 348 | 368 | body: "Aucun courtier ni annonceur ne paie pour influencer un résultat. Pas de traceur publicitaire, pas de revente de données. Le français d'abord, le Québec comme terrain, la Loi 25 comme plancher.", |
| 349 | 369 | }, |
@@ -368,6 +388,12 @@ const socleRows = (m: LiveMetrics): [string, string, string, string][] => [ | ||
| 368 | 388 | `${m.immoka.sources} connecteurs d'agences + détection des ventes`, |
| 369 | 389 | "www.immo-ka.com", |
| 370 | 390 | ], |
| 391 | + [ | |
| 392 | + "House·Ka", | |
| 393 | + "Propriétés à vendre — Canada hors Québec", | |
| 394 | + `${m.houseka.sources} connecteurs + réseau Century 21 national`, | |
| 395 | + "www.house-ka.com", | |
| 396 | + ], | |
| 371 | 397 | [ |
| 372 | 398 | "Vrai-Prix", |
| 373 | 399 | "Résidentiel — tout le Québec", |
@@ -626,6 +652,12 @@ function liveChips(m: LiveMetrics): Record<string, string[]> { | ||
| 626 | 652 | `${fmtInt(m.immoka.cities)} villes`, |
| 627 | 653 | `Prix moyen ${fmtInt(m.immoka.avgPrice)} $`, |
| 628 | 654 | ], |
| 655 | + "www.house-ka.com": [ | |
| 656 | + `${fmtPlus(m.houseka.total)} fiches`, | |
| 657 | + `${m.houseka.sources} connecteurs`, | |
| 658 | + `${fmtInt(m.houseka.cities)} villes`, | |
| 659 | + `Prix moyen ${fmtInt(m.houseka.avgPrice)} $`, | |
| 660 | + ], | |
| 629 | 661 | "www.auto-ka.com": [ |
| 630 | 662 | `${fmtPlus(m.autoka.total)} véhicules`, |
| 631 | 663 | `${m.autoka.sources} concessionnaires`, |
modified
src/app/recherche/page.tsx
+1 −0
@@ -19,6 +19,7 @@ export const metadata: Metadata = { | ||
| 19 | 19 | const SITES: [string, string][] = [ |
| 20 | 20 | ["www.lou-ka.com", "Lou·Ka"], |
| 21 | 21 | ["www.immo-ka.com", "Immo·Ka"], |
| 22 | + ["www.house-ka.com", "House·Ka"], | |
| 22 | 23 | ["www.vrai-prix.com", "Vrai-Prix"], |
| 23 | 24 | ["www.toit-ka.com", "Toit·Ka"], |
| 24 | 25 | ["www.auto-ka.com", "Auto·Ka"], |
modified
src/ka/ecosystem.json
+10 −0
@@ -84,6 +84,16 @@ | ||
| 84 | 84 | "onAccent": "#ffffff", |
| 85 | 85 | "tagline": "Toutes les propriétés à vendre" |
| 86 | 86 | }, |
| 87 | + { | |
| 88 | + "id": "house-ka", | |
| 89 | + "wordmark": "House·Ka", | |
| 90 | + "domain": "www.house-ka.com", | |
| 91 | + "accent": "#0f6b4f", | |
| 92 | + "accentSoft": "#dcefe6", | |
| 93 | + "accentDeep": "#0a4a37", | |
| 94 | + "onAccent": "#ffffff", | |
| 95 | + "tagline": "Maisons à vendre — Canada hors Québec (EN)" | |
| 96 | + }, | |
| 87 | 97 | { |
| 88 | 98 | "id": "vrai-prix", |
| 89 | 99 | "wordmark": "Vrai-Prix", |
modified
src/lib/live.ts
+18 −1
@@ -103,6 +103,13 @@ export type LiveMetrics = { | ||
| 103 | 103 | }; |
| 104 | 104 | syncs: SyncHealth; |
| 105 | 105 | }; |
| 106 | + houseka: { | |
| 107 | + total: number; | |
| 108 | + sources: number; | |
| 109 | + cities: number; | |
| 110 | + avgPrice: number; | |
| 111 | + syncs: SyncHealth; | |
| 112 | + }; | |
| 106 | 113 | autoka: { |
| 107 | 114 | total: number; |
| 108 | 115 | sources: number; |
@@ -201,7 +208,7 @@ const topCities = (o: Json | null): { city: string; n: number }[] => { | ||
| 201 | 208 | }; |
| 202 | 209 | |
| 203 | 210 | export async function getLiveMetrics(): Promise<LiveMetrics> { |
| 204 | − const [lou, immo, auto, fab, food, resto, sorti, crea, trouve, vp, job] = | |
| 211 | + const [lou, immo, auto, fab, food, resto, sorti, crea, trouve, vp, job, house] = | |
| 205 | 212 | await Promise.all([ |
| 206 | 213 | fetchJson("https://www.lou-ka.com/api/stats"), |
| 207 | 214 | fetchJson("https://www.immo-ka.com/api/stats"), |
@@ -214,6 +221,7 @@ export async function getLiveMetrics(): Promise<LiveMetrics> { | ||
| 214 | 221 | fetchJson("https://www.trouve-ka.com/api/status"), |
| 215 | 222 | fetchJson("https://www.vrai-prix.com/api/stats"), |
| 216 | 223 | fetchJson("https://www.job-ka.com/api/stats"), |
| 224 | + fetchJson("https://www.house-ka.com/api/stats"), | |
| 217 | 225 | ]); |
| 218 | 226 | |
| 219 | 227 | const m: LiveMetrics = { |
@@ -242,6 +250,13 @@ export async function getLiveMetrics(): Promise<LiveMetrics> { | ||
| 242 | 250 | }, |
| 243 | 251 | syncs: syncSummary(immo), |
| 244 | 252 | }, |
| 253 | + houseka: { | |
| 254 | + total: num(house, "total", 260279), | |
| 255 | + sources: num(house, "sources", 30), | |
| 256 | + cities: num(house, "cities", 5921), | |
| 257 | + avgPrice: num(house, "avg_price", 934000), | |
| 258 | + syncs: syncSummary(house), | |
| 259 | + }, | |
| 245 | 260 | autoka: { |
| 246 | 261 | total: num(auto, "total", 17098), |
| 247 | 262 | sources: num(auto, "sources", 125), |
@@ -327,6 +342,7 @@ export async function getLiveMetrics(): Promise<LiveMetrics> { | ||
| 327 | 342 | m.totals.connectors = |
| 328 | 343 | m.louka.sources + |
| 329 | 344 | m.immoka.sources + |
| 345 | + m.houseka.sources + | |
| 330 | 346 | m.autoka.sources + |
| 331 | 347 | m.foodka.sources + |
| 332 | 348 | m.restoka.chains + |
@@ -335,6 +351,7 @@ export async function getLiveMetrics(): Promise<LiveMetrics> { | ||
| 335 | 351 | m.totals.items = |
| 336 | 352 | m.louka.total + |
| 337 | 353 | m.immoka.total + |
| 354 | + m.houseka.total + | |
| 338 | 355 | m.autoka.total + |
| 339 | 356 | m.fabrika.products + |
| 340 | 357 | m.foodka.total + |
modified
src/lib/sso.ts
+5 −0
@@ -17,6 +17,11 @@ export const SSO_CLIENTS: Record< | ||
| 17 | 17 | redirectPrefixes: ["https://www.immo-ka.com/"], |
| 18 | 18 | secretEnv: "KA_SSO_SECRET_IMMO_KA", |
| 19 | 19 | }, |
| 20 | + "house-ka": { | |
| 21 | + label: "House·Ka", | |
| 22 | + redirectPrefixes: ["https://www.house-ka.com/"], | |
| 23 | + secretEnv: "KA_SSO_SECRET_HOUSE_KA", | |
| 24 | + }, | |
| 20 | 25 | "crea-ka": { |
| 21 | 26 | label: "Créa·Ka", |
| 22 | 27 | redirectPrefixes: ["https://www.crea-ka.com/", "http://localhost:8160/"], |
| 23 | 28 | |