feat(seo): auditer les vingt landings et ouvrir l'intention EVJF/EVG

Audit page par page des landings et vitrines (SEO-LP-23) : cohérence
problématique → solution → preuve, propreté des modules et des CTA,
alignement FR/EN.

- soiree-jeux et sortie-entre-amis annoncent désormais la page de
  l'événement et non « le vote » : Kwiz est hors BATCHABLE_SERVICE_TYPES
  et ne peut pas être posé vide, le CTA promettait donc une ressource que
  le parcours ne crée pas ;
- repas place Kontrib en tête, conformément à son H1, sa problématique et
  son CTA qui promettent tous la liste ;
- suppression de la clé morte partage-depenses.modules.kontrib (FR/EN) ;
- dix méta ramenées dans leurs bornes ;
- previews EN localisées : Leeds et le Lake District remplacent Lyon et
  Annecy, kount.vitrine.preview_title suit ;
- la priorité sitemap devient une règle de cluster documentée dans
  landings.ts plutôt qu'un jugement page par page ; six liens
  réciproques portent le minimum entrant à deux.

Nouvelle landing evjf-evg (SEO-LP-24), une seule page pour les deux
intentions comme voyage/vacances-entre-amis. Son angle propre est la
personne fêtée : résultats Kwiz masqués jusqu'à publication et choix des
personnes concernées par chaque dépense dans Kount. La FAQ traite
frontalement l'absence d'encaissement.

La landing mariage est écartée et la décision consignée : sans RSVP,
sans liste d'invités ni encaissement, les deux tâches dominantes de
cette intention restent hors de portée.

Catalogue : 21 landings, 42 URL, 15 cas d'usage Hub, 64 pages pré-rendues.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Gautier Stefanini 2026-08-16 09:31:05 +00:00
parent f25cd0a882
commit 626e510767
16 changed files with 231 additions and 63 deletions

View file

@ -23,7 +23,7 @@ G4/G6 sont alignés ; les contrats ciblés et la recette globale sont décrits d
`docs/DESIGN_SYSTEM.md`. G3 reste `TODO` et indépendant de la refonte.
**Surfaces publiques (VIS-08) :** la homepage (`Landing.tsx`), le template des six
vitrines (`ServiceVitrine.tsx`) et celui des 40 URL SEO (`SeoLanding.tsx`) utilisent
vitrines (`ServiceVitrine.tsx`) et celui des 42 URL SEO (`SeoLanding.tsx`) utilisent
les tokens `max-w-public`/`px-gutter`, `max-w-editorial`, `surface-*`, `ink-*`,
`line-*`, rayons et élévations du système. Ne pas réintroduire une largeur, une
gouttière ou un gris Tailwind historique dans ces trois sources ; le contrat
@ -215,11 +215,11 @@ kankwa/
- **Pré-rendu au build (SSG), pas de SSR** : `frontend/scripts/prerender.mjs` rejoue chaque page publique dans un Chromium headless après `vite build`. **Bilingue** : chaque route de `seo-routes.json` est rendue deux fois (page Puppeteer `frPage` / `enPage`, localStorage isolé) → `dist/<route>/index.html` (fr, défaut) + `dist/<route>/index.en.html` (en). Les landing pages ont des chemins distincts par langue, donc un seul `index.html` chacune. Les crawlers sans JS (Facebook, WhatsApp, LinkedIn, Bing, GPTBot…) reçoivent du vrai HTML dans la bonne langue. Le pré-rendu attend `#root h1`, pas le premier enfant de `#root` : sans cela une page dont le contenu est différé figerait son écran dattente dans le HTML statique.
- **Source unique des pages publiques** : `frontend/src/shared/config/seo-routes.json` (pages statiques) + `landings.json` (pages dacquisition). Lus par le pré-rendu, `api/routers/sitemap.py` (hreflang alternates fr/en) **et** `frontend/scripts/static-server.mjs`. Ajouter une page là = elle est pré-rendue et inscrite dans le sitemap. Le blog et `articles.json` ont été retirés : ne pas recréer un second système éditorial.
- **Landing pages d'acquisition (G6)** : `landings.json` déclare pour chaque page son chemin par langue, son cluster (`organiser`/`outils`/`comparatif`), son `primaryService`, les modules montrés et le maillage (`related`). Un seul template, `shared/components/SeoLanding.tsx` + `hooks/useLandingSeo.ts`, rend les quarante URL ; tout le contenu, y compris le scénario de preview contextualisé, vit dans `i18n/locales/{fr,en}/landing.json`. **Ne jamais créer de composant par landing** ni écrire ses routes à la main : `App.tsx` et `Navbar.tsx` les génèrent depuis la config. Les entrées `editorial: true` ajoutent des sections longues, des dates et un JSON-LD `Article` dans ce même template. Le CTA passe par `useCreateEventLink(primaryService)` et la preuve produit est générée depuis `ServiceProductPreview` — même brique que les vitrines. Une landing mono-module conserve l'aperçu détaillé de ce service ; dès que `modules` en déclare plusieurs, la preview compose exactement cette liste ordonnée avec les libellés courts `preview.modules.<id>`. Hub n'est jamais un module de cette grille : le badge n'identifie que le conteneur d'un template événementiel. Les comparatifs se limitent à des axes structurels durables, affichent leur date de vérification et renvoient au concurrent en `rel="nofollow noopener noreferrer"` ; ni prix ni chiffre d'usage recopié. Les vitrines listent les guides associés à leur service et chargent donc également le namespace `landing`.
- **Landing pages d'acquisition (G6)** : `landings.json` déclare pour chaque page son chemin par langue, son cluster (`organiser`/`outils`/`comparatif`), son `primaryService`, les modules montrés et le maillage (`related`). Un seul template, `shared/components/SeoLanding.tsx` + `hooks/useLandingSeo.ts`, rend les quarante-deux URL ; tout le contenu, y compris le scénario de preview contextualisé, vit dans `i18n/locales/{fr,en}/landing.json`. **Ne jamais créer de composant par landing** ni écrire ses routes à la main : `App.tsx` et `Navbar.tsx` les génèrent depuis la config. Les entrées `editorial: true` ajoutent des sections longues, des dates et un JSON-LD `Article` dans ce même template. Le CTA passe par `useCreateEventLink(primaryService)` et la preuve produit est générée depuis `ServiceProductPreview` — même brique que les vitrines. Une landing mono-module conserve l'aperçu détaillé de ce service ; dès que `modules` en déclare plusieurs, la preview compose exactement cette liste ordonnée avec les libellés courts `preview.modules.<id>`. Hub n'est jamais un module de cette grille : le badge n'identifie que le conteneur d'un template événementiel. Les comparatifs se limitent à des axes structurels durables, affichent leur date de vérification et renvoient au concurrent en `rel="nofollow noopener noreferrer"` ; ni prix ni chiffre d'usage recopié. Les vitrines listent les guides associés à leur service et chargent donc également le namespace `landing`.
- **Templates Hub par cas dusage (GRW-02)** : les entrées `organiser` de `landings.json` portent `hubTemplate.eventType` et sont lunique registre des templates. Leur `key`, leurs `modules` ordonnés et leur `short_title` bilingue sont relus par `HubTemplateFields`, partagé entre `CreateHubModal` et `/hub/new`, puis par lonboarding ; ne jamais créer un second catalogue Hub. Le type choisi filtre les cas dusage compatibles et un changement de type efface le template devenu incohérent. Le CTA SEO transmet `template=<key>` dans `next`. Un template conseille le type et lordre des outils, et peut les **poser vides** en un lot explicite (cf. `## Activation produit`) : il ne crée jamais ditem, de date ou de participant artificiel. Le namespace `landing` reste différé et se charge à louverture du sélecteur privé.
- **Serveur statique maison** : `frontend/scripts/static-server.mjs` (remplace `serve`). Il lit `frontend/locales.json` et résout, dans lordre : fichier exact > `index.<locale>.html` selon le domaine > `index.html` de la langue par défaut > `app.html` (shell SPA). Un domaine inconnu utilise la locale par défaut. `serve` appliquait ses rewrites avant le lookup fichier et court-circuitait le pré-rendu.
- **Meta** : `usePageMeta` gère titre, description, canonical, alternates, OG/Twitter et noindex. `useLandingSeo(landing, faq)` publie le graphe JSON-LD commun (WebPage + BreadcrumbList + FAQPage) et ajoute `Article` pour une landing éditoriale.
- **Validation SEO obligatoire** : `npm run check:prerender`, exécuté par `npm run build`, relit les 60 HTML générés et contrôle `h1`, `lang`, canonical, hreflang et Open Graph. Pour les landings il vérifie en plus le graphe JSON-LD complet, la bannière générée, la présence dun CTA de création dans le HTML statique, le développement des pages éditoriales, le tableau et le lien `nofollow` des comparatifs, et lunicité des `og:title` par langue. Toute nouvelle page publique doit satisfaire ce contrôle.
- **Validation SEO obligatoire** : `npm run check:prerender`, exécuté par `npm run build`, relit les 64 HTML générés et contrôle `h1`, `lang`, canonical, hreflang et Open Graph. Pour les landings il vérifie en plus le graphe JSON-LD complet, la bannière générée, la présence dun CTA de création dans le HTML statique, le développement des pages éditoriales, le tableau et le lien `nofollow` des comparatifs, et lunicité des `og:title` par langue. Toute nouvelle page publique doit satisfaire ce contrôle.
- **Bannières de partage** : `/og/<landing-key>.<lang>.png` 1200×630 générées au build, une par landing et par langue.
- **Pages privées** : toute page accessible par lien de partage doit passer `noindex: true` à `usePageMeta`, + header `X-Robots-Tag` côté Caddy (cf. `Caddyfile.example`) pour les crawlers sans JS.
- Le sitemap est servi par l'**API** (`/sitemap.xml`), pas en statique — Caddy
@ -234,7 +234,7 @@ kankwa/
- `frontend/src/shared/config/serviceMetadata.ts` est la source légère des identifiants, labels, chemins et statuts utilisés par la navigation, la homepage et le compte. `services.tsx` reste le registre fonctionnel des routes/cartes/actions Hub. Ne jamais importer le registre fonctionnel pour afficher seulement une métadonnée.
- Les modales et cartes propres aux services sont chargées avec `React.lazy` depuis leurs configs.
- **Catalogues i18n différés** : un namespace volumineux réservé à quelques routes publiques est déclaré dans `LAZY_NAMESPACES` (`src/i18n/config.ts`), exclu du `import.meta.glob` eager et chargé par `loadNamespace(namespace, lang)` en même temps que le composant de la route. Seule la langue active est chargée ; un changement de langue recharge le bundle correspondant. `SeoLanding` et les six vitrines utilisent ce mécanisme pour `landing`. Cest le réflexe à appliquer à tout futur gros catalogue.
- **Mesures** (chunk initial gzip, en séquence) : 147,54 avant PERF-01 → 141,52 (G5) → 145,33 (MKT-07) → 146,07 → 146,17 (palettes) → 147,37 après le premier lot G6 → 145,71 après l'extension événementielle G6. Pour le retrait du blog et les deux landings éditoriales, une mesure comparable sur le `HEAD` immédiatement antérieur donne **152,37 → 150,03 Ko gzip** (2,34 Ko). Comparer toujours à un build de référence du `HEAD` courant, jamais entre méthodes différentes.
- **Mesures** (chunk initial gzip, en séquence) : 147,54 avant PERF-01 → 141,52 (G5) → 145,33 (MKT-07) → 146,07 → 146,17 (palettes) → 147,37 après le premier lot G6 → 145,71 après l'extension événementielle G6. Pour le retrait du blog et les deux landings éditoriales d'alors (`cadeau-commun` a depuis perdu ce statut : `fete-ecole` est la seule aujourd'hui), une mesure comparable sur le `HEAD` immédiatement antérieur donne **152,37 → 150,03 Ko gzip** (2,34 Ko). Comparer toujours à un build de référence du `HEAD` courant, jamais entre méthodes différentes.
---
@ -243,7 +243,7 @@ kankwa/
- Le CTA public principal de la homepage est « Créer mon événement » et cible `/hub/new` après authentification. Les vitrines emploient un libellé contextualisé mais gardent la même création de Hub. La destination interne `next` doit être conservée dans tous les flux (mot de passe, code email et magic link) et validée comme chemin local pour empêcher les redirections ouvertes.
- Un Hub vide présente un seul état de démarrage compact avec les cinq modules disponibles. Après le premier module, une seule action « Ajouter un outil » ouvre le sélecteur. Le marqueur `onboarding=1` est consommé puis retiré de lURL ; ne pas réintroduire de checklist ou daction de partage en doublon.
- La colonne latérale du Hub reste la source unique pour le lien public, les co-gestionnaires et les commentaires. Ces trois panneaux ne doivent pas être déplacés ni fusionnés avec lonboarding.
- Depuis une landing événementielle, `template=<landing-key>` suit le même trajet. La page `/hub/new` et le modal du dashboard partagent le sélecteur type → cas dusage : ils proposent les 13 entrées `organiser` compatibles, préremplissent leur `eventType` et affichent les modules issus de la landing ; après création, lonboarding les place en tête tout en laissant lutilisateur configurer chaque ressource.
- Depuis une landing événementielle, `template=<landing-key>` suit le même trajet. La page `/hub/new` et le modal du dashboard partagent le sélecteur type → cas dusage : ils proposent les 15 entrées `organiser` compatibles, préremplissent leur `eventType` et affichent les modules issus de la landing ; après création, lonboarding les place en tête tout en laissant lutilisateur configurer chaque ressource.
- **Pose en lot des outils dun template** : `TemplateStarterPanel` propose de créer dun coup les modules conseillés, **vides**, via `POST /hub/{id}/modules` (`services/hub/modules.py`). Seul le titre est dérivé (`onboarding.module_title.*` + nom du Hub) ; aucun item, aucune date, aucun participant nest inventé. Le lot est atomique : `enforce_premium_capacity` réserve la capacité pour lensemble, donc un template ne se pose jamais à moitié. Les cases sont pré-cochées jusquà la capacité freemium restante, les suivantes restent visibles et désactivées avec le lien Kankwa+ — le coût est montré avant laction, pas après léchec. `serviceMetadata.starter` désigne les services créables vides et doit rester aligné sur `BATCHABLE_SERVICE_TYPES` ; Kwiz en est exclu car un sondage exige ses options et reste une création en un clic.
- Depuis une vitrine, `service=<id>` est conservé dans `next`, validé contre `serviceMetadata`, puis transmis à lonboarding. Le module demandé apparaît en premier et est signalé, sans ouvrir automatiquement sa modale.
- `/demo` est la démonstration publique bilingue, sans compte ni données artificielles persistées ; la route appartient à `seo-routes.json` et doit rester pré-rendue.

View file

@ -421,6 +421,61 @@ dans la source unique du pré-rendu/sitemap. Premier lot recommandé :
« 62 pages pré-rendues » puis « SEO pré-rendu validé : 62 pages » (16 août
2026).
#### SEO-LP-23 — audit des vingt landings et des six vitrines
- Statut : `DONE`
- Agent : Claude Code
- Début : 16 août 2026
- Travail : vérifier page par page la cohérence problématique → solution → preuve,
la propreté des modules et des CTA, et l'alignement FR/EN ; corriger ce qui
s'en écarte sans toucher aux intentions déjà verrouillées.
- Acceptation : aucun CTA ne promet une ressource que le parcours ne crée pas ;
l'ordre des modules suit l'angle éditorial de la page ; aucun contenu de
catalogue n'est orphelin ; les méta tiennent leurs bornes dans les deux langues ;
la priorité sitemap se dérive du cluster ; tout lien de maillage est réciproque.
- Résultat : le CTA de `soiree-jeux` et `sortie-entre-amis` annonce la page de
l'événement et non « le vote », puisque Kwiz est hors `BATCHABLE_SERVICE_TYPES`
et ne peut pas être posé vide ; `repas` place Kontrib en tête, conformément à son
H1, sa problématique et son CTA ; la clé morte `partage-depenses.modules.kontrib`
est supprimée dans les deux langues ; dix méta hors bornes sont ramenées dans
leurs seuils ; les previews EN quittent Lyon et Annecy pour Leeds et le Lake
District, avec `kount.vitrine.preview_title` aligné ; la priorité devient une
règle de cluster documentée dans `landings.ts` plutôt qu'un jugement page par
page, et six liens réciproques portent le minimum entrant à deux.
- Résultat (non retenu) : la landing `mariage` est écartée — Kankwa n'a ni RSVP
ni liste d'invités (aucun `models/guest.py`, RSVP retiré en phase 3) ni
encaissement, soit les deux tâches dominantes de cette intention. Le type
`mariage` reste sans template, cas déjà géré par `create_modal.template_none_for_type`.
- Preuves : `landings.json`, `landings.ts`, catalogues FR/EN `landing`/`kount`,
`SeoLanding.test.tsx` ; **203 Vitest**, i18n « 2 langues, 10 namespaces »,
« 46 WebP configurés présents », « 62 pages pré-rendues » puis « SEO pré-rendu
validé : 62 pages » ; quatre captures régénérées (`repas` FR/EN,
`anniversaire.en`, `week-end.en`) (16 août 2026).
#### SEO-LP-24 — landing EVJF/EVG
- Statut : `DONE`
- Agent : Claude Code
- Début : 16 août 2026
- Travail : couvrir l'intention enterrement de vie de jeune fille / de garçon,
écartée jusque-là, avec une seule page bilingue et son template Hub.
- Acceptation : une seule landing pour les deux intentions, conformément au
précédent `voyage` / `vacances-entre-amis` verrouillé par test ; un angle qui ne
duplique ni `voyage` ni `week-end` ; quatre modules servis par des capacités
réelles ; maillage réciproque ; FR/EN, SSG, sitemap et previews synchronisés.
- Résultat : `evjf-evg` (`/organiser/evjf-evg`, `/plan/hen-and-stag-do`) porte
`hubTemplate.eventType: voyage` et les modules `kal`, `kwiz`, `kount`,
`kontrib`. Son angle propre est la personne fêtée : elle ne doit rien voir et ne
paie pas sa part, ce qui s'appuie sur deux capacités existantes — résultats Kwiz
masqués tant qu'ils ne sont pas publiés, et choix des personnes concernées par
chaque dépense dans Kount. La FAQ traite frontalement l'absence d'encaissement.
Le catalogue passe à 21 landings, 42 URL et 15 cas d'usage Hub.
- Preuves : `landings.json` (+ quatre `related` réciproques), catalogues FR/EN,
`landings.test.ts` **16 tests** ; i18n vert, « 6 vues Hub et 42 previews SEO »,
bannières `/og/evjf-evg.{fr,en}.png`, « 64 pages pré-rendues (32 FR + 32 EN) »
puis « SEO pré-rendu validé : 64 pages », empreinte marketing `ec346c0a9ab2`
(16 août 2026).
Critères communs : intention distincte, contenu non dupliqué, démonstration produit,
CTA contextualisé, maillage, FR/EN, SSG, sitemap, canonical et données structurées.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View file

@ -28,7 +28,7 @@
"features_intro": "Readable tracking for trips, shared homes, meals and group spending, even with different shares.",
"steps_intro": "Create the group, add expenses as you go and let Kount balance the accounts.",
"preview_label": "Kount expense group preview",
"preview_title": "Weekend in Annecy",
"preview_title": "Weekend in the Lake District",
"preview_subtitle": "Group expenses",
"preview_primary": "Total spent",
"preview_secondary": "Chalet rental",

View file

@ -27,7 +27,7 @@
"preview": {
"label": "Guest preview of the birthday Hub",
"title": "Lea's birthday",
"subtitle": "Saturday 19 September · Lyon",
"subtitle": "Saturday 19 September · Leeds",
"modules": {
"kal": "Find the date",
"kontrib": "Share out the buffet",
@ -91,7 +91,7 @@
"preview": {
"label": "Guest preview of the weekend Hub",
"title": "Weekend at Lea's",
"subtitle": "1214 September · Annecy",
"subtitle": "1214 September · the Lake District",
"modules": {
"kal": "Choose the weekend",
"kount": "Track the expenses",
@ -155,8 +155,8 @@
"title": "Neighbourhood dinner",
"subtitle": "Who brings what?",
"modules": {
"kal": "Choose the right evening",
"kontrib": "Share out the menu",
"kal": "Choose the right evening",
"kount": "Balance the expenses"
},
"status": "2 needs left"
@ -180,8 +180,8 @@
}
],
"modules": {
"kal": "If the date is not settled yet, offer a few slots and let the group decide before opening the list.",
"kontrib": "The list of contributions with quantities, your own categories and a live view of what is already covered.",
"kal": "If the date is not settled yet, offer a few slots and let the group decide before opening the list.",
"kount": "For meals where someone fronts the shopping for the group: expenses are recorded and refunds worked out."
},
"faq": [
@ -278,8 +278,8 @@
"final_desc": "Create the stay and share one link to move every group decision forward."
},
"fete-ecole": {
"meta_title": "Organise a school party: buffet, supplies and parent volunteers",
"meta_description": "School fair, class party, carnival: coordinate the buffet and supplies with a shared list. Every parent checks off what they bring, with no account and no app.",
"meta_title": "Organise a school party: buffet and supplies",
"meta_description": "School fair, class party, carnival: coordinate the buffet and supplies with a shared list. Every parent checks off what they bring, with no account.",
"short_title": "Organise a school party",
"h1": "Organise a school party when thirty families have to coordinate",
"intro": "A school fair is prepared with people who don't all know each other, don't use the same tools and don't have ten minutes to spend on a chat thread. A list shared by link puts everyone on the same level of information.",
@ -650,8 +650,7 @@
}
],
"modules": {
"kount": "Group expense tracking: payers, participants per expense, any currency, custom shares and optimised refunds.",
"kontrib": "Alongside it, sharing out what people bring, for the costs that are not settled in money."
"kount": "Group expense tracking: payers, participants per expense, any currency, custom shares and optimised refunds."
},
"faq": [
{
@ -862,7 +861,7 @@
},
"cremaillere": {
"meta_title": "Plan a housewarming party with one shared link",
"meta_description": "Set the date, divide up drinks, food and supplies, then share your housewarming plans through one link.",
"meta_description": "Set the date, divide up drinks, food and supplies, then share your housewarming plans through one link. No app and no account for your guests.",
"short_title": "Plan a housewarming party",
"h1": "Just moved? Plan your housewarming with one shared link",
"intro": "You have just moved. Set the date, organise what everyone brings and share one link with your guests.",
@ -943,7 +942,7 @@
},
"cousinade": {
"meta_title": "Plan a family reunion on one shared page",
"meta_description": "Find the date, divide meals and expenses, and choose family reunion activities on one shared page.",
"meta_description": "Find the date, divide meals and expenses, and choose family reunion activities on one shared page. Every relative takes part without an account.",
"short_title": "Plan a family reunion",
"h1": "A family reunion planned for the whole family",
"intro": "The more branches of the family there are, the more replies get scattered. Give everyone one page for the date, meals, costs and group choices.",
@ -985,7 +984,7 @@
},
"baby-shower": {
"meta_title": "Plan a baby shower and gift list together",
"meta_description": "Set the date, share the baby gift list, divide up food and choose baby shower games on one page.",
"meta_description": "Set the date, share the baby gift list, divide up food and choose baby shower games on one page. Guests join from the link, with no account.",
"short_title": "Plan a baby shower",
"h1": "A baby shower planned as one moment, not four lists",
"intro": "The date, baby wishes, food and games belong together. Bring them into a clear page friends and family can open without installing an app.",
@ -1027,11 +1026,11 @@
},
"soiree-jeux": {
"meta_title": "Plan a game night and choose games together",
"meta_description": "Let the group vote on games, find the date and divide up game-night snacks from one shared link.",
"meta_description": "Let the group vote on games, find the date and divide up game-night snacks from one shared link. Players vote without creating an account.",
"short_title": "Plan a game night",
"h1": "The first game of the night is making a choice",
"intro": "Party games, strategy or cards? Kwiz turns an endless list into a group decision, while Kal and Kontrib handle the date and what everyone brings.",
"cta": "Create the game-night poll",
"cta": "Create the game night",
"preview": {
"label": "Preview of the Kwiz game-night poll",
"title": "Game night at Hugos",
@ -1048,7 +1047,7 @@
"solution_title": "A real vote before opening the boxes.",
"solution_desc": "Kwiz ranks the groups options. The same Hub can hold a date poll and a contribution list without losing sight of the main choice.",
"steps": [
{ "title": "Suggest the games", "desc": "Create a Kwiz with a short selection suited to the number and tastes of the players." },
{ "title": "Suggest the games", "desc": "Create the game-night page, then its Kwiz vote with a short selection suited to the number and tastes of the players." },
{ "title": "Let the group vote", "desc": "Share the link and see which option brings the most preferences together." },
{ "title": "Finish the plan", "desc": "Add the date and divide up drinks or snacks if the group needs them." }
],
@ -1063,15 +1062,15 @@
{ "q": "Do I need to create a complete event?", "a": "No. Start directly with Kwiz, then attach it to a Hub if you add a date or contributions." }
],
"final_title": "Let one game win before the first round starts.",
"final_desc": "Create the Kwiz poll, share it with the players and prepare the night in one place."
"final_desc": "Create the game-night page, add the vote on games and prepare the rest in one place."
},
"sortie-entre-amis": {
"meta_title": "Plan a day out with friends by group poll",
"meta_description": "Choose the activity and date together, then share the costs of a day out with friends from one common page.",
"meta_description": "Choose the activity and date together, then share the costs of a day out with friends from one common page. No app, no guest account.",
"short_title": "Plan a day out with friends",
"h1": "Turn “we should go out” into a real choice",
"intro": "Restaurant, hike, concert or escape room: deciding is often the hardest part. Let friends vote, find a date and keep any shared costs on the same page.",
"cta": "Create the day-out poll",
"cta": "Create the day out",
"preview": {
"label": "Preview of the Kwiz friends activity poll",
"title": "The Fireflies day out",
@ -1103,11 +1102,11 @@
{ "q": "Can an expense involve only part of the group?", "a": "Yes. In Kount, every expense specifies exactly which participants are involved." }
],
"final_title": "One activity chosen, one date fixed, one real day out.",
"final_desc": "Launch the friends poll and move every decision forward from the same page."
"final_desc": "Create the day-out page, launch the friends vote and move every decision forward in one place."
},
"reveillon": {
"meta_title": "Plan a New Years Eve party and divide the meal",
"meta_description": "Divide up the menu, choose the theme and share New Years Eve party expenses on a page everyone can open.",
"meta_description": "Divide up the menu, choose the theme and share New Years Eve party expenses on a page everyone can open, with no account and no app.",
"short_title": "Plan New Years Eve",
"h1": "A New Years Eve meal that does not fall on one person",
"intro": "Starters, drinks, spare beds, a theme and shopping all feel lighter when every contribution is visible before December 31.",
@ -1188,6 +1187,49 @@
],
"final_title": "The whole family Christmas, clear from one link.",
"final_desc": "Create the page, add the preparations you need and share it with your relatives."
},
"evjf-evg": {
"meta_title": "Plan a hen or stag do without spoiling the surprise",
"meta_description": "Find a date across ten diaries, vote on the activity, divide the shopping and track who paid what, without the guest of honour seeing a thing.",
"short_title": "Plan a hen or stag do",
"h1": "Plan a hen or stag do with ten people, without the guest of honour knowing",
"intro": "With ten people the date is already a problem and the budget is another. Give the group one page for the date, the activity, the shopping and the advances, shared with the group alone.",
"cta": "Create the hen or stag do",
"preview": {
"label": "Group preview of the hen do Hub",
"title": "Chloes hen do",
"subtitle": "2022 March · Edinburgh",
"modules": {
"kal": "Lock in the weekend",
"kwiz": "Choose the activity",
"kount": "Track the advances",
"kontrib": "Divide the shopping"
},
"status": "Shared with 9 friends"
},
"problem_title": "With ten people the date never lands, and the surprise leaks.",
"problem_desc": "Availability arrives in private messages, nobody knows who has already paid for what, and one badly placed screenshot is enough to give it all away.",
"solution_title": "One page the group shares, and only the group.",
"solution_desc": "The same address holds the date replies, the activity vote, the shopping and the advances. The link travels inside the group, never to the guest of honour.",
"steps": [
{ "title": "Lock in the date", "desc": "Compare a few weekends and let everyone reply from the link, without creating an account." },
{ "title": "Settle the activity and the budget", "desc": "Vote on the destination or activity, divide the shopping and record the advances as you go." },
{ "title": "Keep the surprise", "desc": "Send the link to the group only and update everything in one place until you leave." }
],
"modules": {
"kal": "Compare several weekends in a readable availability grid, even beyond ten people.",
"kwiz": "Vote on the destination, activity or theme; results stay hidden until you publish them.",
"kount": "Track the accommodation, activities and shopping, and choose who takes part in each expense so the guest of honour can be left out.",
"kontrib": "Divide decorations, games, shopping and journeys with quantities and a visible owner."
},
"faq": [
{ "q": "How do we keep the surprise?", "a": "Only share the link with the participants. The Hub sends no automatic invitations and Kwiz results stay hidden until you publish them." },
{ "q": "Can the guest of honour be left out of the expenses?", "a": "Yes. Kount lets you choose the people involved in each expense and set custom shares, so their weekend can be split between the others." },
{ "q": "Does everyone need an account?", "a": "No. Participants reply to dates, vote and read the expenses from the link, with no account and no app." },
{ "q": "Does Kankwa collect the money?", "a": "No. Kount works out who owes what and reduces the number of repayments, but the money moves directly between participants." }
],
"final_title": "The group gets organised, the surprise holds.",
"final_desc": "Create the hen or stag do, add the tools you need and share the link with the group only."
}
}
}

View file

@ -19,7 +19,7 @@
"pages": {
"anniversaire": {
"meta_title": "Organiser un anniversaire avec un seul lien",
"meta_description": "Trouvez la date, rassemblez les idées de cadeaux, répartissez le buffet et partagez les frais depuis une seule page. Sans application, sans compte pour vos invités.",
"meta_description": "Trouvez la date, rassemblez les idées de cadeaux, répartissez le buffet et partagez les frais depuis une seule page. Sans compte pour vos invités.",
"short_title": "Organiser un anniversaire",
"h1": "Organiser un anniversaire sans y passer vos soirées",
"intro": "Un anniversaire, ce nest jamais une seule décision : il faut une date qui convienne, des idées de cadeaux sans doublon, un buffet réparti et des avances à rembourser. Kankwa réunit ces quatre sujets sur une page unique que vous partagez dun seul lien.",
@ -155,8 +155,8 @@
"title": "Dîner de quartier",
"subtitle": "Qui apporte quoi ?",
"modules": {
"kal": "Choisir le bon soir",
"kontrib": "Répartir le menu",
"kal": "Choisir le bon soir",
"kount": "Équilibrer les dépenses"
},
"status": "Encore 2 besoins"
@ -180,8 +180,8 @@
}
],
"modules": {
"kal": "Si la date nest pas encore arrêtée, proposez plusieurs créneaux et laissez le groupe trancher avant douvrir la liste.",
"kontrib": "La liste des apports avec quantités, catégories libres et suivi en direct de ce qui est déjà pris en charge.",
"kal": "Si la date nest pas encore arrêtée, proposez plusieurs créneaux et laissez le groupe trancher avant douvrir la liste.",
"kount": "Pour les repas où quelquun avance les courses du groupe : les dépenses sont enregistrées et les remboursements calculés."
},
"faq": [
@ -278,8 +278,8 @@
"final_desc": "Créez le séjour et partagez un seul lien pour faire avancer chaque décision du groupe."
},
"fete-ecole": {
"meta_title": "Organiser une fête d'école : buffet, matériel et parents volontaires",
"meta_description": "Kermesse, fête de classe, carnaval : coordonnez le buffet et le matériel avec une liste partagée. Chaque parent coche ce qu'il apporte, sans compte ni application.",
"meta_title": "Organiser une fête d'école : buffet et matériel",
"meta_description": "Kermesse, fête de classe, carnaval : coordonnez le buffet et le matériel avec une liste partagée. Chaque parent coche ce qu'il apporte, sans compte.",
"short_title": "Organiser une fête d'école",
"h1": "Organiser une fête d'école quand trente familles doivent se coordonner",
"intro": "Une kermesse se prépare avec des gens qui ne se connaissent pas tous, qui n'ont pas les mêmes outils et qui n'ont pas dix minutes à consacrer à un fil de discussion. Une liste partagée par lien remet tout le monde au même niveau d'information.",
@ -443,7 +443,7 @@
},
"sondage-date": {
"meta_title": "Sondage de dates gratuit, sans compte ni publicité",
"meta_description": "Proposez vos créneaux, laissez chacun répondre oui, non ou si nécessaire, et voyez la meilleure date se dégager. Gratuit, sans inscription pour les participants.",
"meta_description": "Proposez vos créneaux, laissez chacun répondre oui, non ou si nécessaire, et voyez la meilleure date se dégager. Gratuit, sans inscription pour vos invités.",
"short_title": "Sondage de dates gratuit",
"h1": "Créer un sondage de dates gratuit, sans compte pour vos invités",
"intro": "Trouver une date commune est un problème simple qui devient pénible dès quon dépasse quatre personnes. Un sondage de dates le règle en quelques minutes : vous proposez des créneaux, chacun se positionne, et le meilleur choix apparaît de lui-même.",
@ -650,8 +650,7 @@
}
],
"modules": {
"kount": "Le suivi des dépenses de groupe : payeurs, participants par dépense, devise libre, parts personnalisables et calcul des remboursements.",
"kontrib": "En complément, la répartition de ce que chacun apporte, pour les dépenses qui ne se règlent pas en argent."
"kount": "Le suivi des dépenses de groupe : payeurs, participants par dépense, devise libre, parts personnalisables et calcul des remboursements."
},
"faq": [
{
@ -676,7 +675,7 @@
},
"comparatif-doodle": {
"meta_title": "Alternative à Doodle : sondage de dates sans publicité",
"meta_description": "Comparez Doodle et Kankwa sur le périmètre, la publicité vue par vos invités, lhébergement et le prix. Sondage de dates gratuit, sans compte pour les participants.",
"meta_description": "Comparez Doodle et Kankwa sur le périmètre, la publicité vue par vos invités, lhébergement et le prix. Sondage de dates gratuit, sans compte invité.",
"short_title": "Kankwa ou Doodle",
"h1": "Kankwa ou Doodle : quelle alternative pour vos sondages de dates ?",
"intro": "Doodle a rendu le sondage de dates évident et reste une référence. La question utile nest donc pas de savoir lequel est meilleur, mais ce dont vous avez besoin : un outil dédié aux créneaux, ou une page qui garde aussi les cadeaux, les apports et les dépenses du même moment.",
@ -1031,7 +1030,7 @@
"short_title": "Organiser une soirée jeux",
"h1": "Le premier jeu de la soirée : réussir à choisir",
"intro": "Jeux dambiance, stratégie ou cartes ? Kwiz transforme la liste infinie en décision collective, puis Kal et Kontrib règlent la date et ce que chacun apporte.",
"cta": "Créer le vote de la soirée",
"cta": "Créer la soirée jeux",
"preview": {
"label": "Aperçu du vote Kwiz pour la soirée jeux",
"title": "Soirée jeux chez Hugo",
@ -1048,7 +1047,7 @@
"solution_title": "Un vote concret avant de sortir les boîtes.",
"solution_desc": "Kwiz classe les options du groupe. Le même Hub peut accueillir le sondage de dates et la liste des apports sans diluer le choix principal.",
"steps": [
{ "title": "Proposez les jeux", "desc": "Créez un Kwiz avec une sélection courte adaptée au nombre et aux envies des joueurs." },
{ "title": "Proposez les jeux", "desc": "Créez la page de la soirée, puis son vote Kwiz avec une sélection courte adaptée au nombre et aux envies des joueurs." },
{ "title": "Laissez le groupe voter", "desc": "Partagez le lien et observez loption qui rassemble le plus de préférences." },
{ "title": "Finalisez la soirée", "desc": "Ajoutez si nécessaire la date et la répartition des boissons ou du grignotage." }
],
@ -1063,7 +1062,7 @@
{ "q": "Faut-il créer un événement complet ?", "a": "Non. Vous pouvez partir directement de Kwiz, puis le rattacher à un Hub si vous ajoutez une date ou des apports." }
],
"final_title": "Faites gagner un jeu avant même la première partie.",
"final_desc": "Créez le vote Kwiz, partagez-le aux joueurs et préparez la soirée au même endroit."
"final_desc": "Créez la page de la soirée, ajoutez le vote des jeux et préparez le reste au même endroit."
},
"sortie-entre-amis": {
"meta_title": "Organiser une sortie entre amis par sondage",
@ -1071,7 +1070,7 @@
"short_title": "Organiser une sortie entre amis",
"h1": "Transformez « on devrait sortir » en choix concret",
"intro": "Restaurant, randonnée, concert ou escape game : le plus difficile est souvent de décider. Faites voter les amis, trouvez le créneau et gardez les éventuels frais dans la même page.",
"cta": "Créer le sondage de sortie",
"cta": "Créer la sortie",
"preview": {
"label": "Aperçu du vote Kwiz pour la sortie entre amis",
"title": "Sortie du groupe des Lucioles",
@ -1103,7 +1102,7 @@
{ "q": "Peut-on partager une dépense avec seulement une partie du groupe ?", "a": "Oui. Dans Kount, chaque dépense indique précisément les personnes concernées." }
],
"final_title": "Une activité choisie, une date fixée, une sortie qui existe.",
"final_desc": "Lancez le vote entre amis et faites avancer chaque décision depuis la même page."
"final_desc": "Créez la page de la sortie, lancez le vote entre amis et faites avancer chaque décision au même endroit."
},
"reveillon": {
"meta_title": "Organiser un réveillon du Nouvel An et répartir le repas",
@ -1189,6 +1188,49 @@
],
"final_title": "Le Noël de toute la famille, lisible depuis un seul lien.",
"final_desc": "Créez la page, ajoutez les préparatifs utiles et partagez-la avec vos proches."
},
"evjf-evg": {
"meta_title": "Organiser un EVJF ou un EVG sans gâcher la surprise",
"meta_description": "Trouvez la date à dix, votez lactivité, répartissez les achats et suivez les avances, sans que la personne fêtée voie quoi que ce soit.",
"short_title": "Organiser un EVJF ou un EVG",
"h1": "Organiser un EVJF ou un EVG à dix, sans que la personne fêtée en sache rien",
"intro": "À dix, la date est déjà un problème et le budget en est un autre. Kankwa donne au groupe une page commune pour la date, le choix de lactivité, les achats et les avances, partagée au groupe seulement.",
"cta": "Créer lEVJF ou lEVG",
"preview": {
"label": "Aperçu du Hub de lEVJF côté groupe",
"title": "EVJF de Chloé",
"subtitle": "2022 mars · Biarritz",
"modules": {
"kal": "Caler le week-end",
"kwiz": "Choisir lactivité",
"kount": "Suivre les avances",
"kontrib": "Répartir les achats"
},
"status": "Page partagée avec 9 proches"
},
"problem_title": "À dix, la date ne se trouve jamais et la surprise fuite.",
"problem_desc": "Les disponibilités arrivent en messages privés, personne ne sait qui a déjà payé quoi, et une capture décran mal placée suffit à tout dévoiler.",
"solution_title": "Une page que le groupe partage, et lui seul.",
"solution_desc": "La même adresse rassemble les réponses de date, le vote de lactivité, les achats et les avances. Le lien circule dans le groupe, jamais vers la personne fêtée.",
"steps": [
{ "title": "Calez la date", "desc": "Comparez quelques week-ends et laissez chacun répondre depuis le lien, sans créer de compte." },
{ "title": "Décidez lactivité et le budget", "desc": "Faites voter la destination ou lactivité, répartissez les achats et saisissez les avances au fur et à mesure." },
{ "title": "Gardez la surprise", "desc": "Diffusez le lien au groupe uniquement et mettez tout à jour au même endroit jusquau départ." }
],
"modules": {
"kal": "Comparez plusieurs week-ends dans une matrice de disponibilités lisible, même au-delà de dix personnes.",
"kwiz": "Faites voter la destination, lactivité ou le thème ; les résultats restent masqués tant que vous ne les publiez pas.",
"kount": "Suivez le logement, les activités et les courses, et choisissez qui participe à chaque dépense pour en exclure la personne fêtée.",
"kontrib": "Répartissez déco, jeux, courses et trajets avec des quantités et un responsable visible."
},
"faq": [
{ "q": "Comment garder la surprise ?", "a": "Ne partagez le lien quaux participants. Le Hub nenvoie aucune invitation automatique et les résultats dun vote Kwiz restent masqués tant que vous ne les publiez pas." },
{ "q": "La personne fêtée peut-elle être exclue des dépenses ?", "a": "Oui. Kount permet de choisir les personnes concernées par chaque dépense et des parts personnalisées, donc son week-end peut être réparti entre les autres." },
{ "q": "Faut-il que tout le monde crée un compte ?", "a": "Non. Les participants répondent aux dates, votent et consultent les dépenses depuis le lien, sans compte ni application." },
{ "q": "Kankwa encaisse-t-il la cagnotte ?", "a": "Non. Kount calcule qui doit quoi à qui et réduit le nombre de remboursements, mais largent circule directement entre les participants." }
],
"final_title": "Le groupe sorganise, la surprise tient.",
"final_desc": "Créez lEVJF ou lEVG, ajoutez les outils utiles et partagez le lien au groupe uniquement."
}
}
}

View file

@ -113,7 +113,7 @@ describe('SeoLanding SEO-LP', () => {
renderLanding('soiree-jeux', '/organiser/soiree-jeux')
expect(screen.getByRole('heading', { level: 1, name: 'Le premier jeu de la soirée : réussir à choisir' })).toBeVisible()
const createLinks = screen.getAllByRole('link', { name: 'Créer le vote de la soirée' })
const createLinks = screen.getAllByRole('link', { name: 'Créer la soirée jeux' })
expect(createLinks).toHaveLength(2)
for (const link of createLinks) {
expect(link).toHaveAttribute('href', '/register?next=%2Fhub%2Fnew%3Ftemplate%3Dsoiree-jeux')

View file

@ -198,5 +198,15 @@
"width": 793,
"height": 590
}
},
"evjf-evg": {
"fr": {
"width": 793,
"height": 590
},
"en": {
"width": 793,
"height": 590
}
}
}

View file

@ -18,22 +18,22 @@
"primaryService": "hub",
"modules": ["kal", "kount", "kontrib"],
"hubTemplate": { "eventType": "voyage" },
"related": ["voyage", "partage-depenses", "cousinade", "sortie-entre-amis"],
"priority": "0.9",
"related": ["voyage", "partage-depenses", "cousinade", "sortie-entre-amis", "evjf-evg"],
"priority": "0.8",
"changefreq": "monthly",
"updatedAt": "2026-08-11"
"updatedAt": "2026-08-16"
},
{
"key": "repas",
"cluster": "organiser",
"path": { "fr": "/organiser/repas", "en": "/plan/group-dinner" },
"primaryService": "kontrib",
"modules": ["kal", "kontrib", "kount"],
"modules": ["kontrib", "kal", "kount"],
"hubTemplate": { "eventType": "repas" },
"related": ["qui-apporte-quoi", "fete-ecole", "reveillon"],
"priority": "0.8",
"changefreq": "monthly",
"updatedAt": "2026-08-11"
"updatedAt": "2026-08-16"
},
{
"key": "voyage",
@ -42,10 +42,10 @@
"primaryService": "hub",
"modules": ["kwiz", "kal", "kontrib", "kount"],
"hubTemplate": { "eventType": "voyage" },
"related": ["week-end", "sortie-entre-amis", "partage-depenses"],
"related": ["week-end", "sortie-entre-amis", "partage-depenses", "comparatif-splitwise-tricount", "evjf-evg"],
"priority": "0.8",
"changefreq": "monthly",
"updatedAt": "2026-08-15"
"updatedAt": "2026-08-16"
},
{
"key": "fete-ecole",
@ -56,10 +56,10 @@
"hubTemplate": { "eventType": "autre" },
"related": ["qui-apporte-quoi", "repas"],
"editorial": true,
"priority": "0.9",
"priority": "0.8",
"changefreq": "monthly",
"publishedAt": "2026-06-13",
"updatedAt": "2026-08-11"
"updatedAt": "2026-08-16"
},
{
"key": "cadeau-commun",
@ -69,7 +69,7 @@
"modules": ["kdo"],
"hubTemplate": { "eventType": "autre" },
"related": ["liste-cadeaux", "anniversaire", "pot-de-depart", "noel-en-famille"],
"priority": "0.9",
"priority": "0.8",
"changefreq": "monthly",
"updatedAt": "2026-08-16"
},
@ -79,10 +79,10 @@
"path": { "fr": "/outils/sondage-date", "en": "/tools/date-poll" },
"primaryService": "kal",
"modules": ["kal"],
"related": ["comparatif-doodle", "anniversaire", "soiree-jeux", "cousinade"],
"related": ["comparatif-doodle", "anniversaire", "soiree-jeux", "cousinade", "pot-de-depart", "evjf-evg"],
"priority": "0.8",
"changefreq": "monthly",
"updatedAt": "2026-08-11"
"updatedAt": "2026-08-16"
},
{
"key": "liste-cadeaux",
@ -112,10 +112,10 @@
"path": { "fr": "/outils/partage-depenses", "en": "/tools/expense-sharing" },
"primaryService": "kount",
"modules": ["kount"],
"related": ["comparatif-splitwise-tricount", "voyage", "cousinade", "sortie-entre-amis"],
"related": ["comparatif-splitwise-tricount", "voyage", "cousinade", "sortie-entre-amis", "week-end", "evjf-evg"],
"priority": "0.8",
"changefreq": "monthly",
"updatedAt": "2026-08-11"
"updatedAt": "2026-08-16"
},
{
"key": "comparatif-doodle",
@ -123,11 +123,11 @@
"path": { "fr": "/comparatif/doodle", "en": "/compare/doodle" },
"primaryService": "kal",
"modules": ["kal", "kwiz"],
"related": ["sondage-date", "anniversaire"],
"related": ["sondage-date", "anniversaire", "pot-de-depart"],
"comparison": true,
"priority": "0.8",
"priority": "0.7",
"changefreq": "monthly",
"updatedAt": "2026-08-11"
"updatedAt": "2026-08-16"
},
{
"key": "comparatif-splitwise-tricount",
@ -135,11 +135,11 @@
"path": { "fr": "/comparatif/splitwise-tricount", "en": "/compare/splitwise-tricount" },
"primaryService": "kount",
"modules": ["kount", "kontrib"],
"related": ["partage-depenses", "cadeau-commun"],
"related": ["partage-depenses", "cadeau-commun", "voyage"],
"comparison": true,
"priority": "0.7",
"changefreq": "monthly",
"updatedAt": "2026-08-11"
"updatedAt": "2026-08-16"
},
{
"key": "cremaillere",
@ -160,7 +160,7 @@
"primaryService": "kal",
"modules": ["kal", "kontrib", "kwiz"],
"hubTemplate": { "eventType": "soiree" },
"related": ["cadeau-commun", "sondage-date", "qui-apporte-quoi"],
"related": ["cadeau-commun", "sondage-date", "qui-apporte-quoi", "comparatif-doodle"],
"priority": "0.8",
"changefreq": "monthly",
"updatedAt": "2026-08-16"
@ -233,8 +233,20 @@
"modules": ["kdo", "kontrib", "kount", "kwiz"],
"hubTemplate": { "eventType": "autre" },
"related": ["cadeau-commun", "liste-cadeaux", "repas", "reveillon"],
"priority": "0.9",
"priority": "0.8",
"changefreq": "monthly",
"updatedAt": "2026-08-15"
"updatedAt": "2026-08-16"
},
{
"key": "evjf-evg",
"cluster": "organiser",
"path": { "fr": "/organiser/evjf-evg", "en": "/plan/hen-and-stag-do" },
"primaryService": "hub",
"modules": ["kal", "kwiz", "kount", "kontrib"],
"hubTemplate": { "eventType": "voyage" },
"related": ["week-end", "voyage", "sondage-date", "partage-depenses"],
"priority": "0.8",
"changefreq": "monthly",
"updatedAt": "2026-08-16"
}
]

View file

@ -36,6 +36,13 @@ export interface LandingConfig {
editorial?: boolean
/** Première publication, uniquement pour les pages éditoriales. */
publishedAt?: string
/**
* Priorité sitemap, **dérivée du cluster** et non d'un jugement page par page :
* `organiser` et `outils` à 0.8, `comparatif` à 0.7 (trafic de comparaison,
* moins prioritaire que les pages d'usage). Une valeur choisie à la main pour
* une page isolée n'est que du bruit : elle se compare mal aux autres et se
* périme sans que rien ne le signale.
*/
priority: string
changefreq: string
updatedAt: string

View file

@ -1,3 +1,3 @@
{
"version": "865e824a6ec6"
"version": "ec346c0a9ab2"
}