# Implantation SEO par strate — Design

- **Date** : 2026-05-29
- **Projet** : advmfr-next (ADV MFR — fabricant B2B de bijouterie or & argent, vitrine, en/fr)
- **Référence tags** : `~/Documents/Elevaseo/SEO/seo-tags.md` (référentiel exhaustif 2025–2026)
- **Statut** : design validé, en attente de revue spec avant plan d'implémentation

## 1. Contexte & objectif

Le site est une vitrine B2B (pas e-commerce) pour un fabricant de bijouterie haut de gamme,
bilingue en/fr, avec 8 pages : home, about-us, production-process, design-development,
gallery, news-events, sustainability, contact-us.

L'objectif est de déployer une couverture SEO/GEO complète et moderne **par strates de
maturité** : on livre d'abord ce qui est stable et prouvé, puis le moderne recommandé,
puis l'expérimental 2026 — en ne branchant que ce qui est rentable et faible risque.

### Existant (point de départ)

`src/config/seo.ts` centralise déjà :
- title template, defaults OG/Twitter, verifications (env Google/Bing)
- `buildPageMetadata` → title, description, canonical, hreflang réciproque + x-default, keywords
- JSON-LD `Organization` + `WebSite`
- sitemap localisé (`src/app/sitemap.ts`), route OG image (`src/app/[locale]/opengraph-image.tsx`)

**Manquant** : `robots.txt`, `manifest`, posture AI/GEO, headers HTTP de sécurité,
JSON-LD par type de page, familles de tags 2026.

## 2. Décisions de cadrage (validées avec l'utilisateur)

| Sujet | Décision |
|---|---|
| Axe des strates | **Maturité / risque** — stable → moderne → expérimental |
| Posture AI | **Citation autorisée, training bloqué, + `noai`/`noimageai`** sur les images (protection des visuels joaillerie, actif principal) |
| JSON-LD | **Intégré aux strates** (enrichi par type de page) |
| Strate 3 | **Livrer le rentable** (`ai-disclosure`, `Content-Signal`), **stub le spéculatif** (`llms.txt`) |
| Architecture | **A — config centralisée** : éclater `seo.ts` en modules, file-conventions Next, headers `next.config` |
| Namespace SEO | **Option A — par page, sous-objet `seo`** : `AboutUsPage.seo.{title,metaDescription,metaKeywords}`. Global de fallback reste `LocaleLayout.metaKeywords`. Colle aux briefs `SEO/pages/*.md` (1 brief = 1 page). Helpers inchangés (scope du translator sur `.seo`). |
| Thème | **Light uniquement** (`brand.md` : seul thème canonique) → `theme-color` simple, pas de media query dark |

## 3. Architecture des modules

```
src/config/seo/
  index.ts            # ré-exporte tout (préserve les imports existants `@/config/seo`)
  meta.ts             # buildPageMetadata, alternates, OG/twitter (ex-seo.ts)
  robots.ts           # posture AI : listes bots training/citation, directives meta
  ai.ts               # ai-disclosure, noai/noimageai, helpers strate 2/3
  structured-data.ts  # builders JSON-LD par type (Organization, AboutPage, …)

src/config/site.ts        # inchangé (constantes du site)

src/app/robots.txt/route.ts   # Route Handler (PAS robots.ts) → permet `Content-Signal:`
src/app/manifest.ts           # PWA manifest (MANQUANT actuellement)
next.config.ts                # headers() : X-Robots-Tag noimageai, Permissions-Policy, Referrer-Policy
```

**Décision clé — `robots.txt` via Route Handler** : le type `MetadataRoute.Robots` de Next
ne sait pas émettre la ligne non-standard `Content-Signal:`. On utilise donc un Route Handler
`src/app/robots.txt/route.ts` qui génère le fichier en contrôle total (rules par user-agent,
ligne `Content-Signal`, `Sitemap`). Statique (`export const dynamic = "force-static"`).

**Compat** : `src/config/seo/index.ts` ré-exporte tout l'API public actuel pour que les
imports existants (`@/config/seo`) continuent de fonctionner sans changement dans les pages.

**Cascade** : chaque page conserve son `generateMetadata` appelant `buildPageMetadata(...)`,
et injecte son JSON-LD via un builder typé de `structured-data.ts`. L'héritage
layout → page est géré nativement par la Metadata API.

## 4. Strate 1 — Stable & prouvé (zéro risque)

Légende : ✅ déjà en place · ➕ à ajouter · 🔧 à modifier

### Meta / link
- ✅ charset (Next auto), `<html lang>`, title template, description, OG, Twitter, verifications
- ✅ canonical + hreflang réciproque + x-default
- 🔧 `viewport` → ajouter `viewport-fit=cover`
- 🔧 `robots` → string complète : `index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1` (combo AI Overviews prouvé)
- ➕ `theme-color` (light unique), `color-scheme: light`, `author`, `publisher`, `format-detection`
- ➕ `src/app/robots.txt/route.ts` : allow `/`, disallow `/api/`, `Sitemap:`
- ➕ `src/app/manifest.ts` : name, short_name, icons, theme/bg color, display, lang

### JSON-LD
- 🔧 enrichir `Organization` → profil fabricant (adresse postale, contact, sameAs)
- ✅ `WebSite`
- ➕ `BreadcrumbList` par page + `WebPage` de base

## 5. Strate 2 — Moderne recommandé

### Posture AI (décision utilisateur)
- ➕ `robots.txt` — **bloquer training** : GPTBot, Google-Extended, ClaudeBot, CCBot, Bytespider, Meta-ExternalAgent, Applebot-Extended ; **autoriser citation** : OAI-SearchBot, PerplexityBot, Claude-SearchBot, DuckAssistBot
- ➕ meta robots — ajouter `noai, noimageai`
- ➕ `next.config.ts` headers :
  - `X-Robots-Tag: noimageai` sur `/_next/image` + assets images
  - `Permissions-Policy: browsing-topics=(), interest-cohort=()`
  - `Referrer-Policy: strict-origin-when-cross-origin`

### Perf / mobile
- ➕ `preconnect`/`preload` fonts, `apple-touch-icon`, `mobile-web-app-capable` (+ fallback `apple-mobile-web-app-capable`), `apple-mobile-web-app-title`

### JSON-LD par type de page (cœur GEO fabricant)
- `about-us` → `AboutPage`
- `contact-us` → `ContactPage` + `PostalAddress`
- `gallery` → `ImageGallery` / `CollectionPage`
- `news-events` → `Article` + `Event`
- `production-process`, `design-development` → `HowTo` / `WebPage`
- pièces joaillerie → `CreativeWork` / `Product`
- ➕ images dans le sitemap (gallery) — fort pour la joaillerie

## 6. Strate 3 — Expérimental 2026

### Livrer (rentable, faible risque)
- ➕ `ai-disclosure` meta = `content="none"` (contenu humain ; préemptif EU AI Act Article 50, applicable août 2026)
- ➕ `Content-Signal: search=yes, ai-train=no, ai-input=no` dans `robots.txt` (raison du Route Handler)

### Stub / documenté (NON branché)
- 🗒️ `llms.txt` + `<link rel="llms">` + tags `llms:*` : structure + commentaire « anticipation, pas un levier GEO 2026 » (verbatim doc : Mueller/Illyes/Limy.ai)
- 🗒️ `<link rel="c2pa-manifest">` (provenance images), `fediverse:creator`, Bluesky `site.standard.*` : notés comme phases futures

## 7. Validation (par strate)

- `next build` vert + type-check strict (`tsc --noEmit`) après chaque strate
- Vérif manuelle DOM : aucun doublon de meta (cf. incident `charSet` déjà corrigé)
- JSON-LD : passe Rich Results Test (mental + structure schema-dts typée)
- `robots.txt` et `manifest` rendus : lecture du contenu généré
- Skills QA Next.js (best-practices, performance) avant PR — cf. `nextjs-16.x.md` §5

## 8. Découpage de livraison

Une strate = une branche éphémère, mergée en fast-forward dans `dev` puis supprimée
(cf. global-rules §3) :

1. `feature/seo-strate-1-stable`
2. `feature/seo-strate-2-moderne`
3. `feature/seo-strate-3-experimental`

Le refactor de `seo.ts` en modules (`src/config/seo/`) est fait en strate 1 (fondation),
les strates 2 et 3 s'appuient dessus.

## 9. Hors périmètre (YAGNI)

- Dark mode / `theme-color` media queries (thème light unique)
- Stacks e-commerce/product OG complets (pas de vente en ligne)
- `llms.txt` branché, C2PA réel, fediverse, Bluesky (stub seulement)
- CSP en `<meta>` (sera géré côté header serveur si besoin, hors de ce chantier)
