diff --git a/.planning/phases/08-content-cocon-semantique/08-PATTERNS.md b/.planning/phases/08-content-cocon-semantique/08-PATTERNS.md
new file mode 100644
index 0000000..2136c08
--- /dev/null
+++ b/.planning/phases/08-content-cocon-semantique/08-PATTERNS.md
@@ -0,0 +1,240 @@
+# Phase 8: Content & Cocon Sémantique — Pattern Map
+
+**Mapped:** 2026-04-22
+**Files analyzed:** 7 (6 new + 1 modified) plus 2 locale files modified
+**Analogs found:** 7 / 7
+
+## File Classification
+
+| New/Modified File | Role | Data Flow | Closest Analog | Match Quality |
+|-------------------|------|-----------|----------------|---------------|
+| `content/fr/blog/how-to-build-your-first-hytale-plugin.md` | content (markdown article) | file-I/O (static content) | `content/fr/blog/test-kotlin-syntax.md` | exact |
+| `content/en/blog/how-to-build-your-first-hytale-plugin.md` | content (markdown article) | file-I/O (static content) | `content/en/blog/test-kotlin-syntax.md` | exact |
+| `content/fr/blog/hytale-plugin-development-2026.md` | content (markdown article) | file-I/O (static content) | `content/fr/blog/test-kotlin-syntax.md` | exact |
+| `content/en/blog/hytale-plugin-development-2026.md` | content (markdown article) | file-I/O (static content) | `content/en/blog/test-kotlin-syntax.md` | exact |
+| `app/components/HytaleRecentArticles.vue` | component (section) | request-response (queryCollection SSR) | `app/pages/blog/index.vue` | role-match (page→component) |
+| `app/pages/hytale.vue` | page (composition) | request-response | current state (self) | exact |
+| `i18n/locales/fr.json` + `en.json` | config (i18n) | static | existing `hytale.*` + `blog.*` blocks | exact |
+
+**Note path correction:** CONTEXT mentions `app/locales/` but actual path is `i18n/locales/` (confirmed via Glob). Planner should use `i18n/locales/fr.json` and `i18n/locales/en.json`.
+
+**Note page path correction:** CONTEXT mentions `app/pages/hytale/index.vue`. Actual page is `app/pages/hytale.vue` (flat, 39 lines). No directory routing.
+
+## Pattern Assignments
+
+### `content/{fr,en}/blog/how-to-build-your-first-hytale-plugin.md` (content, file-I/O)
+
+**Analog:** `content/fr/blog/test-kotlin-syntax.md` (FR) and `content/en/blog/test-kotlin-syntax.md` (EN)
+
+**Frontmatter pattern** (lines 1-7 of analog) — adapt for Phase 8 (`draft: false`, tags include `hytale`):
+```markdown
+---
+title: "Guide du format Markdown"
+description: "Référence complète de tous les éléments et composants disponibles dans les articles"
+date: "2026-04-21"
+tags: ["guide", "markdown", "mdc"]
+draft: true
+---
+```
+
+**Required changes for Phase 8 articles (per CONTEXT D-06):**
+- `draft: false` (CONTEXT D-04)
+- `tags: ['hytale', 'tutorial', 'kotlin']` (article 1) or `['hytale', 'industry', 'analysis']` (article 2) — tag `hytale` MANDATORY (D-11, D-15)
+- `date: "2026-04-22"` (ISO)
+- Omit `updated` field at initial publish (D-06)
+- `image:` optional — if present must point to existing asset in `public/` (D-05, Phase 7 D-14)
+
+**Kotlin code block pattern** (lines 25-33 of analog):
+```markdown
+\`\`\`kotlin
+fun createPlugin(name: String): HytalePlugin {
+ return HytalePlugin.builder()
+ .name(name)
+ .version("1.0.0")
+ .onLoad { println("Plugin $name loaded!") }
+ .build()
+}
+\`\`\`
+```
+
+Every seed article MUST include ≥1 realistic Kotlin block (not pseudo-code) per D-05.
+
+**Internal link pattern (D-08, D-09):** In FR article, inline markdown link uses `/hytale`. In EN article, uses `/en/hytale`:
+```markdown
+Pour un plugin sur-mesure, vous pouvez [commissionner un plugin Hytale](/hytale) directement.
+```
+```markdown
+For a custom plugin, you can [commission a Hytale plugin](/en/hytale) directly.
+```
+Hard-code paths (D-09); do NOT use `localePath()` in markdown. Minimum 1–2 inline links per article.
+
+**Callout pattern available (optional):**
+```markdown
+::alert{type="tip"}
+**Astuce** — Utilisez `pnpm` plutôt que `npm` pour les projets Nuxt.
+::
+```
+
+---
+
+### `app/components/HytaleRecentArticles.vue` (component, request-response)
+
+**Analog:** `app/pages/blog/index.vue` — same `queryCollection` bilingual branch pattern, slimmed to section-level component.
+
+**queryCollection bilingual pattern** (lines 2-21 of analog) — the critical Phase 5 Pitfall-safe pattern:
+```typescript
+const { t, locale } = useI18n()
+const localePath = useLocalePath()
+const isFr = computed(() => locale.value === 'fr')
+
+const { data: articles } = await useAsyncData(
+ `blog-list-${locale.value}`,
+ () =>
+ isFr.value
+ ? queryCollection('blog_fr')
+ .where('draft', '=', false)
+ .order('date', 'DESC')
+ .all()
+ : queryCollection('blog_en')
+ .where('draft', '=', false)
+ .order('date', 'DESC')
+ .all(),
+ { watch: [locale] },
+)
+```
+
+**Adaptation for HytaleRecentArticles:**
+- Key: `hytale-recent-${locale.value}` (per CONTEXT "Reusable Assets")
+- Add tag filter: either `.where('tags', 'LIKE', '%hytale%')` SQL OR JS post-filter `article.tags?.includes('hytale')` (CONTEXT D-11 — planner decides).
+- Add `.limit(2)` (D-11).
+- Branches must be LITERAL strings `'blog_fr'` / `'blog_en'` — never `queryCollection(variableName)` (Phase 5 D-03 Pitfall).
+
+**Conditional render + grid pattern** (lines 141-151 of analog) adapted for compact variant + 2-col grid:
+```vue
+{{ t('hytale.recentArticles.title') }}
+