Commit Graph
3 Commits
Author SHA1 Message Date
anthony ca4f896256 fix(seo): render each page in its actual language during SSR
i18n.changeLanguage(lang) previously only ran in a client-only useEffect,
so every page's SSR pass (Header, Footer, HomePage hero text) always used
i18next's shared default language ('fr') regardless of the actual route —
meaning /en/ and every English conversion page served French body content
to crawlers, undermining the whole per-language SEO effort.

Fixed by cloning the i18next instance per page (i18n.cloneInstance({ lng })
via I18nextProvider) instead of mutating the shared singleton. Mutating the
shared instance directly during render would have been unsafe anyway: the
SSG build renders up to `concurrency` pages in parallel in the same
process, so one page's language change would leak into others rendering
at the same time. Verified across all 30 pairs x 2 languages that server-
rendered body content now matches the page's actual language, with no
cross-page leakage.

This likely also explains the intermittent React hydration error #418
reported in production: a client that hydrates against SSR content whose
language could shift depending on render-order timing is a hydration
mismatch waiting to happen.
2026-08-02 11:12:21 +02:00
anthony 6fc3386965 fix(seo): pass lang as a prop to Header/LanguageSwitcher instead of useParams
Since the vite-react-ssg migration replaced the dynamic /:lang route param
with literal /fr and /en routes, useParams().lang always returned undefined
here, breaking the header brand link (linked to /undefined/) and silently
breaking the language switcher (always resolved otherLang to 'fr').
2026-08-02 10:58:23 +02:00
anthony 3b53d82b3d feat(seo): migrate to build-time prerendering with vite-react-ssg
Fixes SeoHead (title/canonical/hreflang/JSON-LD) to render during SSR via
vite-react-ssg's Head component instead of a client-only useEffect, so
crawlers see real tags without executing JS. Also fixes an SSR crash in
useTheme (localStorage access with no window during server render) and
removes now-duplicated static meta tags from index.html.
2026-08-02 10:30:26 +02:00