Blog — editorial posts (extension)
Strict extension to `tools/blog-changelog-index.kmd` (#049.59). Adds editorial post kind (long-form case studies, deep dives, design philosophy) alongside auto-generated changelog entries. Owner-curated content per feedback memory `kds_owner_curated_content`.
Spec — Blog editorial posts
Strict extension to
blog-changelog-index.kmd(#049.59 ratified). This spec adds editorial post pipeline without breaking changelog behavior.
Princípios
- *wo kinds, one index*—
changelog(auto-gen) +post(editorial); merge sorted by date desc. - *wner-curated editorial*— IA não escreve posts autonomamente (per
feedback_kds_owner_curated_content). - *arkdown source*— editorial posts live in
meta/docs/stack/blog/<slug>.md. - *rontmatter contract*— required fields enforced.
- *ilterable*— index supports
kindfilter chips.
R-edit.1 — Source directory
Editorial markdown source:
meta/docs/stack/blog/
├── README.md
├── 2026-05-14-m3-expressive-launch.md
├── 2026-04-29-hub-package-pages-bug.md
└── ...File naming: YYYY-MM-DD-<slug>.md (date prefix sorts naturally).
Changelog source remains in releases.toml per blog-changelog-index.kmd R1.
R-edit.2 — Frontmatter contract
Every editorial post has YAML frontmatter:
---
title: "Material 3 Expressive: what we shipped"
author: Rodrigo Mendonça
date: 2026-05-14
tags: [design, m3, expressive]
category: design-system
cover: og-images/m3-expressive-launch.png
excerpt: "Short summary for index card preview"
---| Field | Required | Notes |
|---|---|---|
title |
yes | Display name |
author |
yes | Display name (Koder user) |
date |
yes | ISO 8601 |
tags |
no | Array of strings |
category |
yes | One of: design-system / engineering / product / process |
cover |
no | OG image path (relative to meta/docs/stack/blog/) |
excerpt |
no | Manual excerpt; auto-generated from first paragraph if absent |
R-edit.3 — Index merge behavior
design-gen produces /blog/ index merging both kinds:
<ol class="blog-index">
<li data-kind="post" data-date="2026-05-14">Material 3 Expressive...</li>
<li data-kind="changelog" data-date="2026-05-13">v0.22.0 koder_kit...</li>
<li data-kind="post" data-date="2026-04-29">Hub package pages bug...</li>
...
</ol>Sort: data-date desc.
R-edit.4 — Filter chips
Index page renders filter chips at top:
- *ll*(default; both kinds)
- *hangelog*(only
kind=changelog) - *ditorial*(only
kind=post) - (Optional) Category chips per
categoryfield. - (Optional) Tag chips per most-used tags.
Filters update visibility client-side (no page reload); URL hash preserves filter state (#filter=editorial).
R-edit.5 — RSS feed
/blog/feed.xml includes BOTH kinds. RSS items have <category> matching frontmatter; client RSS readers can filter.
Redit.6 — Ownercurated editorial
Per feedback_kds_owner_curated_content:
- IA NÃO escreve posts editoriais autonomamente.
- IA pode escrever DRAFTS apenas se owner solicita explicitamente.
- Owner sempre revisa antes de publicar.
- Changelog entries permanecem auto
gen (deoff-by owner.releases.toml); editorial requer commit signed
Audit log: editorial commits MUST carry Reviewed-by: <owner> trailer.
R-edit.7 — Rendering
design-gen template extension:
- New kind
postregistered. - Markdown parsed via existing markdown pipeline (mesmo do migrate kind).
- Cover image rendered as hero at top of post body.
- Excerpt rendered no index card.
T-suite
- *1*Editorial post with full frontmatter: parses correctly; appears em index.
- *2*Editorial post without optional fields (cover/excerpt): excerpt auto-extracts first paragraph; cover defaults to category icon.
- *3*Filter chip "Editorial": only posts visible.
- *4*Filter chip "Changelog": only changelog entries visible.
- *5*RSS feed includes both kinds with correct categories.
- *6*Circular include in
{include}(markdown): detected + rejected. - *1*Editorial commit without
Reviewed-bytrailer: CI warns (não bloqueia, mas registra).
Cross-link
- Base:
blog-changelog-index.kmd(#049.59) - Source format:
policies/document-format.kmd(.mdpermitted em blog tree) - Feedback memory:
kds_owner_curated_content(não-edit por IA autônoma)