---
phase: 02-ssr-shell
plan: 01
type: execute
wave: 1
depends_on: []
files_modified:
  - nuxt.config.ts
  - app.config.ts
  - app/assets/css/main.css
  - app/locales/fr.json
  - app/locales/en.json
  - public/og-image.png
autonomous: true
requirements: [I18N-01, I18N-02, I18N-04, I18N-05, THEME-02, THEME-03, SEO-03]

must_haves:
  truths:
    - "Color mode cookie config is FOUC-free with dark default"
    - "i18n baseUrl is set for absolute canonical/hreflang URLs"
    - "fr.json and en.json contain nav, footer, seo, and a11y translation keys"
    - "Sitemap generates with hreflang alternates"
    - "Brand color #85cb85 is defined as CSS theme variable and referenced in app.config.ts"
  artifacts:
    - path: "app/assets/css/main.css"
      provides: "@theme with --color-brand-* shades"
      contains: "--color-brand-500"
    - path: "app.config.ts"
      provides: "Nuxt UI primary color mapping"
      contains: "primary: 'brand'"
    - path: "app/locales/fr.json"
      provides: "French translations for Phase 2"
      contains: "nav"
    - path: "app/locales/en.json"
      provides: "English translations for Phase 2"
      contains: "nav"
  key_links:
    - from: "app.config.ts"
      to: "app/assets/css/main.css"
      via: "brand color name reference"
      pattern: "primary.*brand"
    - from: "nuxt.config.ts"
      to: "app/assets/css/main.css"
      via: "css config array"
      pattern: "css.*main.css"
---

<objective>
Configure the design system, color-mode, i18n translations, and sitemap for SSR-safe rendering.

Purpose: Lay the cross-cutting foundation (colors, translations, cookies) that the header/footer/SEO plans depend on.
Output: nuxt.config.ts with color-mode, app.config.ts with brand color, main.css with @theme, enriched fr.json/en.json, static og:image.
</objective>

<execution_context>
@~/.claude/get-shit-done/workflows/execute-plan.md
@~/.claude/get-shit-done/templates/summary.md
</execution_context>

<context>
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/STATE.md
@.planning/phases/02-ssr-shell/02-CONTEXT.md
@.planning/phases/02-ssr-shell/02-RESEARCH.md
@.planning/phases/02-ssr-shell/02-UI-SPEC.md

<interfaces>
<!-- From nuxt.config.ts (current state): -->
<!-- modules: ['@nuxt/ui', '@nuxtjs/i18n', '@nuxt/eslint', '@nuxtjs/sitemap', 'nuxt-gtag', '@nuxt/image'] -->
<!-- i18n already configured with prefix_except_default, FR default, cookie detection -->
<!-- CRITICAL: Do NOT add @nuxtjs/color-mode to modules[] — @nuxt/ui auto-registers it -->
</interfaces>
</context>

<tasks>

<task type="auto">
  <name>Task 1: Design system + color-mode + sitemap config</name>
  <files>app/assets/css/main.css, app.config.ts, nuxt.config.ts</files>
  <read_first>
    - nuxt.config.ts (current module list — do NOT duplicate color-mode)
    - .planning/phases/02-ssr-shell/02-RESEARCH.md (Pattern 5 for CSS @theme, Pattern 1 for colorMode config)
    - .planning/phases/02-ssr-shell/02-UI-SPEC.md (color section for exact hex values)
    - src/config/site.ts (site URL: https://killiandalcin.fr)
  </read_first>
  <action>
1. Create `app/assets/css/main.css` with Tailwind v4 + Nuxt UI imports and brand color @theme:
```css
@import "tailwindcss";
@import "@nuxt/ui";

@theme {
  --color-brand-50: #f0faf0;
  --color-brand-100: #dcf3dc;
  --color-brand-200: #bbe8bb;
  --color-brand-300: #8dd98d;
  --color-brand-400: #a3d6a3;
  --color-brand-500: #85cb85;
  --color-brand-600: #5aaa5a;
  --color-brand-700: #3f8c3f;
  --color-brand-800: #2e6b2e;
  --color-brand-900: #1f4f1f;
  --color-brand-950: #122d12;
}
```

2. Create `app.config.ts`:
```typescript
export default defineAppConfig({
  ui: {
    colors: {
      primary: 'brand',
    },
  },
})
```

3. Update `nuxt.config.ts` — add these keys (do NOT add @nuxtjs/color-mode to modules[]):
- `css: ['~/assets/css/main.css']`
- `colorMode` block: `{ preference: 'dark', fallback: 'dark', storage: 'cookie', storageKey: 'nuxt-color-mode', cookieName: 'nuxt-color-mode', classSuffix: '' }`
- `i18n.baseUrl: 'https://killiandalcin.fr'`
- `site: { url: 'https://killiandalcin.fr', name: 'Killian Dalcin - Developpeur Full Stack' }`

Do NOT touch existing modules array or i18n locale config — they are correct from Phase 1.

4. Copy or create a static og:image file at `public/og-image.png` (1200x630). If no real image available, create a placeholder text file noting it needs a real image. Per user decision: static image in public/, no nuxt-og-image module.
  </action>
  <verify>
    <automated>grep -q "color-brand-500" app/assets/css/main.css && grep -q "primary.*brand" app.config.ts && grep -q "colorMode" nuxt.config.ts && grep -q "baseUrl" nuxt.config.ts && grep -q "css:" nuxt.config.ts && echo "PASS" || echo "FAIL"</automated>
  </verify>
  <acceptance_criteria>
    - app/assets/css/main.css contains `--color-brand-500: #85cb85`
    - app/assets/css/main.css contains `@import "tailwindcss"` and `@import "@nuxt/ui"`
    - app.config.ts contains `primary: 'brand'`
    - nuxt.config.ts contains `colorMode:` with `storage: 'cookie'` and `preference: 'dark'`
    - nuxt.config.ts contains `baseUrl: 'https://killiandalcin.fr'` inside i18n block
    - nuxt.config.ts contains `site:` with `url: 'https://killiandalcin.fr'`
    - nuxt.config.ts does NOT contain `'@nuxtjs/color-mode'` in modules array
    - nuxt.config.ts contains `css: ['~/assets/css/main.css']`
    - public/og-image.png exists
  </acceptance_criteria>
  <done>Design system configured: brand color in CSS @theme, Nuxt UI maps primary to brand, color-mode uses cookie with dark default, i18n baseUrl and site.url set for absolute SEO URLs, static og:image in public/.</done>
</task>

<task type="auto">
  <name>Task 2: Migrate i18n translations for Phase 2 scope</name>
  <files>app/locales/fr.json, app/locales/en.json</files>
  <read_first>
    - app/locales/fr.json (currently empty {})
    - app/locales/en.json (currently empty {})
    - src/locales/fr.ts (source translations to migrate — nav, footer keys)
    - src/locales/en.ts (source EN translations)
    - .planning/phases/02-ssr-shell/02-UI-SPEC.md (Copywriting Contract table — exact copy for all nav, footer, a11y keys)
    - app/data/projects.ts (check which i18n keys projects reference — those need translation entries too)
  </read_first>
  <action>
Enrich app/locales/fr.json and app/locales/en.json with ALL keys needed by Phase 2 (header, footer, SEO metadata, accessibility labels). Also migrate existing project/page translation keys from src/locales/ that are already referenced by data files.

**Phase 2 keys to add (from UI-SPEC Copywriting Contract):**

fr.json top-level structure:
```json
{
  "nav": {
    "home": "Accueil",
    "projects": "Projets",
    "about": "A propos",
    "contact": "Contact",
    "fiverr": "Fiverr",
    "formation": "Formation"
  },
  "footer": {
    "copyright": "© 2026 Killian Dalcin"
  },
  "a11y": {
    "logoLabel": "Killian Dalcin — Developpeur Full Stack — Retour a l'accueil",
    "openMenu": "Ouvrir le menu de navigation",
    "closeMenu": "Fermer le menu de navigation",
    "closeDrawer": "Fermer le menu",
    "langToggle": "Changer la langue — actuellement Francais",
    "themeDark": "Activer le mode clair",
    "themeLight": "Activer le mode sombre",
    "github": "GitHub de Killian Dalcin (nouvelle fenetre)",
    "linkedin": "LinkedIn de Killian Dalcin (nouvelle fenetre)",
    "fiverr": "Fiverr de Killian Dalcin (nouvelle fenetre)"
  },
  "seo": {
    "home": {
      "title": "Killian Dalcin — Developpeur Full Stack Freelance",
      "description": "Portfolio de Killian Dalcin, developpeur full stack freelance specialise en Vue.js, React et Node.js. Applications web performantes et solutions sur-mesure."
    },
    "projects": {
      "title": "Projets — Killian Dalcin",
      "description": "Decouvrez mes realisations en developpement web : applications Vue.js, API Node.js, bots Discord et solutions d'entreprise."
    },
    "about": {
      "title": "A propos — Killian Dalcin",
      "description": "Biographie et competences de Killian Dalcin, developpeur full stack freelance base en France."
    },
    "contact": {
      "title": "Contact — Killian Dalcin",
      "description": "Contactez Killian Dalcin pour discuter de votre projet de developpement web."
    },
    "fiverr": {
      "title": "Services Fiverr — Killian Dalcin",
      "description": "Services de developpement disponibles sur Fiverr : bots Discord, plugins Minecraft, applications web."
    },
    "formation": {
      "title": "Formation — Killian Dalcin",
      "description": "Formations et cours proposes par Killian Dalcin en developpement web."
    }
  }
}
```

en.json same structure with English translations:
```json
{
  "nav": {
    "home": "Home",
    "projects": "Projects",
    "about": "About",
    "contact": "Contact",
    "fiverr": "Fiverr",
    "formation": "Training"
  },
  "footer": {
    "copyright": "© 2026 Killian Dalcin"
  },
  "a11y": {
    "logoLabel": "Killian Dalcin — Full Stack Developer — Back to homepage",
    "openMenu": "Open navigation menu",
    "closeMenu": "Close navigation menu",
    "closeDrawer": "Close menu",
    "langToggle": "Change language — currently English",
    "themeDark": "Switch to light mode",
    "themeLight": "Switch to dark mode",
    "github": "Killian Dalcin on GitHub (opens in new tab)",
    "linkedin": "Killian Dalcin on LinkedIn (opens in new tab)",
    "fiverr": "Killian Dalcin on Fiverr (opens in new tab)"
  },
  "seo": {
    "home": {
      "title": "Killian Dalcin — Freelance Full Stack Developer",
      "description": "Portfolio of Killian Dalcin, freelance full stack developer specializing in Vue.js, React and Node.js. High-performance web applications and custom solutions."
    },
    "projects": {
      "title": "Projects — Killian Dalcin",
      "description": "Discover my web development projects: Vue.js applications, Node.js APIs, Discord bots and enterprise solutions."
    },
    "about": {
      "title": "About — Killian Dalcin",
      "description": "Biography and skills of Killian Dalcin, freelance full stack developer based in France."
    },
    "contact": {
      "title": "Contact — Killian Dalcin",
      "description": "Contact Killian Dalcin to discuss your web development project."
    },
    "fiverr": {
      "title": "Fiverr Services — Killian Dalcin",
      "description": "Development services available on Fiverr: Discord bots, Minecraft plugins, web applications."
    },
    "formation": {
      "title": "Training — Killian Dalcin",
      "description": "Training and courses offered by Killian Dalcin in web development."
    }
  }
}
```

ALSO: migrate all existing translation keys from src/locales/fr.ts and src/locales/en.ts that are referenced by app/data/*.ts files (project titles, descriptions, testimonials, FAQ, techstack categories, home page content, etc.). Merge them into the same fr.json/en.json files under their existing key structure (e.g., `projects.xinko.title`, `home.title`, etc.).

Per D-06: one file per language, enrich existing files.
  </action>
  <verify>
    <automated>node -e "const fr=require('./app/locales/fr.json'); const en=require('./app/locales/en.json'); const checks=['nav.home','footer.copyright','a11y.logoLabel','seo.home.title','seo.projects.title']; const ok=checks.every(k=>{const p=k.split('.'); let v=fr; for(const s of p) v=v?.[s]; return !!v}) && checks.every(k=>{const p=k.split('.'); let v=en; for(const s of p) v=v?.[s]; return !!v}); console.log(ok?'PASS':'FAIL')"</automated>
  </verify>
  <acceptance_criteria>
    - app/locales/fr.json contains keys: nav.home, nav.projects, nav.about, nav.contact, nav.fiverr, nav.formation
    - app/locales/fr.json contains keys: footer.copyright, a11y.logoLabel, a11y.openMenu, a11y.themeDark
    - app/locales/fr.json contains keys: seo.home.title, seo.home.description, seo.projects.title
    - app/locales/en.json contains the same key structure with English values
    - en.json nav.formation value is "Training" (not "Formation")
    - Both files are valid JSON (node -e "require('./app/locales/fr.json')" exits 0)
    - Existing i18n keys referenced by app/data/*.ts are present in both locale files
  </acceptance_criteria>
  <done>Both fr.json and en.json contain all nav, footer, a11y, seo keys from UI-SPEC copywriting contract plus migrated keys from src/locales/ for data file references.</done>
</task>

</tasks>

<threat_model>
## Trust Boundaries

| Boundary | Description |
|----------|-------------|
| Cookie → Server | i18n and color-mode cookies read by server to determine locale/theme |

## STRIDE Threat Register

| Threat ID | Category | Component | Disposition | Mitigation Plan |
|-----------|----------|-----------|-------------|-----------------|
| T-02-01 | Tampering | color-mode cookie | accept | Cookie only controls CSS class (dark/light) — no security impact if tampered |
| T-02-02 | Tampering | i18n cookie | accept | Cookie only controls locale (fr/en) — no security impact if tampered |
| T-02-03 | Information Disclosure | site.url in nuxt.config | accept | Public URL, no secret information |
</threat_model>

<verification>
- `npx nuxi typecheck` passes
- `pnpm dev` starts without errors
- fr.json and en.json are valid JSON with all Phase 2 keys
</verification>

<success_criteria>
- Brand color #85cb85 registered as Nuxt UI primary
- Color-mode configured with cookie storage, dark default, no FOUC
- i18n baseUrl set for absolute hreflang/canonical URLs
- All Phase 2 translation keys present in both locale files
- Static og:image exists in public/
</success_criteria>

<output>
After completion, create `.planning/phases/02-ssr-shell/02-01-SUMMARY.md`
</output>
