design-gen — KDS site generator

  • Area: Developer Tools
  • Path: tools/design-gen
  • Kind: Go + templ + HTMX static-site generator behind kds.koder.dev

Role in the stack

design-gen is the canonical source-to-site pipeline for the Koder Design System (KDS). It walks the Stack-level specspoliciesRFCs plus locale strings and emits the multi-locale kds.koder.dev site, machine-readable APIs (JSON catalog + tokens), and language-bound token exports consumed by every Koder UI surface (Flutter koder_kit, web koder_web_kit, Rust UI [planned], Kotlin/Swift mobile bindings).

The site is the read half of KDS; the specs in meta/docs/stack/specs/ are the write half. design-gen has no state of its own — it's a pure function from specs+presets to rendered output.

What it generates

Artifact Path in dist/ Consumed by
Localized HTML pages <locale>/<facet>/<slug>/index.html Browser visitors via kds.koder.dev
Catalog index api/v1/specs.json (+ api/v1/index/<kind>.json subindexes) LSP, Figma sync, AI agents, internal tools; versioned with schema_version + generated_at
Token manifest api/v1/tokens.json koder-design-lsp (live, 24h TTL)
Search index api/v1/search.json Site client-side search
Token bindings tokens/tokens.{css,scss,json,dart,d.ts,kt,swift} koderkit, koderweb_kit, mobile, generic
OG images <locale>/<facet>/<slug>/og-image.png Social previews (chromedp-rendered)
Sitemaps sitemap.xml, robots.txt Crawlers (env-aware noindex per policies/environments.kmd)
AI discovery llms.txt, llms-full.txt Claude, Copilot, Gemini (llmstxt.org standard)
Feeds feed.xml RSS readers, change-watchers
PWA sw.js, manifest.json Service worker for offline reads
Embed manifest embeds/manifest.json Flutter Web widget bundles

Pipeline

  meta/docs/stack/specs*.kmd       i18n/{en-US,pt-BR,es-ES}.json
                |                                   |
                +-------> design-gen ---------------+
                                |
                                v
  internal/spec/walk.go      classify by frontmatter `kind:`
                                |
                                v
  internal/kinds/<kind>.go   per-kind renderer (component, pattern, theme, ...)
                                |
                                v
  internal/render/render.go  dispatch + parallel render
                                |
                                v
  dist/<locale>/<facet>/<slug>/index.html  +  dist/api/v1
*.kmd` — normative contracts (components,
  patterns, themes, app-layout, motion, voice, fonts, accessibility,
  i18n, ai-ui, errors, signing, ...)
- `meta/docs/stack/policies*.kmd` — behavioral policies
- `meta/docs/stack/rfcs*.kmd` — ratified RFCs (design-RFC-001…008)
- `tools/design-gen/i18n/{en-US,pt-BR,es-ES}.json` — locale strings
  (~1.5K keys per locale)
- `tools/design-gen/assets/css/{base.css,presets.css}` — visual
  baseline + 44 ratified Verge/UI-style presets
- `tools/design-gen/assets/fonts/` — self-hosted Inter + JetBrains
  Mono WOFF2 (per `specs/fonts/typography.kmd`)

## Outputs

See "What it generates" table above.

## Deploy

- **Production:** `kds.koder.dev` (HTTP/3 + QUIC, no auth)
  on Koder Jet vhost at s.khost1 (`/var/www/kds-prd`)
- **Staging:** `stg.kds.koder.dev` (auth-gated, noindex per
  `policies/environments.kmd`)
- **Legacy redirect:** `design.koder.dev` → 301 to `kds.koder.dev`
  (post-rename per `projects/koder-stack#127`)
- **Trigger:** Manual via `deploy/deploy.sh PRD_CONFIRMED=1`; CI auto
  via `.gitea/workflows/design-*` workflows; spec-change webhook
  planned (#116)

## Primary couplings

| Consumer | Relationship |
|---|---|
| `engines/sdk/koder_kit` | Vendors `dist/tokens/tokens.dart` into `lib/src/motion/motion_tokens.dart`; deep-links from widget docstrings (#064) |
| `engines/sdk/koder_web_kit` | Vendors `dist/tokens/tokens.css` into `assets/css/` |
| `engines/sdk/koder-design-lsp` | Fetches live `kds.koder.dev/api/v1/tokens.json` with 24h TTL cache for editor hover + autocomplete |
| Figma sync (project tracker) | Pulls `dist/tokens/tokens.json` snapshot per deploy |
| AI agents (Claude/Copilot/Gemini) | Consume `kds.koder.dev/llms.txt` + `/llms-full.txt` for context; MCP discovery shipped — static `mcp/descriptor.json` + `.well-known/mcp.json` (#117/#128); runtime MCP server lives in koder-design-lsp (`--mcp-http`, design-RFC-010) |
| `infra/net/jet` | Serves the vhost; vhost config in `tools/design-gen/deploy
*.html`
and validates internal `href`/`src`/`srcset` targets resolve on disk;
the report lands at `dist/.broken-links.json`. As of #148 Phase C
(2026-05-28) the **prd gate is strict zero** — `deploy.sh
MAX_BROKEN_LINKS_PRD=0` fails any prd deploy that introduces a broken
internal link, and `tests/regression/broken_links_test.go` holds the
same baseline at 0 (2568 → 0 across Phases A–C).

How specs reference content KDS does **not** render (the cross-corpus
contract, `internal/kinds/xref.go::crossCorpusURL`, Opção A):

| Ref in a spec body | Resolves to |
|---|---|
| `../../policies\|rfcs\|registries/<x>` | `https://meta.koder.dev/<corpus>/<x>` (rendered governance portal) |
| `../../backlog/…`, cross-repo source (`../../../infra/…`) | `https://flow.koder.dev/Koder/koder/src/branch/master/<path>` (source viewer; private → authed) |
| `../components/<x>.kmd` | `/<locale>/reference/components-<x>.html` (internal) |

KDS stays design-system-only; governance keeps its single canonical home
at meta.koder.dev. The checker skips `<pre>`/`<code>` example markup, and
`EnsureRSSFeed` guarantees `/feed.xml` exists on a fresh dist/ so the
strict gate is safe on clean CI builds.

## Backlog topology

- **Component backlog:** `tools/design-gen/backlog/` — 181 done, 1 pending
  (#177 personas ratification — human-gated on community vetting + owner
  art direction). The 2026-05-29 k-evolve rounds (#155–#168) saturated the
  gate/test/incremental gaps; the 2026-06-02 round added a11y AA reconcile
  + theme/SW/CSP fixes (#170–#176), three observability-polish closes
  (#178 per-phase status in `.build-stats.json`; #179 OG per-page failure
  sidecar `.og-perpage-failures.json`; #180 `internal/diag` — single sink
  for build-time warnings, text/JSON via `KDS_LOG_JSON`), and #181 (reconcile
  a stale settings-rail test left red by the #175 theme dedup). **Code-tractable
  gaps are saturated** — a full 6-dimension k-evolve scan (2026-06-02)
  found only those minor observability items; the sole remaining ticket is
  owner/translator/art-gated (#177), and broader open work is
  owner/translator-driven (7-locale expansion, full es-ES copy) or needs a
  Chrome host (gen/gen-parity validation on s.khost1)
- **Stack-level companions:** `meta/docs/stack/backlog/` for cross-cutting
  KDS-arc tickets (this module's doc, the public API spec, the token
  consumer registry, …)
- **Cross-module tickets:** `infra/net/jet#160` (CSP header for
  kds.koder.dev), `engines/sdk/koder_kit#064` (deep-link convention),
  `engines/sdk/koder-design-lsp#004` (cache-hit telemetry)

## Velocity signal

~6–8 week sprint cadence; steady mix of spec/architecture + components
+ patterns + audit tooling. Zero rolled-back tickets; deferred work
explicitly parked (e.g. versioned docs #097 deferred until first
breaking change or Verge v1).

## Why no replacement

design-gen is greenfield — there's no Material/Carbon/Fluent generator
to displace; the KDS taxonomy is owner-defined and the emit targets
(7 token languages, 3 locales, AI discovery surfaces) are Koder-specific.
Self-hosted gate: not applicable (`replaces = []`).

## See also

- `tools/design-gen/README.md` — developer how-to (quickstart, layout,
  locale add, preset add)
- `tools/design-gen/koder.toml` — Stack-convention metadata
- `meta/docs/stack/registries/token-consumers.md` — every token
  consumer registered