Files
kayjaydee e44175b9e4 chore: archive v1.1 milestone — SEO Hytale Autorité & Contenu shipped
M1.1 complete (phases 5-8, 13 plans):
- @nuxt/content v3 + Shiki syntax highlighting
- Blog listing + article pages SSR bilingue (TOC + prev/next)
- JSON-LD Article/Breadcrumb/CollectionPage + sitemap hreflang x-default
- 2 articles seed Hytale FR+EN (API Java réelle)
- Cocon sémantique /blog ↔ /hytale
2026-04-22 22:08:00 +02:00

102 lines
6.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Milestone v1.1: SEO Hytale — Autorité & Contenu
**Status:** ✅ SHIPPED 2026-04-22
**Phases:** 58
**Total Plans:** 13 (2 + 4 + 4 + 3)
## Overview
Construction d'un blog markdown bilingue complet (@nuxt/content v3) avec SEO de niveau production — JSON-LD Article/Breadcrumb/CollectionPage, sitemap dynamique avec hreflang x-default, og:image résolu par article — et cocon sémantique bidirectionnel entre `/blog` et `/hytale` via 2 articles seed Hytale.
## Phases
### Phase 5: @nuxt/content Setup & Renderer
**Goal:** Système de contenu markdown installé et rend fidèlement le contenu technique — blocs de code colorés, images optimisées, tables, alerts.
**Depends on:** Phase 4 (M1 complete)
**Requirements:** BLOG-01, BLOG-04, BLOG-05
**Plans:** 2 plans
- [x] 05-01: Installation @nuxt/content, configuration Shiki github-dark, content.config.ts collections bilingues
- [x] 05-02: Composants MDC (ProseImg, Alert, ProsePre, Columns, Details, Badge, Video, Clear), articles de test FR/EN
**Key decisions captured:** queryCollection avec littéraux seulement (pitfall Vite extractor), single-segment `[slug].vue` vs catch-all, Shiki single-theme, `i18n.baseUrl` requis pour useLocaleHead.
### Phase 6: Blog Pages
**Goal:** Un visiteur navigue /blog, parcourt la liste, ouvre un article, voit sa TOC et navigue prev/next — en SSR FR/EN.
**Depends on:** Phase 5
**Requirements:** BLOG-02, BLOG-03, BLOG-06
**Plans:** 4 plans
- [x] 06-01: Content schema Zod (draft/wordCount/minutes) + Nitro hook reading-time + draft:true test articles
- [x] 06-02: i18n keys blog.*/nav.blog/a11y.blog* + lien Blog AppHeader + BlogCard.vue (default + compact variants)
- [x] 06-03: Page listing app/pages/blog/index.vue (hero + grid + empty state, SSR bilingue)
- [x] 06-04: BlogToc.vue + BlogPrevNext.vue + enrichissement [slug].vue (breadcrumb + TOC + surround)
**Key decisions captured:** Hook `content:file:afterParse` exige `.optional()` sur schema Zod pour les champs injectés ; derivation slug via `article.path.split('/').pop()` ; cache `.nuxt` + `node_modules/.cache/content` à purger après changement schema.
### Phase 7: SEO Blog
**Goal:** Chaque page blog indexable avec meta tags complets, JSON-LD Article valide, URLs blog dans sitemap.
**Depends on:** Phase 6
**Requirements:** SEO-10, SEO-11, SEO-12, SEO-13, SEO-15
**Plans:** 4 plans
- [x] 07-01: Install nuxt-schema-org + schema `updated` + definePerson/defineWebSite global app.vue + sitemap.sources
- [x] 07-02: resolveOgImage helper + /og-blog-default.jpg + [slug].vue useSeoMeta D-15 + defineArticle/defineBreadcrumb
- [x] 07-03: index.vue useSeoMeta D-16 + defineWebPage(CollectionPage) + defineBreadcrumb
- [x] 07-04: server/api/__sitemap__/urls.ts — Nitro endpoint bilingue, draft filter, hreflang alternates x-default
**Key decisions captured:** `queryCollection` en Nitro prend `event` en premier argument (via `@nuxt/content/server` explicit import pour satisfaire vue-tsc) ; `definePerson` global avec @id=#killian réutilisé inline via `{'@id': '#killian'}` ; `articleAuthor` attend `string[]` ; cast local pour `inLanguage` union FR/EN.
### Phase 8: Content & Cocon Sémantique
**Goal:** 2 articles seed Hytale de qualité + section "Articles récents" sur /hytale + cocon sémantique bidirectionnel.
**Depends on:** Phase 7
**Requirements:** BLOG-07, SEO-14
**Plans:** 3 plans
- [x] 08-01: Scaffold HytaleRecentArticles.vue (queryCollection bilingue + filtre JS `tags.includes('hytale')` + limit 2 + v-if hide) + injection hytale.vue + i18n keys
- [x] 08-02: Article seed "How to build your first Hytale plugin" (FR 1209 / EN 1123 mots, Java/JavaPlugin, manifest.json, Gradle)
- [x] 08-03: Article seed "Hytale plugin development in 2026" (FR 1468 / EN 1335 mots, early access state, modern Java features)
**Key decisions captured:** Filtre JS post-query plutôt que SQL LIKE pour les tags JSON array ; liens `/hytale` hardcoded en markdown (pas de `localePath()` en MDC) ; slugs FR/EN identiques pour hreflang pairing. **Correction post-shipping :** articles initialement rédigés en Kotlin (placeholder), réécrits en Java après fetch hytalemodding.dev + britakee-studios GitBook pour refléter l'API réelle (`com.hypixel.hytale.plugin.JavaPlugin`, constructor `JavaPluginInit`, `manifest.json`, Gradle, Java 25).
---
## Milestone Summary
**Shipped features:**
- Blog markdown bilingue FR/EN avec @nuxt/content v3 + Shiki syntax highlighting
- Page listing `/blog` + page article `/blog/[slug]` SSR avec TOC + prev/next
- SEO complet par article : useSeoMeta enrichi (14 clés), JSON-LD Article + Breadcrumb + CollectionPage, og:image résolu
- Sitemap dynamique `/api/__sitemap__/urls` avec alternates hreflang fr/en/x-default, drafts filtrés
- 2 articles seed Hytale publiés (Java API réelle, 2 liens inline /hytale chacun)
- Section "Articles récents" sur `/hytale` (filtrée tag=hytale, v-if hide si vide)
- Cocon sémantique bidirectionnel blog ↔ hytale établi
**New dependencies added:** `@nuxt/content`, `nuxt-schema-org`
**Files created (top-level):**
- `app/components/BlogCard.vue`, `BlogToc.vue`, `BlogPrevNext.vue`, `HytaleRecentArticles.vue`
- `app/pages/blog/index.vue`, `app/pages/blog/[slug].vue`
- `app/utils/seo-person.ts`, `resolve-og-image.ts`
- `server/api/__sitemap__/urls.ts`
- `server/plugins/reading-time.ts`
- `content/fr/blog/` + `content/en/blog/` (4 seed articles)
- `content.config.ts` (schemas Zod bilingues)
**Requirements coverage:** 13/13 — BLOG-01..07, SEO-10..15 tous satisfaits.
**Git range:** 31 commits sur les phases 05-08.
**Notable learnings:**
- Nuxt 4 + @nuxt/content + @nuxtjs/i18n : single-segment `[slug].vue` obligatoire (catch-all casse en strategy `prefix`)
- `queryCollection` dans Nitro nécessite `event` first-arg + import explicite depuis `@nuxt/content/server` pour vue-tsc
- Schema Zod `.optional()` requis pour que les champs injectés par Nitro hook `content:file:afterParse` soient queryables
- Recherche API tierce avant rédaction tutoriel : Kotlin assumé pour Hytale → en réalité Java (correction post-shipping documentée)
**Archive date:** 2026-04-22
**Full phase artifacts:** `.planning/phases/05-*` through `.planning/phases/08-*` (preserved)