Commit graph

54 commits

Author SHA1 Message Date
4ec45b71ce feat: passer Kankwa en gratuit sans limite visible — cacher le premium
Some checks are pending
quality / backend (push) Waiting to run
quality / frontend (push) Waiting to run
quality / real-e2e (push) Waiting to run
- Retirer toutes les mentions de prix (1,99 €/19,99 €), de Kankwa+ et
  de la limite à 3 outils dans les FAQ et comparatifs des landing pages (FR + EN)
- Masquer la section Abonnement dans Account.tsx pour les utilisateurs
  non-premium (reste visible pour les abonnés existants)
- Supprimer le lien "Passer à Kankwa+" dans CreateBringModal,
  CreateKountModal et TemplateStarterPanel quand la limite est atteinte

Infrastructure Stripe et logique premium conservées intactes pour
réintroduction future.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-08-16 10:02:52 +00:00
626e510767 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>
2026-08-16 09:31:05 +00:00
f25cd0a882 fix(seo): normalize landing previews 2026-08-16 08:20:48 +00:00
917918e8b0 Clarify group gift and housewarming journeys 2026-08-16 07:32:06 +00:00
e18fcb332c fix(admin): clarifier le libellé des services 2026-08-15 16:51:14 +00:00
b3bee7485b feat(seo): séparer les sitemaps et consolider les intentions 2026-08-15 16:46:13 +00:00
816c414bef fix(admin): compter les visiteurs uniques dans le funnel non filtré
Avant la migration 0036, COUNT(id) == COUNT(DISTINCT anonymous_id) car
la contrainte permettait au plus une ligne par visiteur+événement. Avec
la colonne `page`, un visiteur peut produire plusieurs landing_view, donc
le funnel comptait des lignes au lieu de visiteurs. Alignement sur
COUNT(DISTINCT anonymous_id) comme la branche filtrée.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-08-14 13:57:58 +00:00
c346a6cff2 feat(admin): décomposition par page dans l'entonnoir d'acquisition
Ajoute une colonne `page` sur `growth_events` (migration 0036) et étend
la contrainte unique pour permettre un landing_view distinct par page visitée.
Homepage, vitrines et landings SEO envoient désormais leur identifiant de page ;
le dashboard Acquisition affiche le classement des pages d'entrée.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-08-14 13:46:21 +00:00
9aff5d8146 feat(admin): G15/ADM-06 — recette clavier, axe, responsive, bundle ; G15 clos
Corrige sept défauts d'accessibilité/design system découverts par la recette
(ink-faint en texte de corps, warning-600 en avant-plan, badge-service hors
ServiceThemeScope, progressbars sans nom accessible, région défilante non
focusable, panneaux sans sémantique de dialogue). Zéro régression (191
Vitest, 8 Playwright dont axe 0 violation critique/sérieuse) et chunk public
inchangé (150,52 kB gzip vs build de référence du HEAD).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-14 13:08:11 +00:00
9811559930 feat(admin): G15/ADM-01..05 — design system, entonnoir, revenus, tableau, système
ADM-01 : shell et dashboard entièrement retokenisés (ink-*/surface-*/line-*),
UserCumulativeChart absorbé par UserGrowthChart (ComposedChart Bar+Line), période
portée par l'URL ; AdminKpiCard, AdminChartWrapper, useChartColors introduits.

ADM-02 : GET /api/admin/growth/funnel (filtrable locale/device/days) ;
GET /growth/activation retiré de la surface publique (ADM-R5) ;
GET /api/admin/stats/growth-events-over-time ; AdminAcquisition créé
(entonnoir, métriques virales, répartition device/source, état URL).

ADM-03 : /api/admin/stats enrichi by_lang/by_plan/mrr_real/arr_real
(mensuel×1,99 + annuel×19,99/12) ; GET /api/admin/stats/services-over-time ;
AdminRevenue créé (MRR réel, ARR, LineChart des services 30 j).

ADM-04 : AdminUsers réécrit avec TanStack Table v9 (useTable/createColumnHelper/
table.Subscribe/table.FlexRender) ; colonnes lang/subscription_plan ; filtres
lang/verified/has_stripe côté API et UI ; export CSV navigateur ; onglet
historique d'audit dans le panneau de détail.

ADM-05 : GET /api/admin/audit-log paginé et filtrable par action ;
POST /api/admin/maintenance/purge-growth ;
GET /api/admin/system/config ; AdminSystem créé (indicateurs config, journal
d'audit avec payload expansible, purge de rétention).

Validation : tsc --noEmit propre, vite build réussi, chunk public 150,52 kB gzip.
Roadmap : ADM-01 à ADM-05 DONE, ADM-R1/R5 DONE, ADM-06 IN_PROGRESS (bundle OK,
Vitest/Playwright/axe à compléter).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-08-14 12:20:02 +00:00
9d08cefe2c feat(admin): G15/ADM-00 — billing fix, droit effectif, audit log, rate limit
Débloque le chantier d'isolation admin (G15). ADM-R2 : la suppression admin
annule désormais l'abonnement Stripe avant d'effacer le compte, sans bloquer
sur un échec fournisseur (journalisé). ADM-R3 : premium_active_clause()
remplace is_premium brut dans les comptages/filtres admin. Ajoute
admin_audit_log (sans FK), la limitation de débit sur /api/admin, le refus
de démarrage sous 32 caractères pour ADMIN_TOKEN, les en-têtes Caddy dédiés,
et la segmentation locale sur growth_events (migrations 0034/0035).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-14 11:27:04 +00:00
24d5c8f54d fix(kal): cap time slot drag at 23:30 to avoid 24:00 Pydantic error
Moving a range to the far right could produce end=24:00, which Python's
time type and PostgreSQL reject. Clamp start to MAX_END - w instead of
TOTAL - w. Test asserts the boundary is respected. Docs: re-evaluation
audit 2026-08-13 post-deployment + ROADMAP/TESTING updates.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-08-13 22:16:08 +00:00
9ad8802de9 fix(hub): remove orphan collaborationOpen media query effect
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-08-13 22:12:42 +00:00
7dba0b7dc6 refactor(ux): extract CollaborationSidebar, apply to all service pages
New shared component wraps the service-right column with the mobile
one-way reveal card ("Partage et collaboration"). Replaces the ad-hoc
<details> in HubEdit and the plain <div class="service-right"> in all
five service edit pages (Kdo, Kontrib, Kount, Kal, Kwiz). Hub passes
its custom hint (with "activité"); services use the new common.json
collaboration.hint key.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-08-13 22:12:06 +00:00
7a3b7704d2 fix(hub): collaboration panel is a one-way reveal card on mobile
Replace <details> toggle with a button card that disappears on click,
showing SharePanel/CoOwnerPanel/CommentBlock inline. On desktop (xl+)
the card is hidden and panels are always visible.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-08-13 22:06:33 +00:00
03242dad4f fix(hub): collaboration panel correctly collapses on mobile
.hub-collaboration-content used flex which overrode <details> native
display:none, keeping content visible even when closed. Switch to
space-y-6 (margin-based gap) so the browser can hide/show content
naturally; xl override stays as display:block !important.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-08-13 21:59:58 +00:00
58fc5619aa feat(ux): share button in page header + hub mobile panel close + panel gap
- Add shareUrl prop to ServicePageHeader, renders ShareButton just left
  of the settings icon on all Hub and service edit pages
- Add onShared callback to ShareButton/SharePanel; Hub mobile panel
  collapses automatically after a successful share action
- Fix .service-right flex column gap-6 so SharePanel, CoOwnerPanel and
  CommentBlock are no longer flush against each other vertically

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-08-13 21:40:33 +00:00
aff01249ae fix(nav): scroll to top on navigation + back button returns to Hub
- Add ScrollToTop component in App.tsx that resets scroll position on
  every route change (React Router does not do this natively)
- Fix Kal and Kwiz PollEdit pages to read location.state.from instead
  of hardcoding /kal and /kwiz — matches the pattern already used by
  Kdo, Kontrib and Kount so the back button returns to the originating
  Hub when navigating from there

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-08-13 21:28:15 +00:00
79cef8b849 fix(design): désamorcer HTTPS du copy confiance, aligner titres pages ressources
Le hero remplace la mention technique HTTPS par un libellé générique
en fr/en. Les pages CGU, mentions et confidentialité gagnent pt-6 sur
leur conteneur pour aligner leur titre sur celui des pages services
connectées (ServiceDashboard).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-13 21:15:44 +00:00
cd80e91e7e fix(design): aligner le fond de la navbar ligne services sur les deux shells
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-08-13 21:04:36 +00:00
6dccf7d02f fix(design): navbar mobile, collaboration gap, legal page width
- Navbar mobile : espaces réduits (px-2/gap-1 → sm:px-3/sm:gap-1.5), labels
  conservés, scrollbar native cachée, gradient fade-out pour signaler le défilement
- Navbar ligne services : fond `surface-inverse` sur shell public (vitrines/landings)
  pour une transition continue vers le hero encre ; onglets inactifs adaptés en
  `ink-inverse/60` ; `surface-muted` conservé sur le shell workspace
- Panneaux de collaboration (SharePanel/CoOwnerPanel/CommentBlock) : gap-4 → gap-6
- Pages légales (Legal, Privacy, Terms) : `page-editorial` → `page` pour aligner
  la largeur de conteneur avec les autres pages du site

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-08-13 20:59:41 +00:00
ed10f6b5ed fix: disable healthcheck for maintenance worker 2026-08-13 20:15:54 +00:00
fc3c2cb1e5 feat: finalize product hardening and operations 2026-08-13 20:13:38 +00:00
44c364b823 docs: préciser le préfixe des rôles typographiques
Le contrat mentionnait `page-title`/`section-title`, alors que les rôles sont des
utilitaires issus de la clé `fontSize` : le préfixe `text-` est obligatoire.
Écrite sans lui, la classe n'existe pas et ne fait échouer ni le build ni les
tests — le titre retombe simplement à la taille par défaut. Le piège s'est
déclenché pendant la reprise d'audit G10.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-13 13:50:01 +00:00
16a7c70aca fix(a11y,design): reprendre l'audit UI/UX transverse (G10)
Noms accessibles et rôles ARIA (AUD-A) : Spinner nommé, Alert en alert/status,
champs Login, CommentBlock, BringPublic, ReservationModal et KdoItemForm dotés
d'un nom accessible (WCAG 1.3.5). Une suppression empêchée passe par
aria-disabled et non disabled — un bouton disabled quitte l'ordre de tabulation,
donc la raison de l'empêchement deviendrait inatteignable au clavier. Les deux
menus de la Navbar partagent useDismissableMenu : Échap referme et rend le focus
au déclencheur.

Retour aux tokens sémantiques (AUD-T) : GuestConversionCTA reprend la surface
sable universelle, ErrorBoundary traduit sous garde avec repli français, Cancel
et MagicVerify passent sur .page-sm, Demo et CurrencyInput perdent leurs gris
bruts. Un aplat porteur de texte remonte au cran 700, comme .btn-primary : le
blanc sur primary-600 ne tient pas AA. Les emoji d'icône de Cancel laissent la
place au SVG canonique de service et à sa palette.

Saisie et retours d'état (AUD-U) : le remplissage automatique de KdoItemForm se
dit par fieldset disabled plutôt que par un voile qui bloquait la souris sans
bloquer le clavier ; inputMode="decimal" sur les neuf champs de montant ; le
chargement d'un tableau de bord conserve titre et action derrière un squelette
au lieu d'un point central ; la suppression est confirmée en région d'état.

Doublons et rendu (AUD-C) : dangerouslySetInnerHTML remplacé par Trans sur une
chaîne traduite, dates du compte via formatDate, shim kount/CurrencyInput
supprimé au profit de @shared/components.

Deux constats de l'audit sont écartés après vérification et documentés dans la
roadmap : le tabIndex={-1} de SwipeToDelete est délibéré, et la fermeture
directe de ReservationModal pour un utilisateur connecté est une décision
produit acquise. Le débordement de VoteSelectionGrid reste TODO : un overflow-x
casserait les en-têtes sticky réglés sur --page-header-bottom.

Vérifications : check:i18n vert (2 langues, 10 namespaces), tsc --noEmit vert,
174 tests Vitest verts, vite build vert (chunk initial 149,58 Ko gzip, contre
150,03 Ko en référence).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-13 13:41:59 +00:00
222f01acc2 fix(design): aligner disposition des cartes contribution et dépense
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-08-13 10:21:06 +00:00
e61cbf515e feat(design): unifier partage et actions de gestion
Un template Hub conseille tous ses modules : n'en marquer qu'un laissait croire
que les autres n'appartenaient pas au cas d'usage choisi, alors que le panneau de
pose en lot les propose tous juste au-dessus. Le badge couvre l'ensemble, plus le
`service=` demandé depuis une vitrine.

Les actions du masthead se répètent d'une ressource à l'autre — réglages partout,
duplication sur le Hub : elles deviennent des icônes nommées groupées à droite du
titre, plutôt que des libellés qui lui disputaient sa largeur. La duplication
passe par la prop `actions` au lieu d'un bouton posé sous la description.

Partager devient un seul contrôle appris une fois : `ShareButton` remplace la
copie du rail de partage et arrive sur les cartes Kal et Kwiz, qui étaient les
deux seules à ne pas l'exposer. `CopyButton` n'avait plus d'appelant. Icône seule
impose un nom accessible : `aria-label` s'ajoute au `title`, et bascule sur « Lien
copié » — l'échange d'icône ne disait rien à un lecteur d'écran.

174 Vitest verts, TypeScript et check:i18n verts.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-13 09:17:20 +00:00
89dbc4fc56 fix(kal): fiabiliser la reconfiguration d'un sondage de dates
La session globale ne se vide pas à la validation (`expire_on_commit=False`) :
un `delete()` Core suivi d'un `add()` ORM laissait les collections déjà chargées
intactes, donc la réponse de `update_poll_config` renvoyait des dates vides alors
que la BDD était correcte. Le poll est désormais expiré avant relecture.

Côté édition, `no_changes_with_responses` n'est plus une erreur générique : la
page recharge le sondage et passe en mode verrouillé, l'état réel des réponses
reçues entre-temps. Un 422 est journalisé avec son détail, sans quoi une
validation refusée ne laissait aucune trace exploitable.

Le calendrier remonte compteur et « vider » sous les dates choisies, où ils
portent sur ce qui est visible, et la page publique cesse de doubler le score
d'une date déjà donné dans le fil de lecture.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-13 09:17:09 +00:00
bd99572d43 feat(design): aligner cadres et mastheads 2026-08-12 23:23:27 +00:00
5f01a9d3b5 feat(design): finaliser G8 VIS-05 à VIS-09 2026-08-12 22:37:51 +00:00
3bab4553b2 feat(design): livrer les lots G8 VIS-00 à VIS-04
Refonte visuelle du produit jusqu'au pilote fonctionnel. Aucune route, API,
permission, étape métier ni limite Premium n'est modifiée.

VIS-00 — anomalies transverses : header et bandeau cookies contenus à 320/390 px,
Kal sorti du terracotta Hub, couleurs brutes remplacées par les tokens.

VIS-01 — tokens arrêtés dans tailwind.config.ts et index.css (sept rôles
typographiques, neutres par rôle, espacements, conteneurs, rayons, élévations,
durées), verrouillés par designTokens.test.ts et démontrés par /style-tile
(noindex, hors sitemap et pré-rendu). Bricolage Grotesque auto-hébergée.

VIS-02 — primitives partagées : btn-quiet/btn-icon, card-notice/interactive/
summary/configuration, badges sémantiques, Field et Badge ; Modal, EmptyState,
MetaChip, ConfirmModal, ProgressBar et ResourceCard migrés aux tokens.

VIS-03 — shells : shellVariant.ts devient la source unique du contexte public /
workspace, une racine de service dépendant aussi de la session. Rail de
collaboration, saisie de code et pages éditoriales factorisés. Anneau de focus
posé une seule fois, btn-primary au cran 700 pour tenir AA.

VIS-04 — Hub pilote : ModuleGroup et ServiceToolTile portent l'assemblage et le
choix d'outil, le démarrage d'un Hub vide devient de l'aide contextuelle, une
seule action dominante par colonne, le type d'événement passe en métadonnée
(emojis retirés des catalogues, EVENT_TYPE_ICONS supprimé) et les formulaires Hub
prennent des libellés persistants. Le champ de partage reçoit un nom accessible.

Validations : check:i18n vert, TypeScript 0 erreur, 119 Vitest (28 fichiers),
Playwright 27 passed, build Docker complet (60 pages SSG, check:marketing et
check:prerender conformes). Chunk initial 148 163 -> 148 690 o gzip pour tout G8.

Le checkpoint « Pilote » reste ouvert : VIS-05 à VIS-07 attendent la revue Hub
desktop et mobile du propriétaire.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-12 17:10:22 +00:00
19b04ed65b feat(hub): poser en un lot les outils d'un template
GRW-07. Un template ne se contente plus de conseiller : il peut créer d'un coup
les modules qu'il recommande, sur action explicite de l'organisateur. La règle
« aucun contenu artificiel » reste entière — seuls les titres sont dérivés du
catalogue et du nom du Hub, aucun item, aucune date, aucun participant n'est
inventé.

- `services/hub/modules.py` + `POST /hub/{event_id}/modules` : le lot est
  atomique, `enforce_premium_capacity` réserve la capacité pour l'ensemble
  (même brique que la duplication GRW-03), donc un template ne se pose jamais
  à moitié. Le backend ne connaît pas le catalogue SEO : il valide une liste de
  `service_type` contre `BATCHABLE_SERVICE_TYPES`, aucun registre dupliqué ;
- `TemplateStarterPanel` remplace le bloc statique de l'onboarding : cases
  pré-cochées jusqu'à la capacité gratuite restante, suivantes visibles mais
  désactivées avec le lien Kankwa+. Sept des treize templates proposent quatre
  modules pour une limite de trois : le coût est montré avant l'action plutôt
  qu'un échec sur le dernier outil ;
- Kwiz reste hors du lot : `KwizPollCreate.options` exige au moins deux
  options, un sondage ne peut pas être créé vide. `serviceMetadata.starter`
  porte cette distinction, alignée sur la constante backend.

Validation : 51 Pytest PostgreSQL, dont un test vérifiant l'absence de
`KalDate`/`KontribItem` créés, l'unique membre Kount et le refus en bloc d'un
lot de quatre pour un compte à 2/3 ; 65 Vitest ; `check:i18n`, `tsc --noEmit`
et build Docker (SSG 60 pages + `check:prerender`) verts.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-11 22:37:31 +00:00
31061cd1c5 feat(hub): remonter les contributions des cinq services
Complète GRW-06 : `/hub/my-contributions` couvre désormais les six types de
participation, Kal et Kwiz compris. Le repli par email rattrape une action
faite en invité avant l'inscription, sur les cinq services partageables.

- migration `0029` : `kontrib_declarations.participant_email`, aligné sur le
  contrat Kdo — l'adresse n'est stockée que pour un invité, un utilisateur
  connecté reste rattaché par `user_id` ;
- rapprochement uniquement sur une adresse `email_verified`, en minuscules, et
  court-circuit des requêtes Kount/Kal/Kwiz sans adresse vérifiée pour ne pas
  produire un `IS NULL` qui rattacherait les participations anonymes ;
- chaque montant porte sa `currency` et le Hub formate via `formatCurrency()` :
  le `€` codé en dur affichait une mauvaise devise pour un groupe en CHF ;
- couleurs des badges dérivées de `serviceThemes.ts` plutôt que de tokens
  sémantiques réattribués à la main.

Validation : 50 Pytest PostgreSQL verts, dont deux tests couvrant les six types,
la casse de l'email, l'exclusion d'un tiers, la coupure sur email non vérifié,
les devises et le contrat invité/connecté de la déclaration Kontrib.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-11 22:36:49 +00:00
5b2539eda9 feat(kdo): passer Kdo en multidevises, aligner sur Kount
- Migration 0030 : colonne currency VARCHAR(10) DEFAULT 'EUR' sur kdo_items
- Schemas/router : currency propagé dans KdoItemCreate/Update/Summary/Response
- Parseur scrape.py : détection de devise via JSON-LD priceCurrency, OG
  product:price:currency et fallback price-parser symbol→ISO (_SYMBOL_TO_ISO)
- formatCurrency déplacé vers shared/utils/ (source unique) ; kount/utils re-exporte
- CurrencyInput déplacé vers shared/components/ (namespace common) ; kount re-exporte
- common.json FR+EN : section currency.* (labels, devises, aperçu)
- KdoItemForm / EditKdoItemModal : sélecteur devise, pré-rempli depuis le scrape
- KdoItemCard / ListPublic : formatCurrency(price, currency) remplace {price} €
- ContributionModal : remaining formaté avec la devise de l'item
- kdo.json FR+EN : price_placeholder et amount_placeholder sans € codé en dur

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-08-11 22:02:10 +00:00
690696c369 feat: finaliser les boucles de croissance G7 2026-08-11 20:55:18 +00:00
0a3daa680c fix(marketing): invalider les anciennes previews 2026-08-11 16:35:47 +00:00
ae9084dae9 fix(marketing): corriger le périmètre des icônes 2026-08-11 16:01:13 +00:00
c215c0b65b fix(seo): clarifier les marques dans les previews 2026-08-11 15:34:20 +00:00
bd98870d5e feat(seo): étendre les landings événementielles 2026-08-11 14:44:09 +00:00
de2b946bfa refactor(seo): remplacer le blog par des landings éditoriales 2026-08-11 12:53:38 +00:00
94e4e8ee2d feat(seo): livrer le premier cluster de landing pages G6
Dix landing pages bilingues (20 URL) reposent sur un template unique piloté
par configuration : landings.json déclare chemin par langue, cluster, service
dominant, modules, maillage et article associé ; SeoLanding.tsx rend tout le
reste depuis les catalogues i18n. App.tsx, Navbar.tsx, le pré-rendu, le
sitemap et les contrôles SEO lisent cette source unique.

Le catalogue landing devient un namespace i18n différé (LAZY_NAMESPACES /
loadNamespace) pour ne pas peser sur le chunk initial : 146,18 → 147,37 Ko
gzip au lieu de 167,01. Le pré-rendu attend désormais #root h1 afin de ne pas
figer l'écran d'attente dans le HTML statique.

check-prerender vérifie le graphe JSON-LD, le CTA, les comparatifs et
l'unicité des og:title ; check-i18n compare les tableaux élément par élément ;
tests/test_sitemap.py verrouille les URL et hreflang des landings.

Preuves : 52 pages SSG validées (kankwa-frontend:g6-landings), Vitest 43
passed, Pytest PostgreSQL 42 passed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-11 09:23:59 +00:00
6ec7bcdfb7 fix(hub): fiabiliser la création des modules 2026-08-10 21:28:22 +00:00
d1f67a907e feat: généraliser les palettes aux espaces métier 2026-08-10 20:35:05 +00:00
3f07a19d19 feat: refondre les vitrines et thèmes services 2026-08-10 20:06:11 +00:00
a1adc03980 feat(seo): finaliser les fondations bilingues G5 2026-08-10 18:32:41 +00:00
0afa6d18bd feat: renforcer la landing G4 2026-08-10 18:05:00 +00:00
8ac65b2859 feat: finaliser G4 et sécuriser le frontend 2026-08-10 17:05:25 +00:00
2f3ec2cc2e feat: complete security quality and activation milestones 2026-08-10 15:36:48 +00:00
5e271a3e10 fix: conserve la hauteur naturelle des cartes 2026-08-09 22:47:32 +00:00
e9a331dd96 fix: aligne la suppression sur la hauteur des cartes 2026-08-09 22:42:15 +00:00