Koder Icons — curated shared UI icon library + KDS surface

draft

stackRFC003 — Koder Icons: curated shared UI icon library + KDS surface

§1 — Problem

The Koder Stack has formal icon infrastructure *nly for product brand icons*(one SVG per Koder product, generated to PNG variants by kicon). It does *ot*have a curated library of *I icons*shared across products: avatar defaults, empty-state graphics, error illustrations, category symbols, action glyphs branded to match Verge.

Today each product reaches independently into Flutter's built-in Icons.* (Material). Consequences observed in production:

  • Inconsistency: Hub uses Icons.account_circle_outlined in the login modal, Kruze used a literal ? in the same role for over a year (KRUZE170, 20260522). No central reference said "this is what signedout looks like in Koder."
  • Branding leak: every product looks "generic Material" in its emptyerror states. Verge tokens cover colorspacing/typography but not iconography.
  • Discoverability: no place to look up "is there a canonical Koder icon for X?"
  • Asset duplication: Hub ships its own asset://assets/icons/<category>.png set for app categories (HUB151 family), which other products would reinvent if they needed similar categories.

§2 — Decision

Create a curated icon library shipped as a Koder Stack SDK and surfaced as a browsable section of kds.koder.dev.

*odule path (canonical):*engines/sdk/koder_icons/

*ayout:*

engines/sdk/koder_icons/
├── icons/                          # SOURCE OF TRUTH — master SVGs
│   ├── avatar/
│   │   ├── default.svg
│   │   ├── default-circle.svg
│   │   └── default.frontmatter.yaml  # tags, aliases, sizes, status, since
│   ├── empty-state/
│   │   ├── search.svg
│   │   ├── messages.svg
│   │   └── ...
│   ├── error-state/
│   │   ├── offline.svg
│   │   ├── server-error.svg
│   │   └── ...
│   ├── category/
│   │   ├── productivity.svg
│   │   ├── media.svg
│   │   └── ...
│   ├── action/                     # branded wrappers over Material (only when Material's default doesn't fit Verge)
│   │   ├── share.svg
│   │   └── ...
│   └── brand-koder/                # logos curated in variants
│       ├── wordmark.svg
│       └── mark.svg
├── flutter/                        # Flutter package
│   ├── lib/koder_icons.dart        # exports KoderIcons.avatarDefault, etc.
│   ├── lib/src/generated.dart      # auto-generated from icons/ + frontmatter
│   └── pubspec.yaml
├── web/                            # npm + standalone web font subset
│   ├── package.json
│   ├── dist/koder-icons.css        # font-face declarations
│   └── dist/koder-icons.woff2      # subset font (only shipped icons)
├── tools/                          # CLI helpers
│   └── (extends dev/kicon)
├── README.kmd
└── koder.toml

*aming convention:*

  • Filesystem: koder-icons/<group>/<variant>.svg — kebab-case
  • Dart import: KoderIcons.<group>_<variant> (snake-case from kebab) — e.g., KoderIcons.avatar_default, KoderIcons.empty_state_search
  • HTML: <koder-icon name="<group>-<variant>" size="24"></koder-icon> web component, OR CSS class <i class="ki ki-avatar-default"></i>
  • Per-icon frontmatter.yaml:
name: avatar/default
title: Default User Avatar
aliases: [user, person, profile]
tags: [avatar, user, generic]
sizes: [16, 20, 24, 32, 48]
status: stable
since: v0.1.0

§3 — Distribution

Surface Package Versioning
Flutter (mobile + desktop) koder_icons pub package semver per release
Web (JS) @koder/icons npm + standalone CSS+woff2 semver
Linux desktop apps koder-icons .deb on Hub apt aligned with semver

Single source of truth: engines/sdk/koder_icons/icons/. All distribution forms are derived. Buildtime codegen runs on every kpkg pack or prerelease CI step.

§4 — Curation policy

*nclusion criteria:*

  • Used (or imminently planned) in ≥2 Koder products
  • Cannot be satisfied by Material's Icons.* without sacrificing Verge brand consistency
  • Has a clear semantic name that a designer in any product would recognize

*xclusion criteria:*

  • One-off product brand icons (those stay under <product>/icons/ and use kicon)
  • Decorative ornaments — those live in product theme assets, not the SDK
  • Material-equivalent icons that don't need rebranding (just use Icons.X)

*rocess:*

  • Anyone can propose new icons by opening a ticket in engines/sdk/koder_icons/backlog/pending/
  • Designer review required before merge to icons/
  • kicon icons-audit in CI blocks adoption of an icon not present in the SDK if it's used by ≥2 products

§5 — KDS site surface

kds.koder.dev/<locale>/icons/ becomes a new section adjacent to existing palette/, fonts/, verge/.

*tools/design-gen` extension:*

  • cmd/design-gen/handlers/icons.go — new handler that walks engines/sdk/koder_icons/icons/, parses frontmatter, renders gallery + per-icon detail pages
  • templates/icons/index.html — gallery with search + category filter + light/dark toggle
  • templates/icons/detail.html — per-icon page with:
    • SVG preview (light/dark sidebyside)
    • Code snippets: Flutter (KoderIcons.X), HTML webcomponent (`<kodericon>), CSS class (<i class="ki ki-X">`), raw SVG download
    • Size variants displayed inline
    • Aliases + tags for search
    • Changelog entry (since version)

Autoregenerates on every designgen build → no manual sync between SDK and site.

§6 — Migration path

*hase 1 — Bootstrap (~5h):*

  • Scaffold engines/sdk/koder_icons/ with empty structure + README
  • Ship 3 founder icons in Phase 1:
    • avatar/default.svg (motivated by KRUZE170, used by Kruze sidebar + Hub login + future Talk signin)
    • empty-state/search.svg (used by Hub search + Drive find + Kruze history search)
    • error-state/offline.svg (used by Hub + Kruze + Talk + Drive)
  • Flutter package wrapper + first three KoderIcons.X exports
  • design-gen icons.go handler renders icons section with these 3
  • Migrate KRUZE-170 from Icons.account_circleKoderIcons.avatar_default

*hase 2 — Coverage expansion (~10-20h, ongoing):*

  • Audit all Koder product backlogs for TODO: brand-this-icon markers, prioritize fill-out
  • Goal: ≤5% of icon usage in products falls back to raw Icons.X
  • Hub categories (assets/icons/<category>.png) migrate from PNG to SVG SDK icons

*hase 3 — Lock-in (~ongoing):*

  • kicon icons-audit becomes pre-commit hook in every product repo (blocking)
  • New product onboarding includes "use KoderIcons" in CLAUDE.md gatilho table

§7 — Open questions for owner ratification

  1. *tyle direction*— outlined vs filled vs duotone as default? Material's choice is "Symbols (variable)". Verge equivalent should be decided once. Default suggestion: outlined, stroke 2px, rounded caps (matches Verge button styling).
  2. *icense*— assets under OFL (matches fonts wave) or under CC0 / MIT? Owner decision.
  3. *ize canonical set*— 16, 20, 24, 32, 48 sufficient? Add 64/128 for hero variants?
  4. *ub categories migration*— should `enginessdkkoder_icons/category

Source: ../home/koder/dev/koder/meta/docs/stack/rfcs/stack-RFC-003-koder-icons-shared-ui-library.kmd