From 2332c69557ec4505ec3846745becf82925c1f314 Mon Sep 17 00:00:00 2001 From: kayjaydee Date: Wed, 8 Apr 2026 16:31:58 +0200 Subject: [PATCH] fix(02): resolve 3 typecheck errors and i18n langDir path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - useSetLocale → destructured setLocale from useI18n() - addSeoAttributes → seo option for useLocaleHead() - process.env → import.meta.env for Nuxt compatibility - langDir: 'locales/' → 'app/locales/' (Nuxt 4 resolves from project root) --- .planning/ROADMAP.md | 2 +- .planning/STATE.md | 20 +-- .../phases/02-ssr-shell/02-VERIFICATION.md | 161 ++++++++++++++++++ app/app.vue | 2 +- app/components/layout/AppHeader.vue | 3 +- nuxt.config.ts | 4 +- 6 files changed, 176 insertions(+), 16 deletions(-) create mode 100644 .planning/phases/02-ssr-shell/02-VERIFICATION.md diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md index 4bba520..c36a834 100644 --- a/.planning/ROADMAP.md +++ b/.planning/ROADMAP.md @@ -70,5 +70,5 @@ Phases execute in numeric order: 1 → 2 → 3 | Phase | Plans Complete | Status | Completed | |-------|----------------|--------|-----------| | 1. Foundation | 2/2 | Complete | 2026-04-08 | -| 2. SSR Shell | 1/3 | In Progress| | +| 2. SSR Shell | 3/3 | Executed | 2026-04-08 | | 3. Pages & Ship | 0/TBD | Not started | - | diff --git a/.planning/STATE.md b/.planning/STATE.md index b12ab9c..37de499 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -3,15 +3,15 @@ gsd_state_version: 1.0 milestone: v1.0 milestone_name: milestone status: executing -stopped_at: Completed 02-02-PLAN.md -last_updated: "2026-04-08T14:26:56.840Z" -last_activity: 2026-04-08 -- Phase 2 planning complete +stopped_at: Phase 2 execution complete — pending verification +last_updated: "2026-04-08T16:00:00.000Z" +last_activity: 2026-04-08 -- Phase 2 all 3 plans executed progress: total_phases: 3 - completed_phases: 2 + completed_phases: 1 total_plans: 5 completed_plans: 5 - percent: 100 + percent: 66 --- # Project State @@ -21,16 +21,16 @@ progress: See: .planning/PROJECT.md (updated 2026-04-07) **Core value:** Chaque page du portfolio doit être crawlable par les moteurs de recherche sans JavaScript côté client -**Current focus:** Phase 1 — Foundation +**Current focus:** Phase 2 — SSR Shell (execution complete) ## Current Position Phase: 2 of 3 (ssr shell) -Plan: Not started -Status: Ready to execute -Last activity: 2026-04-08 -- Phase 2 planning complete +Plan: 3/3 complete +Status: Executed — pending verification +Last activity: 2026-04-08 -- Phase 2 all 3 plans executed -Progress: [░░░░░░░░░░] 0% +Progress: [██████░░░░] 66% ## Performance Metrics diff --git a/.planning/phases/02-ssr-shell/02-VERIFICATION.md b/.planning/phases/02-ssr-shell/02-VERIFICATION.md new file mode 100644 index 0000000..ff6f060 --- /dev/null +++ b/.planning/phases/02-ssr-shell/02-VERIFICATION.md @@ -0,0 +1,161 @@ +--- +phase: 02-ssr-shell +verified: 2026-04-08T18:00:00Z +status: gaps_found +score: 3/5 +overrides_applied: 0 +gaps: + - truth: "curl localhost:3000 returns French HTML; curl localhost:3000/en/ returns English HTML" + status: partial + reason: "TypeScript errors prevent clean build — useSetLocale not found, addSeoAttributes unknown property, process undefined. App may still run in dev mode but typecheck fails with 3 errors." + artifacts: + - path: "app/components/layout/AppHeader.vue" + issue: "useSetLocale is not a valid auto-import — should be useSetLocale from @nuxtjs/i18n or manual setLocale from useI18n()" + - path: "app/app.vue" + issue: "addSeoAttributes option not recognized by I18nHeadOptions type" + - path: "nuxt.config.ts" + issue: "process.env usage needs @types/node or import.meta.env" + missing: + - "Fix useSetLocale — use setLocale from useI18n() or correct auto-import name" + - "Fix useLocaleHead options to match @nuxtjs/i18n v9 API" + - "Fix process.env reference in nuxt.config.ts" + - truth: "http://localhost:3000/sitemap.xml returns valid XML sitemap with hreflang alternates" + status: partial + reason: "Sitemap module is configured (@nuxtjs/sitemap in modules) but no explicit sitemap config with i18n hreflang alternates found in nuxt.config.ts. The module may auto-detect i18n routes but this is unverified without a running server." + artifacts: + - path: "nuxt.config.ts" + issue: "No sitemap-specific configuration block — relies entirely on module defaults for hreflang generation" + missing: + - "Verify sitemap actually generates hreflang alternates (requires running server or explicit config)" +human_verification: + - test: "Start dev server, curl localhost:3000 and verify French HTML with title/og/JSON-LD" + expected: "Complete French HTML with SEO metadata rendered server-side" + why_human: "TypeScript errors may or may not prevent SSR rendering — needs runtime check" + - test: "Toggle language via header button, reload page, verify language persists" + expected: "Cookie-based persistence, no FOUC" + why_human: "Requires browser interaction and visual inspection" + - test: "Toggle dark/light mode, reload, verify no flash" + expected: "Theme persists via cookie, correct class on first paint" + why_human: "FOUC detection requires visual inspection of cold load" + - test: "Visit /sitemap.xml and verify hreflang alternates for FR and EN" + expected: "XML sitemap with xhtml:link rel=alternate for each URL pair" + why_human: "Requires running server to generate sitemap" +--- + +# Phase 2: SSR Shell Verification Report + +**Phase Goal:** Every route renders the correct language, theme, and SEO metadata on the server -- confirmed by `curl` with no JavaScript +**Verified:** 2026-04-08T18:00:00Z +**Status:** gaps_found +**Re-verification:** No -- initial verification + +## Goal Achievement + +### Observable Truths + +| # | Truth | Status | Evidence | +|---|-------|--------|----------| +| 1 | curl localhost:3000 returns French HTML; /en/ returns English HTML | FAILED | 3 TypeScript errors block clean build: useSetLocale unknown, addSeoAttributes invalid, process undefined | +| 2 | Language switch persists across reload (cookie, no FOUC) | ? UNCERTAIN | Header has toggleLocale with useSetLocale (TS error), i18n config has detectBrowserLanguage with cookie -- needs runtime test | +| 3 | Theme toggle persists across reload with no flash | VERIFIED | colorMode configured with cookie storage in nuxt.config.ts, AppHeader uses useColorMode() with preference setter, dark default | +| 4 | curl response includes title, og:title, og:description, JSON-LD | VERIFIED | All 6 pages call useSeoMeta() with reactive i18n getters; index.vue has application/ld+json with Person + ProfessionalService | +| 5 | sitemap.xml returns valid XML with hreflang alternates | ? UNCERTAIN | @nuxtjs/sitemap in modules, i18n has baseUrl -- but no explicit sitemap hreflang config; may work via auto-detection | + +**Score:** 3/5 truths verified (1 failed, 1 uncertain on sitemap, theme+SEO pass structurally) + +### Required Artifacts + +| Artifact | Expected | Status | Details | +|----------|----------|--------|---------| +| `nuxt.config.ts` | SSR, i18n, colorMode, sitemap config | VERIFIED (with TS issue) | All modules configured; process.env TS error on line 54 | +| `app.config.ts` | Nuxt UI primary=brand | VERIFIED | primary: 'brand' mapped | +| `app/assets/css/main.css` | Tailwind v4 + brand palette | VERIFIED | @theme with brand-50 through brand-950 | +| `app/app.vue` | useLocaleHead + NuxtLayout | VERIFIED (with TS issue) | addSeoAttributes option has type mismatch | +| `app/components/layout/AppHeader.vue` | Nav + language toggle + theme toggle + mobile drawer | VERIFIED (with TS issue) | Full implementation with UDrawer, but useSetLocale type error | +| `app/components/layout/AppFooter.vue` | Footer with social links | VERIFIED | Gitea, LinkedIn, Fiverr with proper a11y | +| `app/layouts/default.vue` | Header + slot + footer | VERIFIED | Clean layout wrapper | +| `app/pages/index.vue` | SEO meta + JSON-LD | VERIFIED | useSeoMeta + ld+json script | +| `app/pages/projects.vue` | SEO meta stub | VERIFIED | useSeoMeta with i18n keys | +| `app/locales/fr.json` | French translations | VERIFIED | 509 lines, nav/footer/seo/a11y keys present | +| `app/locales/en.json` | English translations | VERIFIED | 509 lines, matching key structure | +| `public/og-image.png` | OG image | STUB | Text placeholder, not a real image | + +### Key Link Verification + +| From | To | Via | Status | Details | +|------|----|-----|--------|---------| +| AppHeader | i18n | useSetLocale() | PARTIAL | Function called but TS can't resolve auto-import | +| AppHeader | colorMode | useColorMode() | WIRED | preference setter works | +| app.vue | i18n head | useLocaleHead() | PARTIAL | Called but addSeoAttributes option has type error | +| pages/*.vue | i18n SEO | useSeoMeta + t() | WIRED | All 6 pages use reactive i18n getters | +| default.vue | AppHeader/AppFooter | component auto-import | WIRED | Both referenced in template | + +### Anti-Patterns Found + +| File | Line | Pattern | Severity | Impact | +|------|------|---------|----------|--------| +| app/pages/*.vue | various | "Phase 3 content placeholder" | Info | Expected -- page content is Phase 3 scope | +| public/og-image.png | - | Text placeholder file | Warning | og:image URLs will return invalid image | +| nuxt.config.ts | 54 | process.env without types | Blocker | TypeScript error | +| app/app.vue | 3 | addSeoAttributes type mismatch | Blocker | TypeScript error | +| app/components/layout/AppHeader.vue | 4 | useSetLocale not found | Blocker | TypeScript error | + +### Requirements Coverage + +| Requirement | Description | Status | Evidence | +|-------------|-------------|--------|----------| +| I18N-01 | prefix_except_default FR=/, EN=/en/ | SATISFIED | nuxt.config.ts i18n.strategy | +| I18N-02 | Browser detection + cookie persistence | SATISFIED | detectBrowserLanguage config | +| I18N-03 | Language switcher in header | SATISFIED (TS issue) | AppHeader toggleLocale function | +| I18N-04 | Server reads cookie, no hydration mismatch | UNCERTAIN | Needs runtime verification | +| I18N-05 | FR/EN translation files migrated | SATISFIED | 509 lines each with all keys | +| THEME-01 | Dark/light toggle in header | SATISFIED | AppHeader toggleTheme function | +| THEME-02 | Theme persisted in cookie (SSR-safe) | SATISFIED | colorMode.storage: 'cookie' | +| THEME-03 | No FOUC on cold load | UNCERTAIN | Needs visual inspection | +| SEO-01 | title, meta desc, og:title, og:description per page | SATISFIED | useSeoMeta on all 6 pages | +| SEO-02 | JSON-LD on homepage | SATISFIED | Person + ProfessionalService schema | +| SEO-03 | Sitemap with hreflang alternates | UNCERTAIN | Module present, no explicit config | +| SEO-04 | og:image absolute URLs on every page | PARTIAL | URLs present but og-image.png is placeholder text | +| COMP-05 | Header with nav + toggles + mobile drawer | SATISFIED (TS issue) | Full implementation | +| COMP-06 | Footer with links | SATISFIED | Social links + copyright | + +### Human Verification Required + +### 1. SSR French/English HTML rendering +**Test:** Start `pnpm dev`, run `curl http://localhost:3000` and `curl http://localhost:3000/en/` +**Expected:** French HTML with `` and English HTML with ``, both with SEO metadata +**Why human:** TypeScript errors may not block dev server; need to confirm SSR output + +### 2. Language persistence across reload +**Test:** Click language toggle in header, reload the page +**Expected:** Language stays on the selected locale (cookie-based) +**Why human:** Requires browser interaction and cookie inspection + +### 3. Theme persistence with no FOUC +**Test:** Set light mode, close tab, reopen -- observe first paint +**Expected:** Light theme rendered immediately, no dark flash +**Why human:** FOUC is a visual timing issue + +### 4. Sitemap hreflang verification +**Test:** Visit `http://localhost:3000/sitemap.xml` +**Expected:** XML with `` for each URL +**Why human:** Requires running server; sitemap is generated at runtime + +### Gaps Summary + +**3 TypeScript errors block a clean build** and represent the primary gap. The errors are: + +1. **useSetLocale** (AppHeader.vue:4) -- This auto-import name may not exist in the installed @nuxtjs/i18n version. The correct API might be `const { setLocale } = useI18n()` or a different composable name. + +2. **addSeoAttributes** (app.vue:3) -- The `useLocaleHead` options type doesn't include this property in the current i18n version. The API may have changed between versions. + +3. **process.env** (nuxt.config.ts:54) -- Needs `import.meta.env` instead, or @types/node in tsconfig includes. + +The **og-image.png placeholder** is a known stub (documented in 02-01-SUMMARY.md) but means SEO-04 (og:image) is technically incomplete. + +The **sitemap hreflang** generation cannot be confirmed without a running server. + +--- + +_Verified: 2026-04-08T18:00:00Z_ +_Verifier: Claude (gsd-verifier)_ diff --git a/app/app.vue b/app/app.vue index e68ab52..87bde27 100644 --- a/app/app.vue +++ b/app/app.vue @@ -1,6 +1,6 @@