KDS

Architecture

How KDS is organised and how the pieces fit together at runtime.

How KDS is organised, why it's organised that way, and how the pieces fit together at runtime.

Repository structure

KDS lives in the bridge monorepo, in packages/kds/. The monorepo also hosts apps/docs (this site), apps/storybook (the internal lab) and apps/control (an internal Unraid-inspired dashboard).

bridge/
├── apps/
│   ├── docs/               # this site (Fumadocs)
│   ├── storybook/          # internal Storybook lab
│   └── control/            # internal dashboard (Phase 6)
├── packages/
│   ├── kds/                # @kalvner/kds — the DS package
│   ├── eslint-config/      # @kalvner/eslint-config (shared)
│   └── tsconfig/           # @kalvner/tsconfig (shared)
└── tools/
    └── theme-mapping/      # tweakcn → primitive mapping script

Token architecture (3 layers)

Three layers, each with a distinct responsibility:

LayerLives inNamingChanges
1. Primitive@theme {} blocks--color-<palette>-<stop>Almost never (follows Tailwind)
2. Semantic:root / [data-theme] selectors--<role> (no prefix)Per theme switch
3. Chart@theme inline {} blocks--color-chart-<group>-<n>Per chart-data context

Editing a primitive cascades through every theme that references it. Switching data-theme="X" updates every semantic token in-place — components stay ignorant of which theme is active.

See Tokens / Visão geral for the full picture.

Component file structure

Every primitive lives in packages/kds/src/primitives/<categoria>/<Component>/:

Button/
├── Button.tsx            # Component implementation
├── Button.stories.tsx    # CSF3 stories (variants, states, composed)
└── index.ts              # Barrel export

The companion documentation MDX lives in apps/docs/content/primitives/<categoria>/<component>.mdx (per ADR-017 — centralised in the docs app, not co-located in the package). Stories without an MDX page, or MDX without stories, fail review. The 11 MDX sections come from the storybook-component-doc skill in the Kalvner skill library.

Categories (9 functional groups)

Components are organised by what they do, not what they look like. The 9 canonical categories are:

Containers · Typography · Forms · Display · Data
Feedback · Navigation · Overlays · AI

AI is one category alongside the other 8 — not a special case. Within AI, components are sub-categorised in Chatbot (18) and Code (15) to mirror Vercel AI Elements.

See knowledge/ui/design-systems/storybook-structure.md for the canonical decision matrix when a component's category is ambiguous.

Patterns / Layouts / Blocks

Three layers above primitives:

  • Patterns — multi-component compositions that solve a recurring problem (DataTable, EmptyState, FormSection)
  • Layouts — full-page shells (AppShell, AuthShell)
  • Blocks — copy-pasteable page templates (CrudListPage, DashboardGrid, SettingsPage)

Each layer is a separate sidebar section.

Distribution

@kalvner/kds publishes to GitHub Packages under the @kalvner scope, restricted to Kontar and Kalvner's personal projects. Path-per-component subpath exports give consumers guaranteed tree-shaking:

import { Button } from "@kalvner/kds/forms/button";  // preferred

Per ADR-012, barrel imports (@kalvner/kds) work as a fallback but aren't documented for new code.

Build & deploy

This site deploys to ds.kalvner.com via Vercel. Component PRs run lint + typecheck + build + (Phase 5+) Chromatic visual regression on every push.

On this page