spb/groupe-ka Public
Groupe KA — site du holding + KA ID (compte unique & SSO des 7 plateformes). Next.js 16, SQLite, Google & Apple login.
TypeScript 93.9%
CSS 6%
1// Auteur : Simon-Pierre Boucher — contact@spboucher.ai2import type { Metadata } from "next";3import { Inter, JetBrains_Mono, Space_Grotesk } from "next/font/google";4import UserButton from "./UserButton";5import "./globals.css";67const spaceGrotesk = Space_Grotesk({8 subsets: ["latin"],9 variable: "--font-space-grotesk",10});11const inter = Inter({ subsets: ["latin"], variable: "--font-inter" });12const jetbrains = JetBrains_Mono({13 subsets: ["latin"],14 variable: "--font-jetbrains",15});1617export const metadata: Metadata = {18 metadataBase: new URL("https://www.groupe-ka.com"),19 title: "Groupe KA — holding d’agrégateurs automatisés, sans boîte noire",20 description:21 "Groupe KA est un holding québécois d’agrégateurs de produits et services entièrement automatisés : 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) et Food·Ka (épicerie). Sept plateformes, zéro saisie manuelle.",22 openGraph: {23 title: "Groupe KA — holding d’agrégateurs automatisés, sans boîte noire",24 description:25 "Ka, c’est l’agrégation : des centaines de connecteurs, sept plateformes — Lou·Ka, Immo·Ka, Vrai-Prix, ValoPlex, Auto·Ka, Fabri·Ka et Food·Ka.",26 url: "https://www.groupe-ka.com",27 siteName: "Groupe KA",28 locale: "fr_CA",29 type: "website",30 },31};3233const NAV_ITEMS = [34 { href: "/#flux", label: "L’agrégation" },35 { href: "/#chiffres", label: "Chiffres" },36 { href: "/#produits", label: "Plateformes" },37 { href: "/#socle", label: "Le socle" },38 { href: "/#bots", label: "Les bots" },39 { href: "/#mission", label: "Mission" },40 { href: "/#contact", label: "Contact" },41];4243const TICKER_ITEMS = [44 "·Ka = agréger — mille sites, un seul endroit",45 "Sept agrégateurs · une obsession : la transparence",46 "450+ connecteurs lisent les sources jour et nuit",47 "7 000+ logements à louer agrégés en continu",48 "54 000+ propriétés à vendre, lues à la source",49 "15 900+ voitures usagées chez 124 concessionnaires",50 "281 000+ produits québécois de 1 204 boutiques",51 "23 700+ prix d'épicerie suivis chez 20 bannières",52 "3 747 008 propriétés évaluées au Québec",53 "393 867 plex · 1 733 744 portes",54 "Ka2 & Ka4 cartographient le web québécois — ka2.bot · ka4.bot",55 "Zéro boîte noire — tout est automatisé, rien n'est inventé",56];5758function Wordmark({ size = "header" }: { size?: "header" | "footer" }) {59 const base =60 size === "footer"61 ? "text-[30px] text-paper"62 : "text-[22px] text-ink sm:text-[26px]";63 return (64 <span65 className={`gk-display inline-flex items-baseline gap-[5px] font-bold tracking-[-0.04em] ${base}`}66 >67 Groupe68 {size === "footer" ? (69 <span className="text-lime">KA</span>70 ) : (71 <span className="inline-block -rotate-2 rounded-md bg-ink px-[7px] pb-[2px] text-lime transition-transform duration-200 group-hover:rotate-0">72 KA73 </span>74 )}75 </span>76 );77}7879export default function RootLayout({80 children,81}: Readonly<{ children: React.ReactNode }>) {82 return (83 <html lang="fr">84 <body85 className={`${spaceGrotesk.variable} ${inter.variable} ${jetbrains.variable} bg-paper text-ink`}86 >87 <header className="sticky top-0 z-[1100] border-b-2 border-ink bg-paper md:bg-[rgba(245,243,238,0.88)] md:backdrop-blur-xl">88 <div className="mx-auto flex h-16 max-w-6xl items-center justify-between px-4 sm:px-6">89 <a href="#" className="group" aria-label="Groupe KA — accueil">90 <Wordmark />91 </a>92 <nav aria-label="Navigation principale" className="hidden lg:block">93 <ul className="flex items-center gap-1">94 {NAV_ITEMS.map((item) => (95 <li key={item.href}>96 <a97 href={item.href}98 className="gk-display inline-block rounded-full border-[1.5px] border-transparent px-4 py-[7px] text-[13.5px] font-bold text-ink-2 transition-colors hover:border-ink hover:text-ink"99 >100 {item.label}101 </a>102 </li>103 ))}104 <li className="ml-1">105 <UserButton />106 </li>107 <li>108 <a109 href="mailto:contact@groupe-ka.com"110 className="gk-display ml-1 inline-block rounded-full border-[1.5px] border-ink bg-ink px-4 py-[7px] text-[13.5px] font-bold text-lime transition-colors hover:bg-green-deep"111 >112 Écrivez-nous113 </a>114 </li>115 </ul>116 </nav>117 {/* Mobile : icône compte directement dans le header + menu 100 % CSS */}118 <div className="flex items-center gap-2 lg:hidden">119 <UserButton variant="icon" />120 <input121 type="checkbox"122 id="gk-menu"123 className="peer sr-only"124 aria-label="Ouvrir le menu"125 />126 <label127 htmlFor="gk-menu"128 className="gk-mono flex h-11 w-11 cursor-pointer items-center justify-center rounded-md border-[1.5px] border-ink text-[18px] shadow-[3px_3px_0_rgba(20,24,20,0.25)] select-none"129 >130 ☰131 </label>132 <div className="fixed inset-0 z-[3000] hidden flex-col bg-paper peer-checked:flex">133 <div className="flex h-16 items-center justify-between border-b-2 border-ink px-4">134 <Wordmark />135 <label136 htmlFor="gk-menu"137 className="flex h-11 w-11 cursor-pointer items-center justify-center rounded-md border-[1.5px] border-ink text-[18px] shadow-[3px_3px_0_rgba(20,24,20,0.25)] select-none"138 >139 ✕140 </label>141 </div>142 <nav aria-label="Menu mobile" className="px-6 pt-8">143 <ul>144 {NAV_ITEMS.map((item, i) => (145 <li146 key={item.href}147 className="border-b border-dashed border-[rgba(20,24,20,0.25)]"148 >149 <a150 href={item.href}151 className="gk-display flex items-baseline gap-4 py-5 text-[29px] font-bold tracking-[-0.03em] uppercase"152 >153 <span className="gk-mono text-[12px] font-bold text-green">154 0{i + 1}155 </span>156 {item.label}157 </a>158 </li>159 ))}160 <li className="pt-6">161 <a162 href="mailto:contact@groupe-ka.com"163 className="btn btn-primary w-full"164 >165 contact@groupe-ka.com166 </a>167 </li>168 </ul>169 </nav>170 </div>171 </div>172 </div>173 </header>174175 <div className="ticker" aria-hidden="true">176 <div className="ticker-inner">177 {[0, 1].map((dup) => (178 <span key={dup}>179 {TICKER_ITEMS.map((item) => (180 <span key={item} className="ticker-item">181 {item}182 </span>183 ))}184 </span>185 ))}186 </div>187 </div>188189 {children}190191 <footer id="contact" className="mt-16 bg-ink py-11 text-[13px] text-[rgba(245,243,238,0.75)]">192 <div className="mx-auto max-w-6xl px-4 sm:px-6">193 <Wordmark size="footer" />194 <p className="mt-4 max-w-2xl">195 Holding québécois d'agrégateurs de produits et services196 entièrement automatisés. Des centaines de connecteurs lisent les197 sites à la source, normalisent la donnée et se resynchronisent198 seuls — logements, propriétés, autos, produits d'ici,199 épicerie. Rien d'inventé, tout est traçable.{" "}200 <span className="text-lime">201 ·Ka, c'est le suffixe qui veut dire agréger.202 </span>203 </p>204 <p className="mt-5 max-w-2xl border-l-2 border-lime pl-4 text-[13px]">205 <strong className="text-paper">206 Groupe KA est un agrégateur de contenu : nous ne vendons rien,207 ne louons rien et ne sommes partie à aucune transaction.208 </strong>{" "}209 <a210 href="/avis"211 className="text-lime underline-offset-4 hover:underline"212 >213 En savoir plus →214 </a>215 </p>216 <ul className="gk-mono mt-7 flex flex-wrap gap-x-7 gap-y-3 text-[11px] font-bold tracking-[0.1em] uppercase">217 {[218 ["Lou·Ka", "https://www.lou-ka.com"],219 ["Immo·Ka", "https://www.immo-ka.com"],220 ["Vrai-Prix", "https://www.vrai-prix.com"],221 ["ValoPlex", "https://www.valoplex.com"],222 ["Auto·Ka", "https://www.auto-ka.com"],223 ["Fabri·Ka", "https://www.fabri-ka.com"],224 ["Food·Ka", "https://www.food-ka.com"],225 ["Ka2", "https://www.ka2.bot"],226 ["Ka4", "https://www.ka4.bot"],227 ["Ka6", "https://www.ka6.bot"],228 ].map(([label, href]) => (229 <li key={label}>230 <a231 href={href}232 target="_blank"233 rel="noopener noreferrer"234 className="text-[rgba(245,243,238,0.65)] underline-offset-4 transition-colors hover:text-lime hover:underline hover:decoration-lime"235 >236 {label}237 </a>238 </li>239 ))}240 </ul>241 <div className="mt-8 grid gap-x-8 gap-y-4 border-t border-[rgba(245,243,238,0.15)] pt-7 sm:grid-cols-3">242 {[243 {244 email: "contact@groupe-ka.com",245 role: "Projets, partenariats & données",246 },247 {248 email: "info@groupe-ka.com",249 role: "Médias & questions générales",250 },251 {252 email: "admin@groupe-ka.com",253 role: "Légal, vie privée & Loi 25",254 },255 ].map((c) => (256 <p key={c.email} className="text-[12px]">257 <a258 href={`mailto:${c.email}`}259 className="gk-mono font-bold text-[rgba(245,243,238,0.85)] underline-offset-4 hover:text-lime hover:underline"260 >261 {c.email}262 </a>263 <span className="mt-1 block text-[11px] text-[rgba(245,243,238,0.5)]">264 {c.role}265 </span>266 </p>267 ))}268 </div>269 <p className="gk-mono mt-8 text-[11px] text-[rgba(245,243,238,0.45)]">270 © 2026 Groupe KA — Simon-Pierre Boucher ·{" "}271 <a href="/conditions" className="underline-offset-4 hover:text-lime hover:underline">272 Conditions d'utilisation273 </a>{" "}274 ·{" "}275 <a href="/confidentialite" className="underline-offset-4 hover:text-lime hover:underline">276 Politique de confidentialité277 </a>{" "}278 ·{" "}279 <a href="/loi-25" className="underline-offset-4 hover:text-lime hover:underline">280 Protection des renseignements personnels (Loi 25)281 </a>{" "}282 ·{" "}283 <a href="/bots" className="underline-offset-4 hover:text-lime hover:underline">284 Transparence des robots d'indexation285 </a>{" "}286 ·{" "}287 <a href="/retrait" className="underline-offset-4 hover:text-lime hover:underline">288 Politique de retrait et de révision289 </a>{" "}290 ·{" "}291 <a href="/avis" className="underline-offset-4 hover:text-lime hover:underline">292 Notre rôle d'agrégateur293 </a>{" "}294 · groupe-ka.com295 </p>296 </div>297 </footer>298 </body>299 </html>300 );301}302