6.1 KiB
6.1 KiB
phase, plan, subsystem, tags, requirements, requires, provides, affects, tech-stack, key-files, decisions, metrics
| phase | plan | subsystem | tags | requirements | requires | provides | affects | tech-stack | key-files | decisions | metrics | ||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 08-content-cocon-semantique | 01 | content/ui |
|
|
|
|
|
|
|
|
|
Phase 8 Plan 01: Scaffold HytaleRecentArticles — Summary
Scaffolding du cocon semantique cote /hytale : composant HytaleRecentArticles.vue (queryCollection bilingue + filtre JS tag hytale + limit 2), injection dans /hytale, cles i18n FR/EN. Section degrade gracieusement (v-if) tant que 0 article publie, permettant de shipper Wave 1 sans rompre /hytale.
Changes
Task 1 — HytaleRecentArticles.vue (commit ddfc685)
Nouveau composant app/components/HytaleRecentArticles.vue (72 lignes, auto-importe) :
- Script : branches litterales
queryCollection('blog_fr')/queryCollection('blog_en')sur ternaireisFr.value(Phase 5 Pitfall D-03), keyhytale-recent-${locale.value}+watch: [locale], chaine.where('draft','=',false).order('date','DESC').all(). - Filtre JS :
articles = computed(() => all.filter(a => Array.isArray(a.tags) && a.tags.includes('hytale')).slice(0, 2))— guard Array.isArray contre TypeError (T-08-01), filtre JS car LIKE SQLite unreliable sur tags[] (D-11). - Template :
<section v-if="articles.length">(masque total si vide, D-12), header// recent-articles+ h2text-3xl sm:text-4xl+ subtitle, grillegrid-cols-1 md:grid-cols-2 gap-5 lg:gap-6,<BlogCard variant="compact">v-for, footer NuxtLinklocalePath('/blog')avec icon arrow-right.
Task 2 — Injection + i18n (commit bf2ec86)
app/pages/hytale.vue:<HytaleRecentArticles />insere apres le wrapper TestimonialsSection, avant fermeture root div. Aucun script change (auto-import Nuxt).i18n/locales/fr.json: nouveau blochytale.recentArticlessibling dehero/services/pricingavec title "Articles récents", subtitle "Les dernières publications sur le développement de plugins Hytale", viewAll "Voir tous les articles" (style accentue aligneblog.*2026).i18n/locales/en.json: miroir EN "Recent articles" / "Latest writing on Hytale plugin development" / "View all articles".
Verification
pnpm typecheckexit 0 (deux passes, apres chaque tache)node -e "JSON.parse(...)"FR + EN OK (pas de trailing comma ni syntax error)grep "queryCollection\\('blog_(fr|en)'\\)"→ 2 branches litterales presentesgrep "v-if=\"articles.length\""→ presentgrep "variant=\"compact\""→ presentgrep "tags.*includes.*'hytale'"→ filtre JS presentgrep "<HytaleRecentArticles"dans hytale.vue → present ligne 38grep "\"recentArticles\""dans fr.json + en.json → ligne 556 sur les deux- Curl SSR reporte en Wave 2 (articles pas encore publies → section absente du HTML, comportement attendu D-12)
Deviations from Plan
None — plan executed exactly as written. Le filtre JS etait prevu par le plan (D-11), aucune surprise. Les cles i18n en style accentue respectent la recommandation PATTERNS.md.
Decisions Made
- Filtre JS tags (D-11 applied) :
Array.isArray(a.tags) && a.tags.includes('hytale')au lieu de.where('tags', 'LIKE', ...)SQL. Raison : LIKE sur champ JSON-array SQLite non fiable ; guard Array.isArray = mitigation T-08-01 threat register. - Style i18n accentue : coherence avec bloc
blog.*Phase 6-02 (convention 2026). Le blochytale.*legacy ASCII reste pour retrocompatibilite ; les nouvelles cles adoptent la convention actuelle. - Position d'injection : derniere position du root div, apres le wrapper
bg-gray-50/50des Testimonials, conforme CONTEXT D-10 "en bas de page, avant footer-CTA existant" (footer-CTA vit dans AppFooter layout, hors page). - Pas de prop
directionsur BlogCard : variant compact accepte default 'next' (icon arrow-right), coherent avec le CTA viewAll aussi en arrow-right. Pas de semantique prev/next dans ce contexte de listing.
Threat Flags
Aucune nouvelle surface de menace introduite hors du threat model du plan. Les 3 threats (T-08-01 tampering frontmatter, T-08-02 draft leak, T-08-03 DoS) sont tous mitigees comme prevu :
- T-08-01 →
Array.isArray(a.tags)guard avant.includes() - T-08-02 →
.where('draft', '=', false)filtre SQL obligatoire - T-08-03 → accept (volume d'articles < 100 attendu)
Follow-ups (Wave 2)
- Publier les 2 articles seed (how-to-build-your-first-hytale-plugin + hytale-plugin-development-2026) en FR+EN avec
draft: false+ taghytale - Curl
/hytale+/en/hytalepour valider apparition de la section avec les 2 slugs (conforme must_have truth #1)
Self-Check: PASSED
app/components/HytaleRecentArticles.vueexistsapp/pages/hytale.vuecontains<HytaleRecentArticlesi18n/locales/fr.jsoncontains"recentArticles"block with 3 keysi18n/locales/en.jsoncontains"recentArticles"block with 3 keys- Commit
ddfc685found ingit log - Commit
bf2ec86found ingit log pnpm typecheckexit 0