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
kayjaydee
37b87b4b54
docs(08): capture API correction — Kotlin→Java rewrite based on hytalemodding.dev
2026-04-22 22:03:44 +02:00
kayjaydee
a4fd4e78d2
refactor(08-03): rewrite EN article with real Hytale Java API
2026-04-22 22:02:59 +02:00
kayjaydee
eb3553753a
refactor(08-03): rewrite FR article with real Hytale Java API
2026-04-22 22:01:56 +02:00
kayjaydee
fc7392ee1a
refactor(08-02): rewrite EN article with real Hytale Java API
2026-04-22 22:00:42 +02:00
kayjaydee
1d30828a6f
refactor(08-02): rewrite FR article with real Hytale Java API
2026-04-22 22:00:37 +02:00
kayjaydee
b8ddd8e14e
docs(08): mark Phase 8 complete — M1.1 milestone shipped .planning/ROADMAP.md .planning/phases/08-content-cocon-semantique/08-VERIFICATION.md
2026-04-22 21:55:24 +02:00
kayjaydee
6eb81b1f5b
docs(08-03): article seed 2 positionnement Hytale 2026 SUMMARY
...
- 2 articles markdown FR+EN (même slug) 1148/1009 mots, draft: false
- Tags ['hytale', 'industry', 'analysis'], date 2026-04-21 (ordering test)
- Coroutines Kotlin lifecycle-aware (SupervisorJob + cancel onDisable)
- Cocon sémantique bidirectionnel fermé avec l'article 08-02
2026-04-22 21:53:25 +02:00
kayjaydee
078e1a8a5f
docs(08-02): capture summary — first Hytale plugin tutorial (FR+EN seed article)
2026-04-22 21:52:53 +02:00
kayjaydee
5c10c275b1
feat(08-03): add EN blog article 'Hytale plugin development in 2026'
...
- Positioning/authority article 1009 words, draft: false, same slug as FR
- Tags ['hytale', 'industry', 'analysis'], date 2026-04-21
- 6 sections mirroring FR structure (idiomatic EN, not literal translation)
- Same Kotlin coroutines code block (code not translated)
- 2 inline links to /en/hytale (intro + outlook section)
2026-04-22 21:52:21 +02:00
kayjaydee
bb0ddcfa38
feat(08-03): add FR blog article 'Développement de plugins Hytale en 2026'
...
- Article positionnement/autorité 1148 mots, draft: false
- Tags ['hytale', 'industry', 'analysis'], date 2026-04-21
- 6 sections (intro, stack, patterns, écosystème, outlook, conclusion)
- 1 bloc Kotlin coroutines moderne (SupervisorJob + Dispatchers.IO + cancel lifecycle)
- 2 liens inline vers /hytale (intro + section outlook)
2026-04-22 21:52:16 +02:00
kayjaydee
0ba23acd1b
feat(08-02): add EN article how-to-build-your-first-hytale-plugin
...
- Equivalent EN version (970 mots), same slug
- 3 Kotlin code blocks (build.gradle.kts, event listener, command)
- 2 inline links to /en/hytale (intro + build section)
- Frontmatter Zod-valid : draft false, tags [hytale, tutorial, kotlin], date 2026-04-22
2026-04-22 21:52:00 +02:00
kayjaydee
7acea07812
feat(08-02): add FR article how-to-build-your-first-hytale-plugin
...
- Tutorial debutant plugin Hytale en Kotlin (1049 mots)
- 3 blocs code Kotlin realistes (build.gradle.kts, event listener, command)
- 2 liens inline vers /hytale (intro + build section)
- Frontmatter Zod-valide : draft false, tags [hytale, tutorial, kotlin], date 2026-04-22
2026-04-22 21:50:57 +02:00
kayjaydee
c0308edc2d
docs(08-01): scaffold HytaleRecentArticles SUMMARY — component bilingue + i18n FR/EN + injection /hytale
2026-04-22 21:48:48 +02:00
kayjaydee
2d004b15a7
feat(08-01): inject HytaleRecentArticles in /hytale + add i18n keys FR/EN
...
- app/pages/hytale.vue: <HytaleRecentArticles /> inserted after TestimonialsSection wrapper, before closing root div
- i18n/locales/fr.json: hytale.recentArticles {title, subtitle, viewAll} accentue style (aligned with blog.* 2026)
- i18n/locales/en.json: mirror keys
- No script changes (auto-import Nuxt)
2026-04-22 21:47:57 +02:00
kayjaydee
5eb494278d
feat(08-01): add HytaleRecentArticles component (queryCollection bilingual + JS tag filter)
...
- Bilingual literal branches queryCollection('blog_fr'|'blog_en') (Phase 5 Pitfall D-03)
- JS post-filter tags.includes('hytale') + slice(0,2) (D-11 — SQLite LIKE unreliable on JSON array)
- v-if=articles.length hides section when no hytale-tagged articles (D-12)
- BlogCard variant=compact in grid 2 col desktop / 1 col mobile
- NuxtLink localePath('/blog') viewAll CTA
- useAsyncData key hytale-recent-${locale.value} + watch:[locale]
2026-04-22 21:47:23 +02:00
kayjaydee
9cc1dbec5d
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
2026-04-22 18:38:13 +02:00
kayjaydee
9d6ed1780b
docs(08): map analogs for seed articles + HytaleRecentArticles component .planning/phases/08-content-cocon-semantique/08-PATTERNS.md
2026-04-22 18:32:43 +02:00
kayjaydee
32609a9843
docs(08): capture phase context — 2 articles seed Hytale + HytaleRecentArticles section (cocon sémantique blog↔hytale) .planning/phases/08-content-cocon-semantique/08-CONTEXT.md
2026-04-22 12:19:00 +02:00
kayjaydee
110c2dff86
docs(07): mark Phase 7 complete in ROADMAP (4/4 plans) .planning/ROADMAP.md .planning/phases/07-seo-blog/07-VERIFICATION.md
2026-04-22 11:25:57 +02:00
kayjaydee
6956155ce9
docs(07-04): complete sitemap dynamic feed plan
...
- Add 07-04-SUMMARY.md (endpoint Nitro bilingue + hreflang x-default + draft filter)
- Update STATE.md (14/15 plans, 93%)
- Check SEO-12 in REQUIREMENTS.md and ROADMAP.md
- Document gotcha queryCollection import from '@nuxt/content/server' (vue-tsc auto-import not resolved in server/)
2026-04-22 11:22:57 +02:00
kayjaydee
ae274e77ca
docs(07-02): complete blog article SEO plan summary + state update
...
Plan 07-02 shipped: useSeoMeta D-15 + useSchemaOrg Article/Breadcrumb on /blog/[slug],
resolveOgImage helper + og-blog-default.jpg fallback. Curl SSR validated,
typecheck green. Requirements satisfied: SEO-10, SEO-11, SEO-13, SEO-15.
2026-04-22 11:21:46 +02:00
kayjaydee
306e7bb12f
feat(07-04): add dynamic sitemap URL feed for bilingual blog articles
...
- Nitro route server/api/__sitemap__/urls.ts via defineSitemapEventHandler
- Queries blog_fr + blog_en with literal strings and event first-arg (Pitfalls 1 & 2)
- Filters draft=false (D-10, T-07-06 mitigation)
- lastmod = updated ?? date (D-09)
- Emits hreflang alternates fr/en/x-default for bilingual pairs, none for single-language (D-11)
- Feeds @nuxtjs/sitemap via sitemap.sources declared in 07-01
2026-04-22 11:20:09 +02:00
kayjaydee
2582c87df4
feat(07-02): enrich blog article page with full SEO meta + Article/Breadcrumb JSON-LD
...
- D-15: useSeoMeta extended with ogImage (absolute via resolveOgImage),
ogUrl (canonical), ogLocale + ogLocaleAlternate (emitted only when bilingual
pair exists), twitterCard + twitterImage, article:published_time,
article:modified_time (fallback to date when updated absent — D-13),
articleAuthor
- SEO-11/SEO-15: useSchemaOrg([defineArticle, defineBreadcrumb])
— Article author/publisher reference global Person via @id=#killian
(from app/utils/seo-person.ts KILLIAN_PERSON_ID), image mirrors ogImage,
mainEntityOfPage = canonical; BreadcrumbList emits Accueil → Blog → title
- Pitfall 7: altExists query via queryCollection('blog_en'|'blog_fr') with
literal collection names (Vite extractor constraint)
- inLanguageTag computed cast to satisfy overly narrow defineArticle typings
without changing runtime emission
- Validated SSR: curl /fr/blog/test-kotlin-syntax returns og:image absolute,
article:published_time, Article JSON-LD (author @id=#killian), BreadcrumbList 3 items
2026-04-22 11:19:58 +02:00
kayjaydee
d37f870f49
docs(07-03): blog listing SEO enrichment SUMMARY — D-16 + CollectionPage/Breadcrumb JSON-LD
2026-04-22 11:17:55 +02:00
kayjaydee
d2ab5681da
feat(07-03): enrich blog listing with D-16 useSeoMeta + CollectionPage/Breadcrumb JSON-LD
...
- Add SITE_URL + OG_FALLBACK constants (fallback hardcoded, resolveOgImage helper owned by 07-02)
- Extend useSeoMeta: ogImage (absolute /og-blog-default.jpg), ogUrl, ogLocale, ogLocaleAlternate, twitterCard, twitterImage
- Add useSchemaOrg([defineWebPage CollectionPage, defineBreadcrumb(Accueil -> Blog)])
- inLanguage resolved at setup (type constraint: literal union, not ComputedRef)
- Requirements: SEO-10, SEO-13, SEO-15
2026-04-22 11:17:10 +02:00
kayjaydee
b69252c556
feat(07-02): add resolveOgImage helper + og-blog-default.jpg fallback asset
...
- app/utils/resolve-og-image.ts: absolutises frontmatter image or falls back to /og-blog-default.jpg
- public/og-blog-default.jpg: placeholder (copied from og-image.png) — branded 1200x630 design follow-up pending
2026-04-22 11:16:37 +02:00
kayjaydee
44fcca6345
docs(07-01): capture plan summary
...
Foundation SEO Blog shipped — nuxt-schema-org installed, blog schema extended
with updated field, global Person/WebSite schema.org emitted SSR, sitemap.sources
wired to future Nitro endpoint (07-04).
2026-04-22 11:14:46 +02:00
kayjaydee
1a2cfc360b
feat(07-01): wire global schema.org Person + WebSite and sitemap sources
...
- nuxt.config.ts: register 'nuxt-schema-org' module + sitemap.sources=['/api/__sitemap__/urls']
- app/utils/seo-person.ts: KILLIAN_PERSON_ID + killianPerson (derived from siteConfig, email excluded)
- app/app.vue: useSchemaOrg([definePerson(killianPerson), defineWebSite({name, inLanguage})]) appended (D-12)
- Verified SSR: /fr emits JSON-LD Person @id=#killian + WebSite (curl, pas d'hydratation)
2026-04-22 11:13:51 +02:00
kayjaydee
2ec6a213f0
chore(07-01): install nuxt-schema-org + add updated field to blog schema
...
- pnpm add -D nuxt-schema-org@^6.0.4 (D-01, D-04)
- content.config.ts blogSchema: updated: z.string().optional() (D-13, D-14)
- Caches content/.nuxt vidés (Pitfall 8)
2026-04-22 11:10:39 +02:00
kayjaydee
543bcb00fb
docs(roadmap): mark Phase 6 plans 03-04 complete (summaries present since 2026-04-22) .planning/ROADMAP.md
2026-04-22 11:09:26 +02:00
kayjaydee
43d52a42e9
docs(07): plan SEO blog — 4 plans (schema-org, useSeoMeta enrich, sitemap Nitro) .planning/phases/07-seo-blog/07-01-PLAN.md .planning/phases/07-seo-blog/07-02-PLAN.md .planning/phases/07-seo-blog/07-03-PLAN.md .planning/phases/07-seo-blog/07-04-PLAN.md .planning/ROADMAP.md
2026-04-22 10:40:12 +02:00
kayjaydee
0577cc4041
docs(07): map analogs for new SEO files (schema-org + sitemap Nitro) .planning/phases/07-seo-blog/07-PATTERNS.md
2026-04-22 10:34:19 +02:00
kayjaydee
a9c9aef9b8
docs(07): capture phase research — nuxt-schema-org + sitemap Nitro endpoint .planning/phases/07-seo-blog/07-RESEARCH.md
2026-04-22 10:32:18 +02:00
kayjaydee
275d8f268c
docs(07): capture phase context — SEO blog (JSON-LD via nuxt-schema-org, og:image hybride, sitemap Nitro endpoint, hreflang alternates)
2026-04-22 10:25:39 +02:00
kayjaydee
71ab4f29d0
docs(06-04): article chrome SUMMARY — BlogToc + BlogPrevNext + enriched [slug].vue
2026-04-22 10:10:41 +02:00
kayjaydee
a6bb9463dd
feat(06-04): enrich blog article page with breadcrumb, TOC, prev/next
...
- isFr converti en computed (fix Phase 5 non-reactive isFr)
- { watch: [locale] } sur les 2 useAsyncData (article + surround)
- queryCollectionItemSurroundings avec littéraux 'blog_fr'/'blog_en', fields explicites
- Article query WITHOUT draft filter (direct URL access, D-14)
- Surround query WITH .where('draft','=',false).order('date','DESC')
- Mapping prev=surround[1], next=surround[0] (Pitfall 4 DESC order)
- Header: UBreadcrumb + H1 + meta row (date Intl + reading time) + tags + cover NuxtImg eager
- Layout grid desktop [1fr_16rem] avec max-w-3xl colonne article
- ContentRenderer prose wrapper Phase 5 préservé
- BlogToc aside + BlogPrevNext en bas
- ogType: 'article' (préparation Phase 7)
Requirements: BLOG-03, BLOG-06
2026-04-22 10:09:23 +02:00
kayjaydee
42369a1cb4
feat(06-04): add BlogPrevNext component (grid 2 cols, BlogCard compact variant)
2026-04-22 10:06:52 +02:00
kayjaydee
be532c545d
feat(06-04): add BlogToc component (sticky desktop + drawer mobile + IntersectionObserver highlight)
2026-04-22 10:06:38 +02:00
kayjaydee
a6582885a2
docs(06-03): blog listing page SUMMARY
2026-04-22 10:05:57 +02:00
kayjaydee
39dfef5c5a
feat(06-03): add blog listing page /blog (hero + grid + empty state)
...
- Query bilingue queryCollection('blog_fr') / queryCollection('blog_en') literal branches (Phase 5 gotcha)
- .where('draft', '=', false).order('date', 'DESC') with { watch: [locale] }
- Hero pattern /projects.vue: slogan // blog + H1 gradient + 3 stats (articles/tags/languages)
- Grid 1/2/3 responsive cols using BlogCard default variant
- Empty state with UIcon book-open + UButton CTA to /contact
- useSeoMeta minimal (full SEO + JSON-LD reserved for Phase 7)
Requirements: BLOG-02, BLOG-06
2026-04-22 10:05:16 +02:00
kayjaydee
36aaa3c9d6
docs(06-02): complete components UI + i18n locales plan
...
- Add 06-02-SUMMARY.md with 3 task commits (d299383 , 0e42a05 , d0ebf35 )
- Update STATE.md : plan counter 11/15 (73%), next = 06-03 listing page
- Update ROADMAP.md Phase 6 progress : 2/4 plans complete
- Record gotcha 06-02 : slug derivation via path.split('/').filter(Boolean).pop()
2026-04-22 09:15:55 +02:00
kayjaydee
d8a1d82376
feat(06-02): add BlogCard component with default + compact variants
...
- variant="default" (listing): cover image conditional (D-03 no fallback),
aspect-[16/9], first tag UBadge, date i18n via Intl.DateTimeFormat,
h2 title, line-clamp-2 description, reading time + extra tags pills,
absolute inset-0 NuxtLink for SEO/a11y (D-02 tags non-clickable)
- variant="compact" (prev/next, D-09/D-10): no image, label row with
UIcon arrow (left/right per direction), h3 title, date mono,
text-right on next / text-left on prev
- Props: article, variant?='default'|'compact', direction?='prev'|'next'
- Slug derived from article.path last segment (locale-agnostic)
- readingMinutes: uses article.minutes (Nitro hook) with useReadingTime
fallback on article.description
- Schema.org BlogPosting markup (headline/description/keywords/url/image/
datePublished) — ready for Phase 7 JSON-LD Article
- a11y aria-label interpolated via t('a11y.blogPrev'|'blogNext', {title})
2026-04-22 09:13:09 +02:00
kayjaydee
eca3e1d0b6
feat(06-02): add Blog nav link in AppHeader between Hytale and Projects
...
- Insert { key: 'blog', path: '/blog' } in navLinks computed array
- Position: between hytale and projects (D-15 ordering)
- Template v-for iterations unchanged — new link auto-propagates to
desktop nav + mobile slideover
- Label resolved via t(`nav.${link.key}`) → uses nav.blog key
added in Task 2.1
2026-04-22 09:11:27 +02:00
kayjaydee
68f55d4157
feat(06-02): add blog i18n keys (nav.blog, a11y.blog*, blog.*)
...
- Add nav.blog in FR (Blog) + EN (Blog)
- Add a11y.blogTocToggle, blogPrev, blogNext with {title} interpolation
- Add blog.* block: title, subtitle, stats (articles/tags/languages),
readingTime ({minutes} interpolation), prevArticle, nextArticle,
backToBlog, toc.title, emptyState (title/description/cta),
breadcrumb (home/blog)
- FR uses accents (Bientôt, précédent, Sommaire) per projects convention
2026-04-22 09:11:07 +02:00
kayjaydee
f05cdebbcf
docs(06-01): complete content schema + reading-time foundation plan
...
- Add 06-01-SUMMARY.md (5 tasks shipped, 0 deviations).
- Update STATE.md: Phase 6 Plan 06-01 shipped (1/4), gotchas recorded
(hook schema strip, Nitro ~/ alias), next plan = 06-02.
- Update ROADMAP.md M1.1 progress: Phase 5 Complete, Phase 6 at 1/4.
2026-04-22 09:08:42 +02:00
kayjaydee
0752468f07
chore(06-01): mark test-kotlin-syntax articles as draft (FR + EN)
...
- Add `draft: true` to frontmatter of both test-kotlin-syntax.md files
so they are excluded from all `queryCollection(...).where('draft', '=', false)`
listings (D-14).
- Articles remain accessible via direct URL (no draft filter on `.path(x).first()`),
keeping them available for internal rendering tests.
- Listings will be empty until real Hytale seed articles land in Phase 8 —
the empty state will render per D-16 ("Hytale articles coming soon" CTA).
- Body content untouched (only frontmatter +1 line each).
2026-04-22 09:05:47 +02:00
kayjaydee
64dfe376bf
feat(06-01): add useReadingTime composable fallback (200 wpm)
...
- Pure synchronous helper returning minutes (>= 1) from either a pre-computed
word count (number) or raw text (string, tokenized on whitespace).
- Client-side safety net when `article.minutes` isn't yet populated
(e.g., dev hot-reload before the Nitro hook re-parsed). Source of truth
remains the Nitro `content:file:afterParse` hook (D-19).
- Same 200 wpm formula as server-side hook — ensures listing ↔ article parity.
- Auto-imported by Nuxt thanks to `use*` naming convention.
2026-04-22 09:04:53 +02:00
kayjaydee
b5fe5deed5
feat(06-01): add Nitro hook content:file:afterParse for reading-time injection
...
- Register `content:file:afterParse` hook to inject `wordCount` + `minutes`
on every parsed markdown content object (D-19: 200 wpm, floor 1 min).
- Import pure util `countWordsInMinimalBody` from app/utils/countWords.
- Guard against non-`.md` files (defensive — hook fires on all sources).
- Values persist in @nuxt/content SQLite DB and are queryable via
queryCollection thanks to matching Zod fields (content.config.ts).
2026-04-22 09:02:23 +02:00
kayjaydee
28a84e0b64
feat(06-01): add countWordsInMinimalBody util for reading-time computation
...
- Pure AST traversal of @nuxt/content v3 minimal body shape
- Skips code and pre tags (code snippets are not readable prose)
- Zero dependency, zero import, reused by Nitro hook
2026-04-22 08:57:05 +02:00