diff --git a/.planning/REQUIREMENTS.md b/.planning/REQUIREMENTS.md
index 8eb48a3..d50b8b0 100644
--- a/.planning/REQUIREMENTS.md
+++ b/.planning/REQUIREMENTS.md
@@ -98,13 +98,50 @@
| Requirement | Phase | Status |
|-------------|-------|--------|
-| (populated during roadmap creation) | | |
+| SSR-01 | Phase 1 | Pending |
+| SSR-02 | Phase 1 | Pending |
+| SSR-03 | Phase 1 | Pending |
+| DATA-01 | Phase 1 | Pending |
+| DATA-02 | Phase 1 | Pending |
+| DATA-03 | Phase 1 | Pending |
+| DATA-04 | Phase 1 | Pending |
+| DATA-05 | Phase 1 | Pending |
+| INFRA-02 | Phase 1 | Pending |
+| INFRA-03 | Phase 1 | Pending |
+| I18N-01 | Phase 2 | Pending |
+| I18N-02 | Phase 2 | Pending |
+| I18N-03 | Phase 2 | Pending |
+| I18N-04 | Phase 2 | Pending |
+| I18N-05 | Phase 2 | Pending |
+| THEME-01 | Phase 2 | Pending |
+| THEME-02 | Phase 2 | Pending |
+| THEME-03 | Phase 2 | Pending |
+| SEO-01 | Phase 2 | Pending |
+| SEO-02 | Phase 2 | Pending |
+| SEO-03 | Phase 2 | Pending |
+| SEO-04 | Phase 2 | Pending |
+| COMP-05 | Phase 2 | Pending |
+| COMP-06 | Phase 2 | Pending |
+| PAGE-01 | Phase 3 | Pending |
+| PAGE-02 | Phase 3 | Pending |
+| PAGE-03 | Phase 3 | Pending |
+| PAGE-04 | Phase 3 | Pending |
+| PAGE-05 | Phase 3 | Pending |
+| PAGE-06 | Phase 3 | Pending |
+| PAGE-07 | Phase 3 | Pending |
+| PAGE-08 | Phase 3 | Pending |
+| COMP-01 | Phase 3 | Pending |
+| COMP-02 | Phase 3 | Pending |
+| COMP-03 | Phase 3 | Pending |
+| COMP-04 | Phase 3 | Pending |
+| INFRA-01 | Phase 3 | Pending |
+| INFRA-04 | Phase 3 | Pending |
**Coverage:**
-- v1 requirements: 35 total
-- Mapped to phases: 0
-- Unmapped: 35 ⚠️
+- v1 requirements: 38 total
+- Mapped to phases: 38
+- Unmapped: 0 ✓
---
*Requirements defined: 2026-04-07*
-*Last updated: 2026-04-07 after initial definition*
+*Last updated: 2026-04-07 after roadmap creation*
diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md
new file mode 100644
index 0000000..7dcba86
--- /dev/null
+++ b/.planning/ROADMAP.md
@@ -0,0 +1,67 @@
+# Roadmap: Portfolio Killian Dalcin — Nuxt 4 Migration
+
+## Overview
+
+Three phases following the strict build order from research: first lay the Nuxt 4 project skeleton with all modules configured and data migrated, then implement the SSR-critical cross-cutting concerns (i18n, theme, SEO, header/footer), and finally build all pages and ship to production via Docker. Every page is crawlable by search engines when Phase 3 completes.
+
+## Phases
+
+**Phase Numbering:**
+- Integer phases (1, 2, 3): Planned milestone work
+- Decimal phases (2.1, 2.2): Urgent insertions (marked with INSERTED)
+
+Decimal phases appear between their surrounding integers in numeric order.
+
+- [ ] **Phase 1: Foundation** - Nuxt 4 project scaffold, all modules configured, static data migrated, composables ported
+- [ ] **Phase 2: SSR Shell** - i18n FR/EN, dark/light theme, SEO per route, header + footer layout
+- [ ] **Phase 3: Pages & Ship** - All 8 pages, interactive components, EmailJS plugin, GA4, Dockerfile
+
+## Phase Details
+
+### Phase 1: Foundation
+**Goal**: The Nuxt 4 project runs locally with all modules installed, data in `data/`, composables wired, and TypeScript strict mode passing
+**Depends on**: Nothing (first phase)
+**Requirements**: SSR-01, SSR-02, SSR-03, DATA-01, DATA-02, DATA-03, DATA-04, DATA-05, INFRA-02, INFRA-03
+**Success Criteria** (what must be TRUE):
+ 1. `nuxt dev` starts without errors and serves a blank app at `localhost:3000`
+ 2. All static data files exist under `data/` and are importable with TypeScript strict — no `any` types
+ 3. `useProjects()` composable returns typed project list and supports filtering by category and search
+ 4. `npx nuxi typecheck` and `npx eslint .` exit with 0 errors
+**Plans**: TBD
+
+### Phase 2: SSR Shell
+**Goal**: Every route renders the correct language, theme, and SEO metadata on the server — confirmed by `curl` with no JavaScript
+**Depends on**: Phase 1
+**Requirements**: I18N-01, I18N-02, I18N-03, I18N-04, I18N-05, THEME-01, THEME-02, THEME-03, SEO-01, SEO-02, SEO-03, SEO-04, COMP-05, COMP-06
+**Success Criteria** (what must be TRUE):
+ 1. `curl http://localhost:3000` returns French HTML; `curl http://localhost:3000/en/` returns English HTML — no JS required
+ 2. Switching language via the header dropdown persists across page reload (cookie, no FOUC)
+ 3. Toggling dark/light mode in the header persists across page reload with no flash on cold load
+ 4. `curl http://localhost:3000` response includes `
`, `og:title`, `og:description`, and JSON-LD script tag
+ 5. `http://localhost:3000/sitemap.xml` returns a valid XML sitemap with `hreflang` alternates for FR and EN URLs
+**Plans**: TBD
+**UI hint**: yes
+
+### Phase 3: Pages & Ship
+**Goal**: All portfolio pages are live, forms work, analytics fire in production, and the Docker image builds and runs
+**Depends on**: Phase 2
+**Requirements**: PAGE-01, PAGE-02, PAGE-03, PAGE-04, PAGE-05, PAGE-06, PAGE-07, PAGE-08, COMP-01, COMP-02, COMP-03, COMP-04, INFRA-01, INFRA-04
+**Success Criteria** (what must be TRUE):
+ 1. All 8 routes (`/`, `/projects`, `/project/[id]`, `/about`, `/contact`, `/fiverr`, `/formation`, 404) return complete HTML when fetched with `curl`
+ 2. Clicking an image in a project detail page opens a modal carousel with keyboard navigation (arrow keys + Escape closes)
+ 3. Submitting the contact form with valid data shows a success toast; EmailJS delivers the email
+ 4. `docker build` completes and `docker run` serves the SSR app on port 3000
+ 5. Google Analytics 4 events appear in GA4 DebugView when browsing in production mode
+**Plans**: TBD
+**UI hint**: yes
+
+## Progress
+
+**Execution Order:**
+Phases execute in numeric order: 1 → 2 → 3
+
+| Phase | Plans Complete | Status | Completed |
+|-------|----------------|--------|-----------|
+| 1. Foundation | 0/TBD | Not started | - |
+| 2. SSR Shell | 0/TBD | Not started | - |
+| 3. Pages & Ship | 0/TBD | Not started | - |
diff --git a/.planning/STATE.md b/.planning/STATE.md
new file mode 100644
index 0000000..2c0a2a1
--- /dev/null
+++ b/.planning/STATE.md
@@ -0,0 +1,64 @@
+# Project State
+
+## Project Reference
+
+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 Position
+
+Phase: 1 of 3 (Foundation)
+Plan: 0 of TBD in current phase
+Status: Ready to plan
+Last activity: 2026-04-07 — Roadmap created, project initialized
+
+Progress: [░░░░░░░░░░] 0%
+
+## Performance Metrics
+
+**Velocity:**
+- Total plans completed: 0
+- Average duration: —
+- Total execution time: 0 hours
+
+**By Phase:**
+
+| Phase | Plans | Total | Avg/Plan |
+|-------|-------|-------|----------|
+| - | - | - | - |
+
+**Recent Trend:**
+- Last 5 plans: —
+- Trend: —
+
+*Updated after each plan completion*
+
+## Accumulated Context
+
+### Decisions
+
+Decisions are logged in PROJECT.md Key Decisions table.
+Recent decisions affecting current work:
+
+- Init: Use `@nuxtjs/seo` meta-bundle (covers sitemap + og:image + schema-org) instead of standalone modules
+- Init: SSR mode (not SSG) — i18n cookie detection requires server execution per request
+- Init: Cookie-only persistence for i18n + theme (SSR-safe, no localStorage)
+- Init: Static TS data files under `data/` (no @nuxt/content needed)
+
+### Pending Todos
+
+None yet.
+
+### Blockers/Concerns
+
+- Open: Confirm @nuxtjs/i18n v9 stable + Nuxt 4 compatible before Phase 2 planning
+- Open: Confirm @nuxt/ui v3 stable (not beta/rc) before Phase 1 planning
+- Open: Confirm nuxt-gtag Nuxt 4 compatibility before Phase 3 planning
+
+## Session Continuity
+
+Last session: 2026-04-07
+Stopped at: Roadmap created — ready to plan Phase 1
+Resume file: None
diff --git a/CLAUDE.md b/CLAUDE.md
new file mode 100644
index 0000000..b7a7bc9
--- /dev/null
+++ b/CLAUDE.md
@@ -0,0 +1,313 @@
+
+## Project
+
+**Portfolio Killian Dalcin — Migration Nuxt 4**
+
+Migration complète d'un portfolio freelance de Vue 3 SPA vers Nuxt 4 avec SSR complet. Le site présente les projets, services et compétences de Killian Dalcin, développeur freelance, avec support bilingue FR/EN. L'objectif est un SEO parfait et un développement rapide via des composants prêts à l'emploi (Nuxt UI v3).
+
+**Core Value:** Chaque page du portfolio doit être crawlable par les moteurs de recherche sans JavaScript côté client — le SSR est la raison d'être de cette migration.
+
+### Constraints
+
+- **Stack**: Nuxt 4 + Nuxt UI v3 + Tailwind v4 — dernières versions stables
+- **Coût**: Zéro dépendance payante
+- **Composants**: Nuxt UI v3 en priorité sur le custom (80% suffit)
+- **TypeScript**: Mode strict partout
+- **Déploiement**: Docker node:22-alpine, nuxt build (SSR) ou nuxt generate (SSG) selon stratégie
+- **i18n/Theme**: Persistance cookie uniquement (SSR-safe), pas de localStorage
+
+
+
+## Technology Stack
+
+## Languages
+- TypeScript ~5.8.0 - Full application development
+- JavaScript (ES modules) - Frontend runtime
+- HTML5 - Document structure (in `index.html`)
+- CSS - Styling with Tailwind CSS
+- Markdown - Documentation (README.md)
+- YAML - Configuration (implied through Dockerfile)
+## Runtime
+- Node.js 22 - Development and build environment
+- Browser environment - Vue 3 SFC runtime
+- npm - Dependency management
+- Lockfile: `package-lock.json` (present and tracked)
+## Frameworks
+- Vue 3.5.13 - Progressive JavaScript framework for UI
+- Vue Router 4.5.0 - Client-side routing with lazy-loaded pages
+- Pinia 3.0.1 - State management (minimal usage - currently only `counter.ts`)
+- Vue I18n 9.14.4 - Internationalization (English and French locale files in `src/locales/`)
+- Vite 6.2.4 - Build tool and dev server
+- Vite Plugin Vue DevTools 7.7.2 - Development utilities
+- @vitejs/plugin-vue 5.2.3 - Vue 3 SFC support
+- Tailwind CSS 4.1.10 - Utility-first CSS framework
+- @tailwindcss/postcss 4.1.10 - PostCSS plugin for Tailwind
+- PostCSS 8.5.6 - CSS transformation pipeline
+- Autoprefixer 10.4.21 - Vendor prefix handling
+- Terser 5.43.1 - JavaScript minification
+- ESLint 9.22.0 - Linting (config: `eslint.config.ts`)
+- Prettier 3.5.3 - Code formatting (config: `.prettierrc.json`)
+- vue-tsc 2.2.8 - Vue component type checking
+- TypeScript compiler with `type-check` npm script
+- @vueuse/head 2.0.0 - Dynamic document head management for meta tags and SEO
+## Key Dependencies
+- vue 3.5.13 - Core framework
+- vue-router 4.5.0 - SPA routing with code splitting
+- pinia 3.0.1 - State management store
+- vue-i18n 9.14.4 - Multi-language support
+- vite 6.2.4 - Next-gen build tool with HMR
+- tailwindcss 4.1.10 - Rapid UI development
+- typescript 5.8.0 - Static typing and compilation
+- eslint 9.22.0 - Code linting
+- prettier 3.5.3 - Code formatting
+- npm-run-all2 7.0.2 - Parallel script execution (used in build process)
+- @tsconfig/node22 22.0.1 - TSConfig preset for Node 22
+- @types/node 22.14.0 - Node.js type definitions
+- jiti 2.4.2 - CommonJS loader for TypeScript modules
+## Configuration
+- No `.env` files detected in source
+- Google Analytics tracking ID hardcoded: `G-CDVVNFY6MV` (in `index.html`)
+- Umami analytics script loaded from `umami.killiandalcin.fr` (in `index.html`)
+- Google AdSense client ID hardcoded: `ca-pub-5219367964457248` (in `index.html`)
+- `vite.config.ts` - Build optimizations:
+- `tsconfig.json` - References `tsconfig.app.json` and `tsconfig.node.json`
+- `tsconfig.app.json`:
+- `eslint.config.ts` - Flat config format:
+- `.prettierrc.json`:
+- `postcss.config.js` - Tailwind CSS and Autoprefixer
+- `tailwind.config.js` - Content scanning for `index.html` and `src/**/*.{vue,js,ts,jsx,tsx}`
+## Platform Requirements
+- Node.js 22+ (specified in Dockerfile)
+- npm 10+ (implied by Node 22)
+- TypeScript 5.8+
+- Any Unix-like shell (bash/zsh) or Windows with Node.js
+- Docker - Multi-stage build with Node 22-alpine and nginx stable-alpine
+- Web server: nginx (configured in `nginx.conf`)
+- Deployment target: Static HTML served via nginx
+- JavaScript enabled (noscript fallback message in `index.html`)
+- Modern browsers with ES2020+ support (Vite default targets)
+## Scripts & Commands
+
+
+
+## Conventions
+
+## Naming Patterns
+- Vue components: PascalCase (e.g., `AppHeader.vue`, `ProjectCard.vue`)
+- Composables: camelCase with `use` prefix (e.g., `useTheme.ts`, `useProjects.ts`)
+- Utility/config files: camelCase (e.g., `site.ts`, `techstack.ts`)
+- Data files: camelCase (e.g., `testimonials.ts`, `faq.ts`)
+- Type definitions: camelCase in `types/index.ts`
+- All functions use camelCase (e.g., `toggleTheme`, `openGallery`, `getImageUrl`)
+- Composables are named with `use` prefix: `useTheme()`, `useGallery()`, `useSeo()`
+- Getter functions use `get` prefix: `getTheme()`, `getImageUrl()`
+- Boolean functions/computed use `is`/`has` prefix: `isDark`, `hasNext`, `isOpen`
+- Handler functions use verb + `Handler`: `toggleTheme`, `openGallery`, `closeGallery`
+- Refs and computed properties: camelCase (e.g., `isDark`, `currentIndex`, `isOpen`)
+- Interfaces and types: PascalCase (e.g., `Props`, `SeoOptions`, `Theme`)
+- Constants: UPPER_SNAKE_CASE for config constants (not extensively used in codebase)
+- Private/module state: camelCase prefixed with `_` if truly private
+- Type aliases: PascalCase (e.g., `type Theme = 'light' | 'dark'`)
+- Interface names: PascalCase (e.g., `interface Props`, `interface SeoOptions`)
+- Props interfaces: Always named `Props` (e.g., in `