docs(08): create phase plan — content & cocon sémantique (3 plans, 2 waves)
- 08-01 (W1): HytaleRecentArticles.vue scaffold + injection hytale.vue + i18n - 08-02 (W2): article tutorial how-to-build-your-first-hytale-plugin FR+EN - 08-03 (W2): article positionnement hytale-plugin-development-2026 FR+EN Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,312 @@
|
||||
---
|
||||
phase: 08-content-cocon-semantique
|
||||
plan: 02
|
||||
type: execute
|
||||
wave: 2
|
||||
depends_on: ["08-01"]
|
||||
files_modified:
|
||||
- content/fr/blog/how-to-build-your-first-hytale-plugin.md
|
||||
- content/en/blog/how-to-build-your-first-hytale-plugin.md
|
||||
autonomous: true
|
||||
requirements: [BLOG-07, SEO-14]
|
||||
tags: [content, blog, hytale, tutorial, kotlin]
|
||||
|
||||
must_haves:
|
||||
truths:
|
||||
- "Article 'how-to-build-your-first-hytale-plugin' publié (draft: false) en FR et EN avec le même slug"
|
||||
- "Chaque version contient au moins 1 bloc code Kotlin réaliste (event listener ou command handler)"
|
||||
- "Version FR contient au moins 1 lien markdown inline vers /hytale ; version EN vers /en/hytale"
|
||||
- "Frontmatter Zod-valide : title/description localisés, date ISO, tags incluent 'hytale', draft: false"
|
||||
- "Article apparaît dans /blog (FR) et /en/blog (EN) en listing"
|
||||
artifacts:
|
||||
- path: "content/fr/blog/how-to-build-your-first-hytale-plugin.md"
|
||||
provides: "Article FR complet (800-1500 mots) — tutorial débutant plugin Hytale"
|
||||
contains: "draft: false"
|
||||
- path: "content/en/blog/how-to-build-your-first-hytale-plugin.md"
|
||||
provides: "Article EN équivalent, même slug"
|
||||
contains: "draft: false"
|
||||
key_links:
|
||||
- from: "content/fr/blog/how-to-build-your-first-hytale-plugin.md"
|
||||
to: "/hytale (page service)"
|
||||
via: "lien markdown inline `[texte](/hytale)`"
|
||||
pattern: "\\]\\(/hytale\\)"
|
||||
- from: "content/en/blog/how-to-build-your-first-hytale-plugin.md"
|
||||
to: "/en/hytale"
|
||||
via: "lien markdown inline `[text](/en/hytale)`"
|
||||
pattern: "\\]\\(/en/hytale\\)"
|
||||
- from: "Sitemap Nitro endpoint (Phase 7-04)"
|
||||
to: "URL /blog/how-to-build-your-first-hytale-plugin avec hreflang FR+EN"
|
||||
via: "Auto-découverte via queryCollection (déjà live)"
|
||||
pattern: "how-to-build-your-first-hytale-plugin"
|
||||
---
|
||||
|
||||
<objective>
|
||||
Publier l'article seed 1 "How to build your first Hytale plugin" en FR et EN. Tutorial débutant, 800-1500 mots, bloc code Kotlin réaliste, 1-2 liens inline vers la page `/hytale` (commission service). Ne nécessite aucune modif code applicatif — markdown pur + frontmatter Zod.
|
||||
|
||||
Purpose: Premier article du cocon sémantique. Anchor text SEO-friendly "commissioner un plugin Hytale" / "commission a Hytale plugin" renvoyant vers l'offre service. Intent transactionnel-info.
|
||||
|
||||
Output: 2 fichiers markdown (FR + EN), même slug, tags `['hytale', 'tutorial', 'kotlin']`, publiés (draft: false).
|
||||
</objective>
|
||||
|
||||
<execution_context>
|
||||
@$HOME/.claude/get-shit-done/workflows/execute-plan.md
|
||||
@$HOME/.claude/get-shit-done/templates/summary.md
|
||||
</execution_context>
|
||||
|
||||
<context>
|
||||
@.planning/PROJECT.md
|
||||
@.planning/ROADMAP.md
|
||||
@.planning/phases/08-content-cocon-semantique/08-CONTEXT.md
|
||||
@.planning/phases/08-content-cocon-semantique/08-PATTERNS.md
|
||||
@.planning/phases/05-nuxt-content-setup-renderer/05-CONTEXT.md
|
||||
@content/fr/blog/test-kotlin-syntax.md
|
||||
</context>
|
||||
|
||||
<editorial_brief>
|
||||
|
||||
**Slug (D-01, D-03) :** `how-to-build-your-first-hytale-plugin` — identique FR+EN.
|
||||
|
||||
**Titre FR :** "Créer son premier plugin Hytale : guide pas à pas"
|
||||
**Titre EN :** "How to build your first Hytale plugin: a step-by-step guide"
|
||||
|
||||
**Description FR :** "Apprends à coder ton premier plugin Hytale en Kotlin : setup, event listener, et commande custom — avec le code source complet."
|
||||
**Description EN :** "Learn to build your first Hytale plugin in Kotlin: project setup, event listener, custom command — with the complete source code."
|
||||
|
||||
**Tags :** `["hytale", "tutorial", "kotlin"]`
|
||||
**Date :** `"2026-04-22"`
|
||||
**Draft :** `false`
|
||||
**Image :** champ omis (fallback `/og-blog-default.jpg` Phase 7 D-05 s'applique automatiquement).
|
||||
**Champ `updated` :** omis (D-06).
|
||||
|
||||
**Ton (D-07) :** première personne ("je", "I"), technique mais accessible, concret. Voix Killian dev 7 ans, pas corporate. Éviter jargon non-expliqué. Inclure anecdotes pratiques ("la première fois que j'ai lancé...").
|
||||
|
||||
**Longueur cible :** 1000-1300 mots par version.
|
||||
|
||||
**Outline recommandé (6-8 sections, ~200 mots chacune) :**
|
||||
|
||||
1. **Intro — pourquoi Hytale, pourquoi maintenant** (~150 mots)
|
||||
- Le contexte : Hytale API en 2026, public indie + serveurs custom, opportunité dev.
|
||||
- Ce qu'on va construire : un plugin de base qui écoute un event et ajoute une commande.
|
||||
- **Placement naturel du 1er lien `/hytale`** : "Si tu préfères faire [commissioner un plugin Hytale](/hytale) plutôt que le coder toi-même, c'est une option." (FR) / "If you'd rather [commission a Hytale plugin](/en/hytale) instead of coding it yourself, that works too." (EN)
|
||||
|
||||
2. **Prérequis** (~100 mots)
|
||||
- JDK 17+ (ou version actuelle Hytale SDK 2026), IntelliJ IDEA Community, Gradle, connaissances Kotlin basiques.
|
||||
- Fichier `build.gradle.kts` minimal (snippet court optionnel).
|
||||
|
||||
3. **Scaffold du projet** (~200 mots)
|
||||
- Arborescence `src/main/kotlin/com/example/myplugin/MyPlugin.kt`.
|
||||
- `plugin.yml` / `plugin.toml` (selon convention Hytale 2026).
|
||||
- Petit exemple de manifest.
|
||||
|
||||
4. **Premier event listener — le cœur du plugin** (~250 mots) — **BLOC CODE KOTLIN OBLIGATOIRE ici** :
|
||||
```kotlin
|
||||
package com.example.myplugin
|
||||
|
||||
import io.hytale.api.HytalePlugin
|
||||
import io.hytale.api.event.EventHandler
|
||||
import io.hytale.api.event.player.PlayerJoinEvent
|
||||
|
||||
class MyPlugin : HytalePlugin() {
|
||||
override fun onEnable() {
|
||||
logger.info("MyPlugin enabled")
|
||||
server.events.register(this)
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
fun onPlayerJoin(event: PlayerJoinEvent) {
|
||||
event.player.sendMessage("Welcome, ${event.player.name}!")
|
||||
}
|
||||
}
|
||||
```
|
||||
- Explication ligne par ligne : `onEnable`, registration, annotation handler, accès `event.player`.
|
||||
- Note : l'API exacte 2026 peut varier — préciser "exemple conforme au SDK public 2026, adapter selon la doc officielle au moment de la lecture".
|
||||
|
||||
5. **Ajouter une commande custom** (~200 mots) — 2e bloc code court :
|
||||
```kotlin
|
||||
@Command("hello")
|
||||
fun onHelloCommand(sender: CommandSender, args: List<String>) {
|
||||
sender.sendMessage("Hello from MyPlugin!")
|
||||
}
|
||||
```
|
||||
- Où placer dans la classe, comment tester en jeu.
|
||||
|
||||
6. **Build + deploy local** (~150 mots)
|
||||
- `./gradlew build`
|
||||
- Copier le JAR dans `plugins/`, lancer le serveur.
|
||||
- **Placement naturel du 2e lien `/hytale`** (optionnel, 1 suffit) : "Si tu veux déployer un plugin plus ambitieux et que tu préfères déléguer, tu peux [commissioner un plugin Hytale sur-mesure](/hytale)." (FR)
|
||||
|
||||
7. **Prochaines étapes** (~150 mots)
|
||||
- Suggestions : écouter d'autres events, persister des données, optimiser perf.
|
||||
- Liens externes vers doc Hytale (ne PAS ajouter en Wave 2 — Claude peut si source connue, sinon omettre).
|
||||
|
||||
8. **Conclusion** (~100 mots)
|
||||
- Résumé, encouragement.
|
||||
|
||||
**Liens internes — règle absolue (D-08, D-09) :**
|
||||
- Version **FR** : **au moins 1** lien markdown `](/hytale)` inline dans la prose. Anchor text en français naturel. Idéalement 2 liens (intro + build section).
|
||||
- Version **EN** : **au moins 1** lien markdown `](/en/hytale)` inline. Anchor text en anglais naturel. Path commence par `/en/` (préfixe i18n explicite).
|
||||
- **NE PAS** utiliser `localePath()` ou `<NuxtLink>` en markdown — hardcode des paths.
|
||||
|
||||
**Bloc code Kotlin (D-05) :** au moins 1 bloc ```kotlin réaliste (pas pseudo-code — signatures API, imports cohérents). L'exemple onPlayerJoin ci-dessus satisfait l'exigence minimale. Un 2e bloc (commande) est bonus.
|
||||
|
||||
**Frontmatter exact FR :**
|
||||
```yaml
|
||||
---
|
||||
title: "Créer son premier plugin Hytale : guide pas à pas"
|
||||
description: "Apprends à coder ton premier plugin Hytale en Kotlin : setup, event listener, et commande custom — avec le code source complet."
|
||||
date: "2026-04-22"
|
||||
tags: ["hytale", "tutorial", "kotlin"]
|
||||
draft: false
|
||||
---
|
||||
```
|
||||
|
||||
**Frontmatter exact EN :**
|
||||
```yaml
|
||||
---
|
||||
title: "How to build your first Hytale plugin: a step-by-step guide"
|
||||
description: "Learn to build your first Hytale plugin in Kotlin: project setup, event listener, custom command — with the complete source code."
|
||||
date: "2026-04-22"
|
||||
tags: ["hytale", "tutorial", "kotlin"]
|
||||
draft: false
|
||||
---
|
||||
```
|
||||
|
||||
</editorial_brief>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 1: Rédiger version FR de l'article tutorial</name>
|
||||
<files>content/fr/blog/how-to-build-your-first-hytale-plugin.md</files>
|
||||
<read_first>
|
||||
- content/fr/blog/test-kotlin-syntax.md (pattern frontmatter + code block + callouts MDC)
|
||||
- .planning/phases/08-content-cocon-semantique/08-CONTEXT.md §D-01, D-04, D-05, D-06, D-07, D-08
|
||||
- .planning/phases/08-content-cocon-semantique/08-PATTERNS.md §"content/{fr,en}/blog/..."
|
||||
- Section `<editorial_brief>` ci-dessus (outline complet)
|
||||
</read_first>
|
||||
<action>
|
||||
Créer `content/fr/blog/how-to-build-your-first-hytale-plugin.md`.
|
||||
|
||||
**Frontmatter exact** (copier depuis `<editorial_brief>`) — `draft: false`, tags `["hytale", "tutorial", "kotlin"]`, date `"2026-04-22"`, pas de champ `image`, pas de champ `updated`.
|
||||
|
||||
**Corps de l'article** : suivre l'outline 8 sections du brief éditorial, ton première personne (je/moi/mon), concret, 1000-1300 mots.
|
||||
|
||||
**Exigences dures non-négociables :**
|
||||
1. Au moins 1 bloc ```kotlin avec imports + classe + event handler (réaliste, pas pseudo-code). Voir exemple exact dans le brief §section 4. Un 2e bloc court pour la commande est recommandé.
|
||||
2. Au moins 1 lien markdown inline `](/hytale)` — path en dur, pas `localePath()`. Anchor text français naturel, ex: "[commissioner un plugin Hytale sur-mesure](/hytale)". Idéalement 2 occurrences (intro + build section).
|
||||
3. Pas de champ `image:` au frontmatter. Pas de champ `updated`.
|
||||
4. Respect strict du schema Zod blog_fr (Phase 5) : les champs non déclarés sont strippés — ne pas inventer.
|
||||
|
||||
**Interdits :**
|
||||
- Pseudo-code Kotlin (doit compiler conceptuellement).
|
||||
- `<NuxtLink>` ou `localePath()` dans le markdown.
|
||||
- Liens absolus `https://killiandalcin.fr/hytale` — utiliser path relatif `/hytale`.
|
||||
- Contenu AI-slop générique ("dans ce guide, nous allons explorer...") — voix Killian concrète.
|
||||
|
||||
**Style Markdown :**
|
||||
- Titres `##` pour les 8 sections (pas de `#` qui est réservé au title frontmatter).
|
||||
- Code inline avec backticks pour noms de classes/méthodes.
|
||||
- Callouts `::alert{type="tip"}` ou `::alert{type="info"}` optionnels si pertinent (pattern Phase 5 MDC).
|
||||
</action>
|
||||
<verify>
|
||||
<automated>pnpm typecheck</automated>
|
||||
</verify>
|
||||
<done>
|
||||
- Fichier existe : `test -f content/fr/blog/how-to-build-your-first-hytale-plugin.md`
|
||||
- `grep "draft: false" content/fr/blog/how-to-build-your-first-hytale-plugin.md` passe
|
||||
- `grep -E "tags:.*hytale" content/fr/blog/how-to-build-your-first-hytale-plugin.md` passe (ou check YAML array form)
|
||||
- `grep -c '\](/hytale)' content/fr/blog/how-to-build-your-first-hytale-plugin.md` ≥ 1
|
||||
- `grep -c '```kotlin' content/fr/blog/how-to-build-your-first-hytale-plugin.md` ≥ 1
|
||||
- Mots ≥ 800 : `wc -w content/fr/blog/how-to-build-your-first-hytale-plugin.md` ≥ 800
|
||||
- `pnpm typecheck` exit 0 (validation Zod schema blog_fr passe)
|
||||
</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 2: Rédiger version EN de l'article tutorial (même slug, contenu équivalent)</name>
|
||||
<files>content/en/blog/how-to-build-your-first-hytale-plugin.md</files>
|
||||
<read_first>
|
||||
- content/fr/blog/how-to-build-your-first-hytale-plugin.md (juste créé par Task 1 — référence directe pour équivalence)
|
||||
- content/en/blog/test-kotlin-syntax.md (pattern frontmatter EN)
|
||||
- .planning/phases/08-content-cocon-semantique/08-CONTEXT.md §D-03, D-08, D-09
|
||||
</read_first>
|
||||
<action>
|
||||
Créer `content/en/blog/how-to-build-your-first-hytale-plugin.md` — **même slug** que la version FR, contenu équivalent traduit (pas une simple traduction automatique : adapter idiomes, garder la voix naturelle en anglais).
|
||||
|
||||
**Frontmatter exact** :
|
||||
```yaml
|
||||
---
|
||||
title: "How to build your first Hytale plugin: a step-by-step guide"
|
||||
description: "Learn to build your first Hytale plugin in Kotlin: project setup, event listener, custom command — with the complete source code."
|
||||
date: "2026-04-22"
|
||||
tags: ["hytale", "tutorial", "kotlin"]
|
||||
draft: false
|
||||
---
|
||||
```
|
||||
|
||||
**Corps :** équivalent à la version FR (mêmes 8 sections, même outline, même blocs code Kotlin identiques — les commentaires code peuvent rester en anglais dans les deux versions).
|
||||
|
||||
**Règle critique liens internes (D-09) :**
|
||||
- Version EN : lien vers **`/en/hytale`** (préfixe explicite), PAS `/hytale`. Exemple : `[commission a Hytale plugin](/en/hytale)`.
|
||||
- Au moins 1 occurrence `](/en/hytale)` — idéalement 2.
|
||||
- Path en dur dans le markdown. Pas de `localePath()`.
|
||||
|
||||
**Longueur :** 1000-1300 mots. Voix première personne ("I", "my first plugin"), ton technique accessible.
|
||||
|
||||
**Blocs code :** mêmes snippets Kotlin que la version FR (les imports et signatures API n'ont pas à être traduits). Les explications textuelles autour doivent être en anglais.
|
||||
|
||||
**Interdits identiques à Task 1.**
|
||||
</action>
|
||||
<verify>
|
||||
<automated>pnpm typecheck</automated>
|
||||
</verify>
|
||||
<done>
|
||||
- Fichier existe
|
||||
- `grep "draft: false" content/en/blog/how-to-build-your-first-hytale-plugin.md` passe
|
||||
- `grep -E "tags:.*hytale" content/en/blog/how-to-build-your-first-hytale-plugin.md` passe
|
||||
- `grep -c '\](/en/hytale)' content/en/blog/how-to-build-your-first-hytale-plugin.md` ≥ 1
|
||||
- `grep -c '```kotlin' content/en/blog/how-to-build-your-first-hytale-plugin.md` ≥ 1
|
||||
- Mots ≥ 800
|
||||
- `pnpm typecheck` exit 0
|
||||
- Run `pnpm dev` puis `curl http://localhost:3000/blog/how-to-build-your-first-hytale-plugin` → 200 + HTML contient titre FR
|
||||
- `curl http://localhost:3000/en/blog/how-to-build-your-first-hytale-plugin` → 200 + HTML contient titre EN
|
||||
- `curl http://localhost:3000/hytale` → HTML contient section "Articles récents" + lien vers le slug (l'article Plan 08-01 est maintenant alimenté)
|
||||
</done>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<threat_model>
|
||||
## Trust Boundaries
|
||||
|
||||
| Boundary | Description |
|
||||
|----------|-------------|
|
||||
| markdown author → Zod schema → SSR | Contenu statique rédigé par dev, Zod-validé Phase 5, aucun user input |
|
||||
|
||||
## STRIDE Threat Register
|
||||
|
||||
| Threat ID | Category | Component | Disposition | Mitigation Plan |
|
||||
|-----------|----------|-----------|-------------|-----------------|
|
||||
| T-08-04 | T (Tampering) | frontmatter YAML | mitigate | Schema Zod blog_fr/blog_en strip les champs inconnus, typecheck rattrape les erreurs |
|
||||
| T-08-05 | I (Info Disclosure) | lien inline | accept | Les paths `/hytale` / `/en/hytale` sont publics, pas de leak |
|
||||
| T-08-06 | S (Spoofing) | auteur article | accept | Pas de champ `author` user-controlled — author implicite Killian via schema.org Phase 7 |
|
||||
</threat_model>
|
||||
|
||||
<verification>
|
||||
- Les 2 articles passent le typecheck (Zod schema validation au build time)
|
||||
- `curl /blog` contient le slug en FR, `curl /en/blog` en EN
|
||||
- `grep '](/hytale)'` sur FR ≥ 1, `grep '](/en/hytale)'` sur EN ≥ 1
|
||||
- Sitemap : `curl /sitemap.xml | grep how-to-build-your-first-hytale-plugin` retourne au moins 2 occurrences (FR + EN avec hreflang alternates automatiques Phase 7-04)
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
- 2 articles `.md` publiés (draft: false), mêmes slugs, frontmatter Zod-valide
|
||||
- Cocon sémantique : chaque article a ≥1 lien vers `/hytale` (locale-aware, paths en dur)
|
||||
- Bloc code Kotlin réaliste (pas pseudo-code) dans chaque version
|
||||
- Minimum 800 mots par version, cible 1000-1300
|
||||
- Section "Articles récents" sur /hytale (livrée Plan 08-01) affiche cet article après deploy
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
Après complétion, créer `.planning/phases/08-content-cocon-semantique/08-02-SUMMARY.md`.
|
||||
</output>
|
||||
Reference in New Issue
Block a user