diff --git a/.planning/research/ARCHITECTURE.md b/.planning/research/ARCHITECTURE.md
new file mode 100644
index 0000000..18e497a
--- /dev/null
+++ b/.planning/research/ARCHITECTURE.md
@@ -0,0 +1,333 @@
+# Architecture Patterns
+
+**Project:** Portfolio Killian' Dalcin — Nuxt 4 SSR
+**Researched:** 2026-04-10
+**Confidence:** HIGH (verified against actual codebase + Nuxt 4 docs patterns)
+
+---
+
+## Is the Current Architecture Sound?
+
+**Yes — the foundation is solid.** The core SSR pipeline is correctly implemented:
+
+- `ssr: true` + `compatibilityVersion: 4` — full SSR, not hybrid
+- `@nuxtjs/i18n` with `prefix_except_default` — SEO-correct URL scheme (FR at `/`, EN at `/en/`)
+- `@nuxtjs/color-mode` with `storage: 'cookie'` — theme class applied server-side, no flash
+- `useSeoMeta()` with reactive `() => t('...')` callbacks — meta resolves server-side per locale
+- `useLocaleHead()` in `app.vue` — injects `hreflang` alternates on every page automatically
+- Data layer (`app/data/*.ts` + `useProjects()`) is clean: static IDs, translated fields via i18n keys, reactive recomputation on locale change
+
+Three real problems exist in the current implementation (not architecture flaws — just execution gaps):
+
+1. **og:image hardcoded** to `https://killiandalcin.fr/og-image.png` on all 6 pages, including project detail where `project.image` is already available
+2. **JSON-LD only on homepage** — other pages have no structured data; `jobTitle` still says "Developpeur Full Stack Freelance" instead of positioning Hytale
+3. **ogUrl missing** — `useSeoMeta()` calls don't include `ogUrl`, so the canonical URL is absent from Open Graph, though `` is provided by `@nuxtjs/i18n`
+
+---
+
+## Recommended Architecture
+
+The existing layer structure is correct. No refactoring needed. Extensions follow the same pattern:
+
+```
+Pages (app/pages/)
+ hytale.vue ← new page, same pattern as fiverr.vue
+ project/[id].vue ← add dynamic og:image (project.image already there)
+
+Composables (app/composables/)
+ useSeoMeta → per-page calls ← add ogUrl to every page
+ useJsonLd.ts ← new: centralize JSON-LD generation
+
+Data (app/data/)
+ hytale.ts ← new: pricing tiers, service cards, tech highlights
+ site.ts ← update jobTitle to Hytale positioning
+
+Locales (app/locales/fr.json, en.json)
+ seo.hytale.* ← new SEO keys
+ hytale.* ← new page content keys
+```
+
+### Component Boundaries for the Hytale Page
+
+| Component | Responsibility | Communicates With |
+|-----------|---------------|-------------------|
+| `pages/hytale.vue` | Page assembly, SEO, JSON-LD | `HytaleHeroSection`, `HytalePricingGrid`, `HytaleServiceCards`, `FAQSection`, `CTASection` |
+| `sections/HytaleHeroSection.vue` | Hero — "Hytale Plugin Developer" headline, early access badge | `useI18n()` |
+| `sections/HytalePricingGrid.vue` | 3-column pricing table (Simple / Complex / Sur-mesure + Maintenance) | `app/data/hytale.ts` via props |
+| `sections/HytaleServiceCards.vue` | What's included per service, tech stack used | `app/data/hytale.ts` via props |
+| Reuse `FAQSection.vue` | Hytale-specific FAQs | `data/faq.ts` (add `hytaleFAQs` export) |
+| Reuse `CTASection.vue` | Call to action to contact / Fiverr | props |
+
+Follow the `fiverr.vue` structural pattern exactly — it already does service cards correctly. The Hytale page is a thematic variant, not a new pattern.
+
+---
+
+## og:image Hardcoding Fix
+
+**Problem:** All pages including `project/[id].vue` use the same static `og-image.png`. The project detail page already has `project.value?.image` available but ignores it.
+
+**Fix: per-page og:image strategy**
+
+```typescript
+// pages/project/[id].vue — already has project data, just use it
+useSeoMeta({
+ // ...
+ ogImage: () => project.value?.image
+ ? `https://killiandalcin.fr${project.value.image}`
+ : 'https://killiandalcin.fr/og-image.png',
+})
+```
+
+For all other pages, create dedicated OG images rather than sharing one. The naming convention:
+
+| Page | File | Dimensions |
+|------|------|-----------|
+| Default / fallback | `/public/og/og-default.png` | 1200×630 |
+| Hytale | `/public/og/og-hytale.png` | 1200×630 |
+| Fiverr | `/public/og/og-fiverr.png` | 1200×630 |
+| Projects | `/public/og/og-projects.png` | 1200×630 |
+
+Each page's `useSeoMeta()` references its own file. This is the simplest, most reliable approach — no server-side image generation required, works perfectly with SSR, zero dependencies.
+
+**Do not use `@vercel/og` or `nuxt-og-image`.** The portfolio is Docker-deployed, not Vercel. `nuxt-og-image` adds a Satori/Chromium dependency and requires additional config for non-Vercel deployments. Static pre-made images are sufficient for a portfolio and have zero runtime cost.
+
+---
+
+## Canonical URL Strategy with prefix_except_default
+
+**Current situation:** `@nuxtjs/i18n` with `prefix_except_default` + `baseUrl: 'https://killiandalcin.fr'` automatically generates:
+
+```html
+
+
+
+
+
+
+
+
+
+
+```
+
+This is correct — `useLocaleHead()` in `app.vue` handles all of this automatically. **No manual canonical management needed.**
+
+The one gap is `ogUrl` in Open Graph. Add it to every page's `useSeoMeta()`:
+
+```typescript
+// Pattern for every page
+const { locale } = useI18n()
+const localePath = useLocalePath()
+
+useSeoMeta({
+ // ... existing fields ...
+ ogUrl: () => `https://killiandalcin.fr${localePath('/hytale')}`,
+})
+```
+
+`useLocalePath()` resolves the correct prefixed path for the current locale (`/hytale` for FR, `/en/hytale` for EN), making `ogUrl` SSR-safe and locale-correct.
+
+**For the sitemap:** `@nuxtjs/sitemap` already reads from `@nuxtjs/i18n` configuration and generates hreflang entries automatically. No manual sitemap management needed for the Hytale page — it appears automatically when `pages/hytale.vue` is created.
+
+---
+
+## JSON-LD Structured Data Patterns
+
+### What to Use Per Page
+
+| Page | Schema Types | Priority |
+|------|-------------|----------|
+| `/` (homepage) | `Person` + `WebSite` + `ProfessionalService` | Exists, needs update |
+| `/hytale` | `Service` (×3 tiers) + `SoftwareApplication` | New |
+| `/projects` | `ItemList` of `SoftwareSourceCode` | Nice to have |
+| `/project/[id]` | `SoftwareSourceCode` or `CreativeWork` | Nice to have |
+| `/fiverr` | `Offer` per service | Nice to have |
+| `/contact` | `ContactPage` | Low value |
+
+### Centralize with a Composable
+
+The current pattern inlines JSON-LD in each page's `useHead()`. This works but leads to duplication of `Person` data across pages. Centralize reusable schemas:
+
+```typescript
+// app/composables/useJsonLd.ts
+export function usePersonSchema() {
+ return {
+ '@type': 'Person',
+ name: "Killian' DAL-CIN",
+ url: 'https://killiandalcin.fr',
+ jobTitle: 'Hytale Plugin Developer & Full Stack Developer',
+ email: 'contact@killiandalcin.fr',
+ sameAs: [
+ 'https://linkedin.com/in/killian-dal-cin',
+ 'https://www.fiverr.com/users/mr_kayjaydee',
+ 'https://gitea.kamisama.ovh/kayjaydee',
+ ],
+ }
+}
+
+export function useWebSiteSchema() {
+ return {
+ '@type': 'WebSite',
+ name: "Killian' DAL-CIN",
+ url: 'https://killiandalcin.fr',
+ potentialAction: {
+ '@type': 'SearchAction',
+ target: 'https://killiandalcin.fr/projects?q={search_term_string}',
+ 'query-input': 'required name=search_term_string',
+ },
+ }
+}
+
+export function useHytaleServiceSchemas() {
+ return [
+ {
+ '@type': 'Service',
+ name: 'Hytale Plugin Development — Simple',
+ provider: { '@type': 'Person', name: "Killian' DAL-CIN" },
+ serviceType: 'Software Development',
+ description: 'Basic Hytale plugin: single mechanic, standard features',
+ offers: { '@type': 'Offer', priceCurrency: 'USD', price: '150' },
+ },
+ {
+ '@type': 'Service',
+ name: 'Hytale Plugin Development — Complex',
+ provider: { '@type': 'Person', name: "Killian' DAL-CIN" },
+ serviceType: 'Software Development',
+ description: 'Advanced Hytale plugin with custom systems, multiplayer, persistence',
+ offers: { '@type': 'Offer', priceCurrency: 'USD', price: '400' },
+ },
+ {
+ '@type': 'Service',
+ name: 'Hytale Plugin Maintenance',
+ provider: { '@type': 'Person', name: "Killian' DAL-CIN" },
+ serviceType: 'Software Maintenance',
+ description: 'Monthly plugin maintenance: update compatibility after Hytale patches',
+ offers: { '@type': 'Offer', priceCurrency: 'USD', priceSpecification: { '@type': 'UnitPriceSpecification', price: '50', unitCode: 'MON' } },
+ },
+ ]
+}
+```
+
+Each page then composes what it needs:
+
+```typescript
+// pages/index.vue
+const { usePersonSchema, useWebSiteSchema } = useJsonLd()
+useHead({
+ script: [{
+ type: 'application/ld+json',
+ innerHTML: JSON.stringify({
+ '@context': 'https://schema.org',
+ '@graph': [usePersonSchema(), useWebSiteSchema()],
+ }),
+ }],
+})
+
+// pages/hytale.vue
+const { usePersonSchema, useHytaleServiceSchemas } = useJsonLd()
+useHead({
+ script: [{
+ type: 'application/ld+json',
+ innerHTML: JSON.stringify({
+ '@context': 'https://schema.org',
+ '@graph': [usePersonSchema(), ...useHytaleServiceSchemas()],
+ }),
+ }],
+})
+```
+
+### SoftwareApplication for Hytale Plugins
+
+For the Hytale page, `SoftwareApplication` is the most SEO-relevant schema for plugin demos or featured work:
+
+```json
+{
+ "@type": "SoftwareApplication",
+ "name": "Hytale Plugin — [Plugin Name]",
+ "applicationCategory": "GameApplication",
+ "operatingSystem": "Hytale",
+ "author": { "@type": "Person", "name": "Killian' DAL-CIN" },
+ "offers": { "@type": "Offer", "price": "0", "priceCurrency": "USD" }
+}
+```
+
+Use `SoftwareApplication` only when there are real plugin demos or releasable plugins. Use placeholder data with clearly marked demo content for now.
+
+---
+
+## Hytale Page: Pricing Grid Pattern
+
+The most effective pricing grid for this use case is a 3-tier table with a highlighted middle tier. Nuxt UI v3 provides everything needed without custom components:
+
+```vue
+
+
+
+ ...
+
+
+
+
+ Most Popular
+
+ ...
+
+
+
+ ...
+
+```
+
+Pricing data belongs in `app/data/hytale.ts` (not `siteConfig`) because it is Hytale-specific content, not site-wide configuration. Translatable labels live in locale files; prices stay in the data file (they are locale-independent).
+
+---
+
+## Anti-Patterns to Avoid
+
+### Anti-Pattern 1: Duplicating Person schema across pages as raw objects
+**What:** Copy-pasting the full `Person` object in every page file
+**Why bad:** When Killian's jobTitle changes to "Hytale Plugin Developer", every page needs updating manually
+**Instead:** `useJsonLd.ts` composable as shown above — single source of truth
+
+### Anti-Pattern 2: Using localStorage for any SSR state
+**What:** Storing locale or theme in localStorage
+**Why bad:** Causes hydration mismatch — server renders with default, client re-renders after mount
+**Instead:** Cookie-only (already correctly implemented)
+
+### Anti-Pattern 3: Static ogUrl strings
+**What:** `ogUrl: 'https://killiandalcin.fr/hytale'` hardcoded
+**Why bad:** EN version at `/en/hytale` gets wrong ogUrl, confusing social crawlers
+**Instead:** `ogUrl: () => \`https://killiandalcin.fr\${localePath('/hytale')}\``
+
+### Anti-Pattern 4: Translating prices
+**What:** Putting price strings like "$150" or "150€" in locale files
+**Why bad:** Prices change independently of language; mixes content types
+**Instead:** Prices in data file, currency/format computed if needed
+
+### Anti-Pattern 5: nuxt-og-image for a Docker-SSR deployment
+**What:** Using Satori-based dynamic OG image generation
+**Why bad:** Adds Chromium/Satori dependency, complex config for non-Vercel targets, overhead per request
+**Instead:** Static pre-made OG images per page in `/public/og/`
+
+---
+
+## Scalability Considerations
+
+This is a static-content portfolio. Scalability is not a concern. The architecture is appropriate for:
+- ~10 pages
+- ~20 projects
+- 2 locales
+- No user accounts, no dynamic data beyond the contact form
+
+The only scaling vector is content volume (more projects, more services). The current data layer (`app/data/`) handles this cleanly — add entries to arrays, add i18n keys, done.
+
+---
+
+## Sources
+
+- Nuxt 4 docs: `ssr: true`, `compatibilityVersion: 4` — verified against current nuxt.config.ts
+- `@nuxtjs/i18n` v9 docs: `prefix_except_default`, `useLocaleHead()`, `useLocalePath()` — HIGH confidence
+- Schema.org: `Service`, `SoftwareApplication`, `Person`, `WebSite` — HIGH confidence
+- `@nuxtjs/sitemap` v6: auto i18n integration — HIGH confidence (verified module is installed)
+- Pattern for `useJsonLd.ts` composable: derived from existing codebase conventions (composable-per-concern)
+- og:image static file strategy: MEDIUM confidence (sufficient for use case, no dynamic content needed)
diff --git a/.planning/research/FEATURES.md b/.planning/research/FEATURES.md
new file mode 100644
index 0000000..1605a39
--- /dev/null
+++ b/.planning/research/FEATURES.md
@@ -0,0 +1,368 @@
+# Feature Landscape
+
+**Domain:** Freelancer portfolio — niche game plugin developer (Hytale)
+**Researched:** 2026-04-10
+**Confidence:** MEDIUM — based on codebase analysis, domain knowledge, freelance market patterns; WebSearch unavailable
+
+---
+
+## 1. Freelancer Portfolio Pricing Pages — Visible vs Hidden
+
+### Verdict: Show pricing. Always.
+
+**Rationale for Killian's situation specifically:**
+
+The Hytale plugin dev market on Fiverr has ~1 direct competitor at $45. The market is not price-sensitive yet — it's trust-sensitive. A server owner searching "Hytale plugin developer" has no reference price. Showing prices:
+- Filters unserious inquiries before they consume calendar time (critical with only 5-10h/week availability)
+- Signals confidence and professionalism
+- Anchors expectations upward (a visible €300 tier makes a €100 tier feel reasonable)
+- Removes the "I need to ask" friction that kills conversions for international clients in different timezones
+
+**The only valid reason to hide pricing:** Custom enterprise work where scope varies by 10x. That does not apply here — plugin complexity is bounded.
+
+### Recommended Tier Structure
+
+Three tiers work best for plugin dev services. Four or more creates decision paralysis.
+
+| Tier | Name | Price Range | Contents |
+|------|------|-------------|----------|
+| Starter | Simple Plugin | €80–150 | Single feature, documented, delivered in 5 days, 15 days support |
+| Standard | Complex Plugin | €200–400 | Multiple systems (economy, progression, custom events), 30 days support, 1 revision round |
+| Premium | Full Experience | €500–900 | Full game loop (dungeon, boss, economy, UI), architecture doc, maintenance contract option |
+| Recurring | Maintenance | €30–60/mo | Compatibility updates per Hytale version, bug fixes, 1 minor feature/month |
+
+**Key structural decisions:**
+
+- Put the maintenance tier visually separate — it is a different product (recurring revenue vs one-shot)
+- "Starting at" language is fine for custom tier, but anchor with a concrete base price
+- Show what is explicitly NOT included (server hosting, assets/textures, art) — this prevents scope creep complaints
+- Add a "Most Popular" badge on Standard. It normalizes the mid tier and lifts average order value.
+
+**Nuxt UI v3 implementation:** Use `UCard` grid (3 columns desktop, 1 column mobile). The pricing tiers do not need a dedicated library — straight Tailwind + UCard is sufficient. Avoid installing a pricing-specific component library.
+
+---
+
+## 2. Hytale Plugin Services Page — What Server Owners Need to See
+
+### The buyer persona
+
+A Hytale server owner is typically:
+- Non-technical (they run a server, they don't code it)
+- Risk-averse (bad plugin = server downtime = player churn)
+- Skeptical ("can you even build Hytale plugins, the game just launched")
+- Looking for long-term relationship, not one-shot delivery
+
+They have Minecraft server experience and will compare to that ecosystem. Key questions in their head:
+
+1. Does this dev actually know Hytale specifically, or will they fake it?
+2. What happens when the next Hytale update breaks my plugin?
+3. Can I see examples or a demo?
+4. Will they be around in 6 months?
+
+### Page sections — recommended order
+
+**Section 1: Credibility header**
+- Title: "Hytale Plugin Developer" — not "Game Dev" or "Modder"
+- One-liner that addresses skepticism: "Building for Hytale since Early Access — I track every API change so your server stays running"
+- Availability badge (reuse the animated one from HeroSection)
+
+**Section 2: What makes Hytale plugins different**
+- Short educational paragraph (3-4 sentences) explaining the Hytale API vs Minecraft — this signals genuine knowledge
+- Mention: Hytale uses a Java/Kotlin API, the modding system is fundamentally different from Spigot/Paper, requires adapting to active API evolution
+- This signals to server owners that this developer is not a Minecraft dev pretending
+
+**Section 3: Services grid (the pricing section described above)**
+- Four cards: Simple, Complex, Full Experience, Maintenance
+- Each card must answer: What do I get? How long? What's the support situation?
+
+**Section 4: The maintenance pitch — this is the unique selling point**
+- Dedicated callout/alert component (UAlert or custom banner)
+- Message: Hytale updates frequently during Early Access. Every major update risks breaking plugins. A maintenance contract means zero downtime and no re-negotiation on every patch.
+- This is the structural advantage from PROJECT.md — lean into it hard
+
+**Section 5: Process (3-step)**
+- Step 1: Discovery call (Discord preferred — server owners are on Discord)
+- Step 2: Spec + quote in 48h
+- Step 3: Delivery with documentation
+- Keep this extremely short — server owners don't read walls of text
+
+**Section 6: Demo / Portfolio**
+- If no Hytale projects exist yet: use Minecraft plugin work as proof of concept + explicit note "Hytale API is similar to Java/Kotlin modding I've done for Minecraft — I'm actively building Hytale demos"
+- A "coming soon" placeholder is better than no section — it signals intent
+- Video embed or GIF of a plugin in action converts better than screenshots
+
+**Section 7: FAQ specific to Hytale**
+- "The game is in Early Access, is this risky?" — address directly
+- "What if Hytale updates break my plugin?" — maintenance contract answer
+- "Do you have experience with Hytale specifically?" — honest answer + Minecraft parallel
+- "Can I pay per update?" — redirect to maintenance tier
+
+**Section 8: CTA**
+- Primary: "Book a Discovery Call" (Discord link or contact form)
+- Secondary: "View Pricing"
+
+### Route: `/hytale` (not `/games` or `/modding`)
+
+The URL slug matters for SEO. `/hytale` captures "hytale plugin developer" searches directly. Register `hytale` in the nav alongside the existing pages.
+
+---
+
+## 3. Testimonials Section — Displaying 5–10 Reviews
+
+### Current state
+
+`testimonials.ts` has 5 real reviews, all 5-star, all from Fiverr. All French-language except one English ("awesome guy"). `testimonialsStats` declares 10 total reviews and 25 projects — slightly inflated vs actual data shown.
+
+### The small-count problem
+
+5 reviews is not a weakness if framed correctly. The mistake is showing 5 cards and letting the sparseness speak for itself. Solutions:
+
+**Pattern 1: Featured + Grid (recommended)**
+- 1 large "featured" testimonial card (the unqlf_ one — it's the most specific and includes project type "Plugin Minecraft")
+- 4 smaller cards below in 2x2 grid
+- This asymmetric layout fills the space and makes 5 cards look curated rather than scarce
+- The `featured: true` flag is already on the right testimonial in the data
+
+**Pattern 2: Carousel with autoplay**
+- Works for mobile; hides the count
+- Risk: autoplay is annoying and reduces trust
+- Not recommended
+
+**Pattern 3: Stats bar above cards**
+- "5.0 / 5.0 — 10+ verified reviews on Fiverr" + link to Fiverr profile
+- This shifts the authority to a third-party platform — more credible than displaying 5 internal cards
+- Add a Fiverr logo/icon next to the stat to reinforce the source
+- The `reviewsLink` already exists in i18n pointing to the Fiverr profile
+
+**Pattern 4: Language split — show the English one on the EN locale**
+- The "awesome guy" testimonial (botuhuh) is English and international — feature it prominently on the EN locale
+- French testimonials go first on FR locale
+- This can be implemented by sorting testimonials client-side by language match — simple logic in the component
+
+### Recommended implementation
+
+Use Pattern 1 + Pattern 3 combined:
+- Stats bar (5.0 rating, link to Fiverr) at top
+- Featured card (full-width or 60% width)
+- 4-card 2x2 grid
+- "See all reviews on Fiverr" CTA link at bottom
+
+For the Hytale page specifically, filter testimonials to show only `project_type === 'Plugin Minecraft'` — only 1 exists currently, but it's the most relevant. Pad with a "Review coming soon" placeholder card until more Hytale reviews accumulate.
+
+### What to fix in the data
+
+The `results` field is weak — values like `"Prix: Jusqu'à 50€"` and `"Durée: 10 jours"` reveal order size which may underposition the service. Consider removing the price from results display or changing it to outcome-focused language: "Delivered 2 days early", "Still using the plugin 6 months later".
+
+---
+
+## 4. Hero Section — Niche Positioning "Hytale Plugin Developer"
+
+### Current problem (confirmed by reading the code)
+
+The hero title uses `t('home.title')` which resolves to "Expert Full Stack Developer for Hire | Vue.js, React & Node.js Specialist" in EN. The code splits the last two words for gradient styling — this technique only works if the last two words are the differentiating concept (they're not: "Node.js Specialist" gets the gradient).
+
+Additionally, the terminal code block hardcodes `'Full Stack Dev'` as the role. The terminal does show `'Hytale Plugins'` in the skills array — good — but it is buried among 6 other skills.
+
+The availability badge says "Available for projects" — hardcoded English in the template (not using i18n key), which is a bug.
+
+### Hero best practices for niche positioning
+
+**Rule 1: Specialization in H1, not in paragraph**
+The H1 must state the specialization. Visitors scan H1, they don't read paragraphs. "Hytale Plugin Developer" must be in the H1, not in the subtitle or skills list.
+
+**Rule 2: Acknowledge the broader skill set in subtitle, not in title**
+The subtitle is the right place to mention Vue/Node/web work — it reassures server owners that this is a real professional developer, not a hobbyist.
+
+**Rule 3: Dual-audience heading (Hytale + Web)**
+Killian has two buyer types: Hytale server owners and web clients. The hero must serve the primary audience (Hytale — the strategic bet) without completely alienating web clients.
+
+Recommended approach: tabbed or split hero is overkill. Use a primary H1 that leads with Hytale, with a secondary descriptor:
+
+```
+Hytale Plugin Developer
+& Freelance Web Dev
+```
+
+The gradient goes on "Hytale Plugin Developer". Web services are the secondary line.
+
+**Rule 4: Specificity = trust**
+"I build custom Hytale plugins that survive every API update" beats "I build custom solutions that scale."
+
+**Rule 5: Terminal widget — update the role**
+Change `'Full Stack Dev'` to `'Hytale Plugin Dev'` in HeroSection.vue. This is a hardcoded string in the template (line 104), not using i18n, so fix it directly.
+
+### i18n changes required in hero
+
+The `home.title` split-by-last-2-words approach is fragile — it produces different results for FR and EN because sentence structure differs. The right solution:
+
+- Split `home.title` into two keys: `home.title.main` and `home.title.highlight`
+- `home.title.highlight` gets the gradient styling
+- This removes the brittle `split(' ').slice(-2)` logic
+
+New i18n values:
+
+```json
+// EN
+"home": {
+ "title": {
+ "main": "Hytale Plugin Developer",
+ "highlight": "& Freelance Web Dev"
+ },
+ "subtitle": "I build custom Hytale plugins that survive every API update — and web apps that convert. 7+ years of experience, 0 missed deadlines."
+}
+
+// FR
+"home": {
+ "title": {
+ "main": "Développeur de Plugins Hytale",
+ "highlight": "& Dev Web Freelance"
+ },
+ "subtitle": "Je construis des plugins Hytale qui survivent à chaque mise à jour de l'API — et des applications web qui convertissent. 7+ ans d'expérience, 0 délais manqués."
+}
+```
+
+The availability badge text ("Available for projects") is hardcoded in HeroSection.vue line 30 — needs to be an i18n key `home.availableBadge`.
+
+---
+
+## 5. i18n Audit — Finding Missing and Bad Translations
+
+### Issues already visible in the current files
+
+**Structural parity issues (EN has keys FR is missing or vice versa):**
+- Both files have identical key structure currently — no missing keys found at top level
+- Risk area: as new pages (Hytale) and features (pricing) are added, keys will diverge
+
+**Quality issues in existing translations:**
+
+EN quality problems:
+- `home.title` = "Expert Full Stack Developer for Hire | Vue.js, React & Node.js Specialist" — generic SEO-spam tone, not the niche positioning needed
+- `seo.home.title` still says "Freelance Full Stack Developer" — must change to include Hytale
+- `seo.home.description` makes no mention of Hytale, plugins, or game development
+- `a11y.logoLabel` = "Full Stack Developer" — must update when hero positioning changes
+- `footer.servicesList` contains "Mobile Apps" and "Tech Consulting" — neither is a real service offered
+- `fiverr.subtitle` claims "500+ orders delivered" and "100% satisfaction rate" — verify these are accurate; if not, this is a credibility risk
+
+FR quality problems:
+- `about.title` = "À propos de Killian'- Développeur Full Stack" — the dash is missing a space before it (`Killian'-` should be `Killian' —` or just remove)
+- `faq.homeFaq.delivery.answer` mentions "Bot Discord simple" as the first example — for a Hytale-focused portfolio this should lead with Hytale plugin timelines
+- `contact.methods.availability` = "Disponible pour remote & freelance" — the English word "remote" in French copy feels lazy; use "télétravail"
+
+Hardcoded strings (not using i18n at all):
+- HeroSection.vue line 30: `"Available for projects"` — hardcoded EN
+- HeroSection.vue line 104: `'Full Stack Dev'` — hardcoded in terminal widget
+- HeroSection.vue line 148: `"50+ projects"` — hardcoded EN
+- HeroSection.vue line 152: `"5.0 rating"` — hardcoded EN
+
+### Audit methodology for ongoing use
+
+**Method 1: Key extraction diff (best for structural parity)**
+
+```bash
+# Extract all keys from both files and diff
+node -e "
+ const en = require('./i18n/locales/en.json');
+ const fr = require('./i18n/locales/fr.json');
+ const flatten = (obj, prefix='') => Object.keys(obj).reduce((acc, k) => {
+ const key = prefix ? prefix + '.' + k : k;
+ return typeof obj[k] === 'object' && !Array.isArray(obj[k])
+ ? { ...acc, ...flatten(obj[k], key) }
+ : { ...acc, [key]: obj[k] };
+ }, {});
+ const enKeys = Object.keys(flatten(en));
+ const frKeys = Object.keys(flatten(fr));
+ const missingInFr = enKeys.filter(k => !frKeys.includes(k));
+ const missingInEn = frKeys.filter(k => !enKeys.includes(k));
+ console.log('Missing in FR:', missingInFr);
+ console.log('Missing in EN:', missingInEn);
+"
+```
+
+Run this after every feature addition that adds i18n keys.
+
+**Method 2: Search for hardcoded strings in templates**
+
+```bash
+# Find text content in templates that bypasses t()
+grep -rn '>[A-Z][a-z]' app/components/ app/pages/ | grep -v '{{' | grep -v 't(' | grep -v ':' | grep -v '