SEO : canonical, JSON-LD Organization+WebSite, robots.txt, sitemap.xml, template de titres
- layout : alternates.canonical ./ (par route), og:url harmonisé, html lang fr-CA, title template %s | Groupe KA, données structurées schema.org (holding + 13 plateformes, WebSite inLanguage fr-CA) - src/app/robots.ts : allow / ; disallow /api/, /compte, /sso ; lien sitemap - src/app/sitemap.ts : accueil + 9 pages publiques - pages : suffixe — Groupe KA retiré des titres (géré par le template) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
17 changed files +133 −17
modified
src/app/avis/page.tsx
+1 −1
@@ -2,7 +2,7 @@ | ||
| 2 | 2 | import type { Metadata } from "next"; |
| 3 | 3 | |
| 4 | 4 | export const metadata: Metadata = { |
| 5 | − title: "Avis : notre rôle d'agrégateur — Groupe KA", | |
| 5 | + title: "Avis : notre rôle d'agrégateur", | |
| 6 | 6 | description: |
| 7 | 7 | "Groupe KA est un agrégateur de contenu : nous ne vendons rien, ne louons rien et ne sommes partie à aucune transaction. Aucun contrat ne se forme entre vous et Groupe KA du fait de la consultation de nos plateformes.", |
| 8 | 8 | }; |
modified
src/app/bots/page.tsx
+1 −1
@@ -2,7 +2,7 @@ | ||
| 2 | 2 | import type { Metadata } from "next"; |
| 3 | 3 | |
| 4 | 4 | export const metadata: Metadata = { |
| 5 | − title: "Déclaration de transparence — Robots d'indexation — Groupe KA", | |
| 5 | + title: "Déclaration de transparence — Robots d'indexation", | |
| 6 | 6 | description: |
| 7 | 7 | "Fonctionnement des robots d'indexation du Groupe KA (ka·2, ka·4, ka·6) : données publiques uniquement, respect de robots.txt, charge minimale, retrait sur demande — zéro boîte noire.", |
| 8 | 8 | }; |
modified
src/app/compte/carte/page.tsx
+1 −1
@@ -12,7 +12,7 @@ import { roleCard } from "@/lib/roles"; | ||
| 12 | 12 | import PrintButton from "./PrintButton"; |
| 13 | 13 | |
| 14 | 14 | export const metadata: Metadata = { |
| 15 | − title: "Carte imprimable | Groupe KA", | |
| 15 | + title: "Carte imprimable", | |
| 16 | 16 | robots: { index: false }, |
| 17 | 17 | }; |
| 18 | 18 | |
modified
src/app/compte/page.tsx
+1 −1
@@ -24,7 +24,7 @@ import ProfileForm from "./ProfileForm"; | ||
| 24 | 24 | import CopyText from "./CopyText"; |
| 25 | 25 | |
| 26 | 26 | export const metadata: Metadata = { |
| 27 | − title: "Mon KA ID | Groupe KA", | |
| 27 | + title: "Mon KA ID", | |
| 28 | 28 | description: "Votre compte unique pour les plateformes du Groupe KA.", |
| 29 | 29 | }; |
| 30 | 30 | |
modified
src/app/conditions/page.tsx
+1 −1
@@ -2,7 +2,7 @@ | ||
| 2 | 2 | import type { Metadata } from "next"; |
| 3 | 3 | |
| 4 | 4 | export const metadata: Metadata = { |
| 5 | − title: "Conditions d’utilisation — Groupe KA", | |
| 5 | + title: "Conditions d’utilisation", | |
| 6 | 6 | description: |
| 7 | 7 | "Conditions d’utilisation du site groupe-ka.com et principes communs aux plateformes du Groupe KA.", |
| 8 | 8 | }; |
modified
src/app/confidentialite/page.tsx
+1 −1
@@ -2,7 +2,7 @@ | ||
| 2 | 2 | import type { Metadata } from "next"; |
| 3 | 3 | |
| 4 | 4 | export const metadata: Metadata = { |
| 5 | − title: "Politique de confidentialité — Groupe KA", | |
| 5 | + title: "Politique de confidentialité", | |
| 6 | 6 | description: |
| 7 | 7 | "Politique de confidentialité du site groupe-ka.com — Loi 25, aucun traceur publicitaire, aucun témoin tiers.", |
| 8 | 8 | }; |
modified
src/app/connexion/page.tsx
+1 −1
@@ -6,7 +6,7 @@ import { SSO_CLIENTS } from "@/lib/sso"; | ||
| 6 | 6 | import AuthForm from "./AuthForm"; |
| 7 | 7 | |
| 8 | 8 | export const metadata: Metadata = { |
| 9 | − title: "KA ID — connexion | Groupe KA", | |
| 9 | + title: "KA ID — connexion", | |
| 10 | 10 | description: |
| 11 | 11 | "Un seul compte pour toutes les plateformes du Groupe KA : créez votre KA ID ou continuez avec Google.", |
| 12 | 12 | }; |
modified
src/app/layout.tsx
+69 −3
@@ -17,14 +17,20 @@ const jetbrains = JetBrains_Mono({ | ||
| 17 | 17 | |
| 18 | 18 | export const metadata: Metadata = { |
| 19 | 19 | metadataBase: new URL("https://www.groupe-ka.com"), |
| 20 | − title: "Groupe KA — holding d’agrégateurs automatisés, sans boîte noire", | |
| 20 | + title: { | |
| 21 | + default: "Groupe KA — holding d’agrégateurs automatisés, sans boîte noire", | |
| 22 | + template: "%s | Groupe KA", | |
| 23 | + }, | |
| 24 | + alternates: { | |
| 25 | + canonical: "./", | |
| 26 | + }, | |
| 21 | 27 | description: |
| 22 | 28 | "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.", |
| 23 | 29 | openGraph: { |
| 24 | 30 | title: "Groupe KA — holding d’agrégateurs automatisés, sans boîte noire", |
| 25 | 31 | description: |
| 26 | 32 | "Ka, c’est l’agrégation : des centaines de connecteurs, dix plateformes — Lou·Ka, Immo·Ka, Vrai-Prix, ValoPlex, Auto·Ka, Fabri·Ka, Food·Ka, Resto·Ka, Sorti·Ka, Créa·Ka et Job·Ka.", |
| 27 | − url: "https://www.groupe-ka.com", | |
| 33 | + url: "./", | |
| 28 | 34 | siteName: "Groupe KA", |
| 29 | 35 | locale: "fr_CA", |
| 30 | 36 | type: "website", |
@@ -49,6 +55,62 @@ export const viewport: Viewport = { | ||
| 49 | 55 | viewportFit: "cover", |
| 50 | 56 | }; |
| 51 | 57 | |
| 58 | +// Données structurées schema.org (SEO) : le holding + ses plateformes, | |
| 59 | +// alignées sur la liste réellement affichée dans le pied de page. | |
| 60 | +const SITE_URL = "https://www.groupe-ka.com/"; | |
| 61 | +const PLATEFORMES: [string, string][] = [ | |
| 62 | + ["Trouve·Ka", "https://www.trouve-ka.com"], | |
| 63 | + ["Lou·Ka", "https://www.lou-ka.com"], | |
| 64 | + ["Immo·Ka", "https://www.immo-ka.com"], | |
| 65 | + ["Vrai-Prix", "https://www.vrai-prix.com"], | |
| 66 | + ["ValoPlex", "https://www.valoplex.com"], | |
| 67 | + ["Auto·Ka", "https://www.auto-ka.com"], | |
| 68 | + ["Fabri·Ka", "https://www.fabri-ka.com"], | |
| 69 | + ["Food·Ka", "https://www.food-ka.com"], | |
| 70 | + ["Resto·Ka", "https://www.resto-ka.com"], | |
| 71 | + ["Sorti·Ka", "https://www.sorti-ka.com"], | |
| 72 | + ["Créa·Ka", "https://www.crea-ka.com"], | |
| 73 | + ["API·Ka", "https://www.api-ka.com"], | |
| 74 | + ["Job·Ka", "https://www.job-ka.com"], | |
| 75 | +]; | |
| 76 | +const JSON_LD = { | |
| 77 | + "@context": "https://schema.org", | |
| 78 | + "@graph": [ | |
| 79 | + { | |
| 80 | + "@type": "Organization", | |
| 81 | + "@id": `${SITE_URL}#organization`, | |
| 82 | + name: "Groupe KA", | |
| 83 | + url: SITE_URL, | |
| 84 | + logo: `${SITE_URL}og.png`, | |
| 85 | + description: | |
| 86 | + "Holding québécois d’agrégateurs de produits et services entièrement automatisés — zéro saisie manuelle, zéro boîte noire.", | |
| 87 | + email: "contact@groupe-ka.com", | |
| 88 | + areaServed: { | |
| 89 | + "@type": "AdministrativeArea", | |
| 90 | + name: "Québec, Canada", | |
| 91 | + }, | |
| 92 | + brand: PLATEFORMES.map(([name, url]) => ({ | |
| 93 | + "@type": "Brand", | |
| 94 | + name, | |
| 95 | + url, | |
| 96 | + })), | |
| 97 | + subOrganization: PLATEFORMES.map(([name, url]) => ({ | |
| 98 | + "@type": "Organization", | |
| 99 | + name, | |
| 100 | + url, | |
| 101 | + })), | |
| 102 | + }, | |
| 103 | + { | |
| 104 | + "@type": "WebSite", | |
| 105 | + "@id": `${SITE_URL}#website`, | |
| 106 | + name: "Groupe KA", | |
| 107 | + url: SITE_URL, | |
| 108 | + inLanguage: "fr-CA", | |
| 109 | + publisher: { "@id": `${SITE_URL}#organization` }, | |
| 110 | + }, | |
| 111 | + ], | |
| 112 | +}; | |
| 113 | + | |
| 52 | 114 | const NAV_ITEMS = [ |
| 53 | 115 | { href: "/#trouve-ka", label: "Moteur" }, |
| 54 | 116 | { href: "/#flux", label: "L’agrégation" }, |
@@ -113,10 +175,14 @@ export default async function RootLayout({ | ||
| 113 | 175 | }: Readonly<{ children: React.ReactNode }>) { |
| 114 | 176 | const ticker = tickerItems(await getLiveMetrics()); |
| 115 | 177 | return ( |
| 116 | − <html lang="fr"> | |
| 178 | + <html lang="fr-CA"> | |
| 117 | 179 | <body |
| 118 | 180 | className={`${spaceGrotesk.variable} ${inter.variable} ${jetbrains.variable} bg-paper text-ink`} |
| 119 | 181 | > |
| 182 | + <script | |
| 183 | + type="application/ld+json" | |
| 184 | + dangerouslySetInnerHTML={{ __html: JSON.stringify(JSON_LD) }} | |
| 185 | + /> | |
| 120 | 186 | <header className="sticky top-0 z-[var(--z-header)] border-b-2 border-ink bg-paper md:bg-[rgba(245,243,238,0.88)] md:backdrop-blur-xl"> |
| 121 | 187 | <div className="mx-auto flex h-16 max-w-6xl items-center justify-between px-4 sm:px-6"> |
| 122 | 188 | <a href="#" className="group" aria-label="Groupe KA — accueil"> |
modified
src/app/loi-25/page.tsx
+1 −1
@@ -2,7 +2,7 @@ | ||
| 2 | 2 | import type { Metadata } from "next"; |
| 3 | 3 | |
| 4 | 4 | export const metadata: Metadata = { |
| 5 | − title: "Protection des renseignements personnels (Loi 25) — Groupe KA", | |
| 5 | + title: "Protection des renseignements personnels (Loi 25)", | |
| 6 | 6 | description: |
| 7 | 7 | "Comment Groupe KA recueille, utilise, conserve et protège les renseignements personnels, conformément à la Loi 25 du Québec — agrégateur de contenu public, demandes d'accès, de rectification et de retrait.", |
| 8 | 8 | }; |
modified
src/app/m/[kaId]/page.tsx
+1 −1
@@ -7,7 +7,7 @@ import { db } from "@/lib/db"; | ||
| 7 | 7 | import { roleLabel } from "@/lib/roles"; |
| 8 | 8 | |
| 9 | 9 | export const metadata: Metadata = { |
| 10 | − title: "Identification de membre | Groupe KA", | |
| 10 | + title: "Identification de membre", | |
| 11 | 11 | description: "Identification d'un membre du Groupe KA par son KA-ID.", |
| 12 | 12 | robots: { index: false }, |
| 13 | 13 | }; |
modified
src/app/retrait/page.tsx
+1 −1
@@ -2,7 +2,7 @@ | ||
| 2 | 2 | import type { Metadata } from "next"; |
| 3 | 3 | |
| 4 | 4 | export const metadata: Metadata = { |
| 5 | − title: "Politique de retrait et de révision — Groupe KA", | |
| 5 | + title: "Politique de retrait et de révision", | |
| 6 | 6 | description: |
| 7 | 7 | "Comment demander le retrait d'une annonce indexée sur les plateformes du Groupe KA, la révision d'une estimation ou l'arrêt de la couverture d'une propriété sur Vrai-Prix et ValoPlex. Sans frais, traité en 48 à 72 heures ouvrables.", |
| 8 | 8 | }; |
added
src/app/robots.ts
+17 −0
@@ -0,0 +1,17 @@ | ||
| 1 | +// Auteur : Simon-Pierre Boucher — contact@spboucher.ai | |
| 2 | +// robots.txt généré par Next (Metadata API) — SEO 2026-08-22. | |
| 3 | +import type { MetadataRoute } from "next"; | |
| 4 | + | |
| 5 | +export default function robots(): MetadataRoute.Robots { | |
| 6 | + return { | |
| 7 | + rules: [ | |
| 8 | + { | |
| 9 | + userAgent: "*", | |
| 10 | + allow: "/", | |
| 11 | + // Routes techniques ou de compte : rien à indexer. | |
| 12 | + disallow: ["/api/", "/compte", "/sso"], | |
| 13 | + }, | |
| 14 | + ], | |
| 15 | + sitemap: "https://www.groupe-ka.com/sitemap.xml", | |
| 16 | + }; | |
| 17 | +} | |
added
src/app/sitemap.ts
+33 −0
@@ -0,0 +1,33 @@ | ||
| 1 | +// Auteur : Simon-Pierre Boucher — contact@spboucher.ai | |
| 2 | +// sitemap.xml généré par Next (Metadata API) — SEO 2026-08-22. | |
| 3 | +// Pages publiques statiques seulement (les fiches /m et /u sont des pages | |
| 4 | +// de membre, /compte et /connexion des pages de session : exclues). | |
| 5 | +import type { MetadataRoute } from "next"; | |
| 6 | + | |
| 7 | +const BASE = "https://www.groupe-ka.com"; | |
| 8 | + | |
| 9 | +export default function sitemap(): MetadataRoute.Sitemap { | |
| 10 | + const lastModified = new Date(); | |
| 11 | + const pages: { | |
| 12 | + path: string; | |
| 13 | + changeFrequency: MetadataRoute.Sitemap[number]["changeFrequency"]; | |
| 14 | + priority: number; | |
| 15 | + }[] = [ | |
| 16 | + { path: "/", changeFrequency: "daily", priority: 1 }, | |
| 17 | + { path: "/stats", changeFrequency: "daily", priority: 0.8 }, | |
| 18 | + { path: "/status", changeFrequency: "daily", priority: 0.6 }, | |
| 19 | + { path: "/telecharger", changeFrequency: "weekly", priority: 0.7 }, | |
| 20 | + { path: "/avis", changeFrequency: "monthly", priority: 0.5 }, | |
| 21 | + { path: "/bots", changeFrequency: "monthly", priority: 0.5 }, | |
| 22 | + { path: "/retrait", changeFrequency: "monthly", priority: 0.4 }, | |
| 23 | + { path: "/conditions", changeFrequency: "yearly", priority: 0.3 }, | |
| 24 | + { path: "/confidentialite", changeFrequency: "yearly", priority: 0.3 }, | |
| 25 | + { path: "/loi-25", changeFrequency: "yearly", priority: 0.3 }, | |
| 26 | + ]; | |
| 27 | + return pages.map(({ path, changeFrequency, priority }) => ({ | |
| 28 | + url: `${BASE}${path}`, | |
| 29 | + lastModified, | |
| 30 | + changeFrequency, | |
| 31 | + priority, | |
| 32 | + })); | |
| 33 | +} | |
modified
src/app/stats/page.tsx
+1 −1
@@ -20,7 +20,7 @@ import { | ||
| 20 | 20 | import EcoStatsClient from "./eco-client"; |
| 21 | 21 | |
| 22 | 22 | export const metadata: Metadata = { |
| 23 | − title: "Statistiques de l'écosystème — Groupe KA", | |
| 23 | + title: "Statistiques de l'écosystème", | |
| 24 | 24 | description: |
| 25 | 25 | "Tableau de bord maître du Groupe KA : indicateurs consolidés en direct des plateformes de l'écosystème ·Ka, classement par volume, croissance comparée, résumé par plateforme et rapports écosystème PDF.", |
| 26 | 26 | }; |
modified
src/app/status/page.tsx
+1 −1
@@ -16,7 +16,7 @@ import { | ||
| 16 | 16 | export const dynamic = "force-dynamic"; |
| 17 | 17 | |
| 18 | 18 | export const metadata: Metadata = { |
| 19 | − title: "Statut des services — Groupe KA", | |
| 19 | + title: "Statut des services", | |
| 20 | 20 | description: |
| 21 | 21 | "État en direct et historique de disponibilité des plateformes de l'écosystème Groupe KA : vérifications aux 5 minutes, barres 24 h et 90 jours, latences.", |
| 22 | 22 | }; |
modified
src/app/telecharger/page.tsx
+1 −1
@@ -5,7 +5,7 @@ | ||
| 5 | 5 | import type { Metadata } from "next"; |
| 6 | 6 | |
| 7 | 7 | export const metadata: Metadata = { |
| 8 | − title: "Télécharger l'app KA — Groupe KA", | |
| 8 | + title: "Télécharger l'app KA", | |
| 9 | 9 | description: |
| 10 | 10 | "KA, la super-app de l'écosystème Groupe KA : 12 univers, recherche universelle, carte 2D/3D, favoris, KA Agent. iPhone (TestFlight), Android (APK direct) et macOS (DMG notarié).", |
| 11 | 11 | }; |
modified
src/app/u/[kaId]/page.tsx
+1 −1
@@ -12,7 +12,7 @@ import { | ||
| 12 | 12 | import { roleCard } from "@/lib/roles"; |
| 13 | 13 | |
| 14 | 14 | export const metadata: Metadata = { |
| 15 | − title: "Profil de membre | Groupe KA", | |
| 15 | + title: "Profil de membre", | |
| 16 | 16 | description: "Profil public d'un membre du Groupe KA.", |
| 17 | 17 | }; |
| 18 | 18 | |
| 19 | 19 | |