Blog / changelog index
HTML index page at `kds.koder.dev/blog/` that lists Koder Design releases as blog-style cards, ordered newest-first. Material parity (`/blog`). Backed by the same source data that powers the existing `feed.xml` RSS feed.
Spec — Blog / changelog index
Facet *ool*of Koder Design. Material parity: https://m3.material.io/blog.
URL: https://kds.koder.dev/{locale}/blog/ (canonical; /changelog/ 301 → /blog/).
Two views
| View | URL | Use |
|---|---|---|
| *ndex* | /blog/ |
List of all releases (paginated) |
| *ntry* | /blog/{version-slug}/ |
Single release detail |
Both views render via design-gen kind blog (new kind).
R1 — Index layout
┌─────────────────────────────────────────────┐
│ Koder Design · Blog │
│ ─────────────────────────────────────────── │
│ │
│ [Latest] [v1.x] [v0.x] [All] │ ← version filter chips
│ │
│ v1.4.0 · 2026-05-11 │ ← entry card
│ Cluster 4 wave 2 — 16 components │
│ 3,686 lines added · 16 new specs │
│ [Read more →] [Migrate from v1.3.0 →] │
│ ─────────────────────────────────────────── │
│ v1.3.0 · 2026-05-09 │
│ Cluster 4 wave 1 — 8 component specs │
│ ... │
│ ─────────────────────────────────────────── │
│ v1.2.0 · ... │
│ │
│ [← Previous] · 1 of 3 · [Next →] │
└─────────────────────────────────────────────┘- Entry cards stacked vertically
- Each card: version + date + 1-line summary + 2 metric facts +
buttons (Read more, Migrate from prev)
- Filter chips at top: All (default) / Latest minor major / by major
version
- Pagination: 10 entries per page
R2 — Entry detail layout
/blog/v1.4.0/ (single release page):
┌─────────────────────────────────────────────┐
│ v1.4.0 · 2026-05-11 │ ← header
│ Cluster 4 wave 2 — 16 components │
│ ─────────────────────────────────────────── │
│ Summary (1-2 paragraph hand-written) │
│ ─────────────────────────────────────────── │
│ ## Added │
│ - 16 component specs in `specs/components/` │
│ - Consolidation policy: Material agrupa │
│ ... │
│ │
│ ## Changed │
│ - Umbrella #049: 31/62 → 47/62 (50% → 76%) │
│ │
│ ## Deprecated / Removed │
│ - (none) │
│ │
│ ## Stats │
│ - 3,686 lines added / 20 removed │
│ - 16 files created │
│ - 1 commit │
│ ─────────────────────────────────────────── │
│ [← All releases] · [Migrate from v1.3.0 →] │
│ [GitHub diff →] │
└─────────────────────────────────────────────┘R3 — Source of truth
A single meta/docs/stack/releases/releases.toml file holds all release metadata. Each release stanza:
[[releases]]
version = "v1.4.0"
date = "2026-05-11"
title = "Cluster 4 wave 2 — 16 components"
summary = "Wave 2 of the Material.io parity programme ..."
tags = ["components", "wave-2", "#049"]
commits = ["1956224163"]
stats = { added = 3686, removed = 20, files = 16 }
migrate-from = "v1.3.0"The design-gen blog kind reads this file (TOML), sorts by date desc, paginates, and renders both views.
R4 — Adding a new release entry
Per releases.kmd policy, each tag of meta/docs/stack/v* automation:
- Auto-extracts version + date + commit refs from tag
- Owner writes the
summary(1-2 paragraphs) at tag time - Generator writes the stanza to
releases.toml design-genrebuilds/blog/index + new entry page- RSS feed (
feed.xml) regenerates from same source
Migration guide crosslink autocomputed (migrate-from field).
R5 — RSS feed (existing)
feed.xml already exists per Makefile (make rss VERSION=vX.Y.Z).
This spec adds the HTML index that mirrors the RSS:
- RSS = machine-readable
- Blog = human-readable
- Both consume the same
releases.toml
R6 — Filter chips
Per components/chips.kmd filter variant:
[Latest](single-select, shows only the latest entry)[v1.x](multi-select with other major filters; shows all v1.* releases)[v0.x][All](default, no filter)
URL state: /blog/?version=v1.x (shareable).
R7 — Search
Single search box at top of index — full-text over title + summary + tags fields. Live-filters cards as user types. No server roundtrip (client-side index, < 50 KB).
R8 — Pagination
10 entries per page default; URL params: ?page=2. "Previous" / "Next" buttons + numbered page links (e.g., "1 of 3").
If filtered to < 10 entries, no pagination shown.
R9 — Per-locale content
Index UI strings localized (filter chip labels, "Read more", pagination labels). Entry detail content (summary, sections) is en-US source; ptBR localization optional per release (ownercurated when material is significant).
R10 — Accessibility
- Entry cards:
<article>semantic,<h2>for version title - Pagination:
aria-label="Pagination"+aria-current="page"onactive page
- Filter chips:
role="checkbox"per chip (multi-select group) - Search box:
role="searchbox" - Skip
tocontent link - Headings hierarchical: h1 (page) → h2 (entry) → h3 (Added / Changed
sections inside entry detail)
R11 — Performance
- Index page: < 50 KB HTML (only first 10 entries + filter chips)
- Search index: < 50 KB JSON (titles + summaries + tags)
- Lighthouse score ≥ 95 (matches rest of KDS site)
R12 — Forbidden patterns
- ❌ Hardcoded HTML release list (always generate from
releases.toml) - ❌ Separate index page per locale duplicating
releases.tomlcontent
- ❌ Releases without
migrate-from(every release ≥ second has apredecessor — link out to migration guide)
- ❌ Pagination with > 20 entries per page (perf + scan ergonomics)
- ❌ "Subscribe" form that's not RSS / Atom (no email gating)
Cross-link
tools/migration-guides.kmd— entry detail links to migrationguide (
migrate-fromfield)releases/packaging.kmd— release artifact names + tag policylanding-pages/products.kmd— overall site structure- Generator code:
tools/design-gen/internal/kinds/blog.{go,templ} - Source file:
meta/docs/stack/releases/releases.toml