SPB Git forge

spb/groupe-ka

Public

Groupe KA — site du holding + KA ID (compte unique & SSO des 7 plateformes). Next.js 16, SQLite, Google & Apple login.

81commits 1branches 0releases
89.2 MBsize
maindefault branch
22 days agolast push
TypeScript 70.4% HTML 18.4% JavaScript 4% Python 3.8% CSS 3.4%

pivot Trouve-Ka : accueil (section phare, ticker, socle), métadonnées, loi-25, tagline ecosystem, replis live.ts — et rapport quotidien enrichi des stats du moteur de recherche du groupe

Simon-Pierre Boucher committed 1 mo ago (Aug 23, 2026) parent 9448411

6 changed files +65 −40

modified scripts/rapport-quotidien.mjs +20 −3
@@ -14,6 +14,7 @@ import { fileURLToPath } from "node:url";
14 14 const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
15 15 const RAPPORTS_DIR = path.join(ROOT, "data", "rapports");
16 16 const API_KA = "http://127.0.0.1:8000";
17 +const TROUVE_KA = "https://www.trouve-ka.com";
17 18 const SITE = "http://127.0.0.1:8110";
18 19 const MODEL = "claude-sonnet-4-6";
19 20 const HEADLESS_SHELL = path.join(
@@ -68,10 +69,11 @@ async function tryJson(url, timeoutMs) {
68 69 // ---------- 1. collecte des données API·Ka ----------
69 70
70 71 async function collecter(dateRapport) {
71 − const [health, dash7j, runsRes, ...statsParService] = await Promise.all([
72 + const [health, dash7j, runsRes, trouveStatus, ...statsParService] = await Promise.all([
72 73 tryJson(`${API_KA}/health`),
73 74 tryJson(`${API_KA}/api/stats/dashboard?period=7j`),
74 75 tryJson(`${API_KA}/api/v1/runs?limit=60`),
76 + tryJson(`${TROUVE_KA}/api/status`, 10000),
75 77 ...SERVICES.map(([s]) => tryJson(`${API_KA}/api/v1/${s}/stats`)),
76 78 ]);
77 79
@@ -119,6 +121,19 @@ async function collecter(dateRapport) {
119 121 records_total: services.reduce((a, s) => a + (s.total ?? 0), 0),
120 122 },
121 123 connecteurs: health?.data?.connectors ?? null,
124 + // Moteur de recherche interne (pivot 2026-08-23 : index limité aux sites du groupe)
125 + moteur_recherche: trouveStatus
126 + ? {
127 + plateforme: "Trouve·Ka",
128 + pages_indexees: trouveStatus.pages_indexed ?? null,
129 + sites_indexes: trouveStatus.domains_count ?? null,
130 + indexees_derniere_heure: trouveStatus.indexed_last_hour ?? null,
131 + erreurs_derniere_heure: trouveStatus.errors_last_hour ?? null,
132 + file_de_crawl: trouveStatus.frontier_pending ?? null,
133 + robot: trouveStatus.crawler_state ?? null,
134 + recherche_ok: trouveStatus.search_ok ?? null,
135 + }
136 + : null,
122 137 api_7j: {
123 138 appels: kpi("calls"),
124 139 latence_ms: kpi("latency"),
@@ -144,6 +159,8 @@ Chaque matin, tu écris LE rapport de la nuit : la collecte automatisée de 02:0
144 159
145 160 Cadences de rafraîchissement des sources (à connaître avant de crier à l'anomalie) : la plupart des plateformes resynchronisent leurs sources plusieurs fois par jour, mais Resto·Ka se synchronise UNE FOIS PAR SEMAINE (un compte d'enregistrements identique plusieurs jours d'affilée y est NORMAL, pas un cache figé) et Créa·Ka une fois par jour. Ne signale une stagnation en vigilance que si elle dépasse la cadence attendue de la plateforme.
146 161
162 +Le groupe a aussi son moteur de recherche : Trouve·Ka. Depuis le 23 août 2026, il n'indexe QUE les pages des sites de l'écosystème KA (pivot assumé — avant cette date il indexait le web québécois ouvert, ne compare pas avec ces anciens chiffres). Ses données du matin sont dans "moteur_recherche" (pages indexées, sites couverts, rythme horaire, file de crawl, état du robot). L'index se remplit progressivement depuis le pivot : une croissance rapide des pages indexées est NORMALE ces premières semaines et mérite d'être racontée comme telle. Ajoute un fait saillant Trouve·Ka quand il a quelque chose à dire (montée de l'index, robot arrêté, recherche dégradée → vigilance).
163 +
147 164 Règles absolues :
148 165 - Tu n'inventes AUCUN chiffre : tout vient des données fournies. Si une donnée est nulle/absente, tu le dis ou tu n'en parles pas.
149 166 - Nombres en format canadien-français (espace pour les milliers, virgule décimale) : « 45 073 », « 2,3 % ».
@@ -159,9 +176,9 @@ Règles absolues :
159 176 "vigilance": ["points à surveiller (collectes échouées, baisses inhabituelles, connecteurs dégradés) — liste vide si tout va bien"],
160 177 "mot_de_la_fin": "une phrase de clôture avec du panache"
161 178 }
162 −- "faits_saillants" : une entrée par plateforme qui a quelque chose à dire (6 à 9 entrées).
179 +- "faits_saillants" : une entrée par plateforme qui a quelque chose à dire (6 à 10 entrées, Trouve·Ka compris s'il a du nouveau).
163 180 - "analyse" : 2 ou 3 sections.
164 −- Utilise les vrais noms : Lou·Ka, Immo·Ka, Auto·Ka, Fabri·Ka, Food·Ka, Resto·Ka, Sorti·Ka, Créa·Ka, Job·Ka, API·Ka.`;
181 +- Utilise les vrais noms : Lou·Ka, Immo·Ka, Auto·Ka, Fabri·Ka, Food·Ka, Resto·Ka, Sorti·Ka, Créa·Ka, Job·Ka, API·Ka, Trouve·Ka.`;
165 182
166 183 async function rediger(snapshot, dateRapport) {
167 184 const key = process.env.ANTHROPIC_API_KEY;
modified src/app/layout.tsx +2 −2
@@ -26,7 +26,7 @@ export const metadata: Metadata = {
26 26 canonical: "./",
27 27 },
28 28 description:
29 − "Groupe KA est un holding québécois d’agrégateurs de produits et services entièrement automatisés : Trouve·Ka (moteur de recherche du web québécois), Lou·Ka (location), Immo·Ka (propriétés à vendre), Vrai-Prix (valeur résidentielle), ValoPlex (plex), Auto·Ka (voitures usagées), Fabri·Ka (produits québécois), Food·Ka (épicerie), Resto·Ka (restaurants, menus et prix), Sorti·Ka (sorties et événements) Créa·Ka (créateurs d’ici) et Job·Ka (emplois). Zéro saisie manuelle.",
29 + "Groupe KA est un holding québécois d’agrégateurs de produits et services entièrement automatisés : Trouve·Ka (le moteur de recherche de l’écosystème), Lou·Ka (location), Immo·Ka (propriétés à vendre), Vrai-Prix (valeur résidentielle), ValoPlex (plex), Auto·Ka (voitures usagées), Fabri·Ka (produits québécois), Food·Ka (épicerie), Resto·Ka (restaurants, menus et prix), Sorti·Ka (sorties et événements) Créa·Ka (créateurs d’ici) et Job·Ka (emplois). Zéro saisie manuelle.",
30 30 openGraph: {
31 31 title: "Groupe KA — holding d’agrégateurs automatisés, sans boîte noire",
32 32 description:
@@ -137,7 +137,7 @@ const MOBILE_NAV_ITEMS = [
137 137 // Ticker construit sur les métriques LIVE des plateformes (src/lib/live.ts).
138 138 const tickerItems = (m: LiveMetrics): string[] => [
139 139 "·Ka = agréger — mille sites, un seul endroit",
140 − `Trouve·Ka cherche le Québec — ${fmtPlus(m.trouveka.pages)} pages du web d'ici indexées`,
140 + `Trouve·Ka cherche tout l'écosystème — ${fmtPlus(m.trouveka.pages)} pages des sites ·Ka indexées`,
141 141 `Trouve·Ka indexe ${fmtInt(m.trouveka.indexedLastHour)} pages à l'heure — le robot ne dort pas`,
142 142 "Dix agrégateurs · une obsession : la transparence",
143 143 `${fmtInt(m.totals.connectors)}+ connecteurs lisent les sources jour et nuit`,
modified src/app/loi-25/page.tsx +2 −2
@@ -14,8 +14,8 @@ const APPS_ROWS: [string, string, string, string, string][] = [
14 14 [
15 15 "Trouve·Ka",
16 16 "www.trouve-ka.com",
17 − "Moteur de recherche — web québécois",
18 − "Pages web publiquement accessibles du web québécois, indexées par un robot dédié",
17 + "Moteur de recherche — écosystème Groupe KA",
18 + "Pages publiques des sites du Groupe KA, indexées par un robot dédié à partir de leurs sitemaps",
19 19 "Renseignements rendus publics par les sites indexés; extraits et liens vers la page originale seulement",
20 20 ],
21 21 [
modified src/app/page.tsx +33 −27
@@ -333,7 +333,7 @@ const MANIFESTO = [
333 333 const socleRows = (m: LiveMetrics): [string, string, string, string][] => [
334 334 [
335 335 "Trouve·Ka",
336 − "Recherche — tout le web québécois",
336 + "Recherche — tout l'écosystème KA",
337 337 `Crawler dédié + index plein texte — ${fmtPlus(m.trouveka.pages)} pages`,
338 338 "www.trouve-ka.com",
339 339 ],
@@ -738,15 +738,16 @@ export default async function Home() {
738 738 kicker="Le produit phare · moteur de recherche"
739 739 title={
740 740 <>
741 − Trouve·Ka. <span className="hl">Cherche le Québec.</span>
741 + Trouve·Ka. <span className="hl">Cherche tout le groupe.</span>
742 742 </>
743 743 }
744 744 >
745 745 <p className="mt-3 max-w-xl text-[14.5px] text-ink-2">
746 − Les agrégateurs ·Ka couvrent chacun un marché. Trouve·Ka couvre tout
747 − le reste : c&apos;est le moteur de recherche du groupe, dont
748 − l&apos;index est bâti exclusivement sur le web québécois — son robot
749 − le parcourt jour et nuit et n&apos;indexe que lui.
746 + Les agrégateurs ·Ka couvrent chacun un marché. Trouve·Ka les
747 + rassemble : c&apos;est le moteur de recherche du groupe, dont
748 + l&apos;index est bâti exclusivement sur les sites de
749 + l&apos;écosystème — son robot les parcourt jour et nuit, guidé par
750 + leurs sitemaps, et n&apos;indexe qu&apos;eux.
750 751 </p>
751 752 <div className="mt-7 grid items-stretch gap-6 lg:grid-cols-[minmax(0,1.15fr)_minmax(0,1fr)]">
752 753 <article className="gk-card gk-card-hover p-5 sm:p-7">
@@ -766,7 +767,7 @@ export default async function Home() {
766 767 </span>
767 768 </h3>
768 769 <p className="gk-display mt-3 text-[17px] font-bold uppercase tracking-[-0.01em]">
769 − Tout le web québécois, dans une seule barre de recherche.
770 + Tout l&apos;écosystème KA, dans une seule barre de recherche.
770 771 </p>
771 772 {/* Barre de recherche factice — l'objet lui-même */}
772 773 <div
@@ -775,7 +776,7 @@ export default async function Home() {
775 776 >
776 777 <span className="gk-mono text-[15px] font-bold">⌕</span>
777 778 <span className="gk-mono flex-1 truncate text-[12.5px] text-ink-3">
778 − poutine · plex à vendre · microbrasserie · Gaspésie…
779 + 4½ à Limoilou · plex à vendre · emploi infirmier · resto Gaspésie…
779 780 </span>
780 781 <span
781 782 className="gk-display rounded-full bg-ink px-4 py-[5px] text-[12.5px] font-bold"
@@ -789,18 +790,18 @@ export default async function Home() {
789 790 {fmtPlus(m.trouveka.pages)} pages indexées
790 791 </span>
791 792 <span className="stat-chip !text-[11px]">
792 − {fmtPlus(m.trouveka.domains)} domaines d&apos;ici
793 + {fmtInt(m.trouveka.domains)} sites du groupe
793 794 </span>
794 795 <span className="stat-chip !text-[11px]">
795 796 {fmtInt(m.trouveka.indexedLastHour)} pages indexées / heure
796 797 </span>
797 − <span className="stat-chip !text-[11px]">100 % Québec</span>
798 + <span className="stat-chip !text-[11px]">100 % Groupe KA</span>
798 799 </div>
799 800 <ul className="mt-5 space-y-2 border-t-[1.5px] border-dashed border-[rgba(20,24,20,0.25)] pt-5">
800 801 {[
801 − "Résultats 100 % québécois — l'index ne contient que le web d'ici",
802 + "Résultats 100 % Groupe KA — logements, propriétés, emplois, restos, événements, produits, véhicules, créateurs",
802 803 `État du moteur public : ${fmtInt(m.trouveka.frontierPending)} pages en file de crawl, ${fmtDec(m.trouveka.embeddingCoverage * 100)} % de l'index couvert par la recherche sémantique`,
803 − "Soumettez votre site — l'indexation sur demande, ouverte à tous",
804 + "Une fiche publiée sur un site ·Ka devient cherchable en quelques secondes",
804 805 "Robot dédié, documenté, qui respecte robots.txt",
805 806 ].map((f) => (
806 807 <li key={f} className="flex gap-3 text-[13.5px] text-ink-2">
@@ -812,14 +813,19 @@ export default async function Home() {
812 813 </li>
813 814 ))}
814 815 </ul>
815 − <a
816 − href="https://www.trouve-ka.com"
817 − target="_blank"
818 − rel="noopener noreferrer"
819 − className="btn btn-primary mt-6 w-full sm:w-auto"
820 − >
821 − Chercher sur www.trouve-ka.com ↗
822 − </a>
816 + <div className="mt-6 flex flex-wrap gap-3">
817 + <a
818 + href="https://www.trouve-ka.com"
819 + target="_blank"
820 + rel="noopener noreferrer"
821 + className="btn btn-primary w-full sm:w-auto"
822 + >
823 + Chercher sur www.trouve-ka.com ↗
824 + </a>
825 + <a href="/recherche" className="btn w-full sm:w-auto">
826 + Chercher sans quitter groupe-ka.com
827 + </a>
828 + </div>
823 829 </article>
824 830 <div className="gk-card !bg-ink p-6 text-paper sm:p-7">
825 831 <p className="kicker !text-lime">
@@ -830,19 +836,19 @@ export default async function Home() {
830 836 <br />
831 837 cherchent le monde.
832 838 <br />
833 − <span className="text-lime">Trouve·Ka cherche le Québec.</span>
839 + <span className="text-lime">Trouve·Ka cherche le Groupe KA.</span>
834 840 </p>
835 841 <p className="mt-4 max-w-md text-[13.5px] text-[rgba(245,243,238,0.75)]">
836 − Un commerce de Rimouski, une érablière de Lanaudière, un blogue
837 − de Limoilou : noyés dans un index mondial, introuvables. Dans un
838 − index qui ne contient que le Québec, ils sont en première page.
839 − C&apos;est l&apos;agrégation poussée à sa conclusion logique —
840 − indexer la province entière.
842 + Un 4½ sur Lou·Ka, une érablière sur Fabri·Ka, un festival sur
843 + Sorti·Ka : des millions de fiches réparties sur les sites du
844 + groupe — et une seule barre pour toutes les trouver. C&apos;est
845 + l&apos;agrégation poussée à sa conclusion logique — un index
846 + maison pour tout l&apos;écosystème.
841 847 </p>
842 848 <ul className="mt-5 space-y-2 border-t border-[rgba(245,243,238,0.15)] pt-5 text-[13px] text-[rgba(245,243,238,0.75)]">
843 849 {[
844 850 "Crawler maison + index de recherche dédié",
845 − "Nourri par les éclaireurs ka2, ka4 et ka6",
851 + "Nourri par les sitemaps des sites de l'écosystème",
846 852 "Zéro publicité, zéro profilage — comme tout le groupe",
847 853 ].map((f) => (
848 854 <li key={f} className="flex gap-3">
modified src/ka/ecosystem.json +1 −1
@@ -62,7 +62,7 @@
62 62 "accentSoft": "#e7f2fd",
63 63 "accentDeep": "#14508f",
64 64 "onAccent": "#ffffff",
65 − "tagline": "Le moteur de recherche du web québécois"
65 + "tagline": "Le moteur de recherche du Groupe KA"
66 66 },
67 67 {
68 68 "id": "lou-ka",
modified src/lib/live.ts +7 −5
@@ -291,13 +291,15 @@ export async function getLiveMetrics(): Promise<LiveMetrics> {
291 291 mega: num(crea, "by_tier.mega", 36),
292 292 },
293 293 },
294 + // Pivot 2026-08-23 : Trouve·Ka indexe les 14 sites du Groupe KA
295 + // (replis = instantané du jour du pivot, index en croissance continue).
294 296 trouveka: {
295 − pages: num(trouve, "pages_indexed", 1170502),
296 − domains: num(trouve, "domains_count", 72280),
297 + pages: num(trouve, "pages_indexed", 7200),
298 + domains: num(trouve, "domains_count", 14),
297 299 running: (trouve?.crawler_state ?? "running") === "running",
298 − indexedLastHour: num(trouve, "indexed_last_hour", 22505),
299 − errorsLastHour: num(trouve, "errors_last_hour", 257),
300 − frontierPending: num(trouve, "frontier_pending", 2500000),
300 + indexedLastHour: num(trouve, "indexed_last_hour", 6600),
301 + errorsLastHour: num(trouve, "errors_last_hour", 26),
302 + frontierPending: num(trouve, "frontier_pending", 4584180),
301 303 embeddingCoverage: num(trouve, "embedding_coverage", 1.0),
302 304 },
303 305 vraiprix: {
304 306