The codebase context for builders

Project structure, token architecture, component anatomy, and a step-by-step guide to adding new components. Hand this file to any builder — human or AI — and they can extend the system without exploring.

What This Is

A React component library + design system + documentation website. It has two interconnected parts:

  1. Component Library (/src) — 42+ React components built with Vite + TypeScript. Each component has its own folder with implementation, scoped CSS, and Storybook stories. Components are consumed by the website via the @design-system path alias.
  2. Documentation Website (/website) — A separate Next.js app that showcases every component with live, interactive examples. Each component has its own page under website/src/app/components/[component-name]/.

The design spec lives in design.md — read it before touching tokens, colors, or typography.


Quick Start

# Component library dev server
npm run dev                    # http://localhost:5173

# Storybook (interactive component showcase)
npm run storybook              # http://localhost:6006

# Documentation website (separate project)
cd website && npm install && npm run dev   # http://localhost:3000

Other useful commands:

npm run build           # type-check + build library
npm run lint            # ESLint
npm run build-storybook # export static Storybook

Project Structure

/
├── design.md                  # Design spec — source of truth for tokens, colors, typography
├── src/
│   ├── components/            # 42 component folders (each self-contained)
│   ├── tokens/
│   │   ├── tokens-primitives.css    # Raw hex/px values — never use directly in components
│   │   ├── tokens-light.css         # Semantic tokens, light theme
│   │   ├── tokens-dark.css          # Semantic tokens, dark theme
│   │   └── tokens-typography.css    # Font size/weight/line-height scale
│   ├── fonts/                 # Nunito Sans + Material Symbols web fonts
│   └── App.tsx                # Dev sandbox (generic; components are imported via @design-system)
├── .storybook/                # Storybook config
├── website/                   # Next.js docs site (separate npm project)
│   ├── src/app/
│   │   ├── components/        # One folder per component, each with page.tsx + page.module.css
│   │   ├── foundations/       # Design tokens & layout doc pages
│   │   └── about/             # About/work pages
│   └── src/components/        # Shared Next.js UI (Header, Sidebar, Footer, etc.)
└── old-website-reference/     # Archived previous version — do not touch

Token Architecture

Three tiers — never skip a tier:

tokens-primitives.css       --primitive-teal-07: #118AB2
        ↓
tokens-light/dark.css       --color-action-primary-bg: var(--primitive-teal-07)
        ↓
Component CSS               background-color: var(--color-action-primary-bg)
  • Primitives (--primitive-*) — raw values. Source of truth. Never referenced in components.
  • Semantic tokens (--color-*, --radius-*, --gap-*, --padding-*, --font-*) — always use these in components.
  • Dark mode is driven by data-theme="dark" on the root element. Every semantic token has a light and dark value — no prefers-color-scheme queries in components.

Key invariants:

  • Teal --color-action-primary-bg (#118AB2) is only for primary CTA buttons and focus rings. Never decorative.
  • Never hardcode hex values in component CSS — always a semantic token.
  • Buttons are always --radius-full (pill). Inputs and cards are always --radius-md (12px).

Component Anatomy

Every component lives in its own folder under src/components/:

src/components/Button/
├── Button.tsx            # TypeScript implementation + exported interface
├── Button.css            # Scoped CSS using semantic token vars
└── Button.stories.ts     # Storybook stories (Meta + named Story exports)

Components are imported in the website using the @design-system alias:

import { Button } from '@design-system/components/Button/Button';

CSS class naming: ds-{component} base class, ds-{component}--{modifier} for variants. Example: ds-button, ds-button--primary, ds-button--compact.


How to Add a New Component

  1. Create the folder: src/components/MyComponent/
  2. Write MyComponent.tsx: Export a named component + a TypeScript interface for props. Use semantic tokens in class names, never inline styles.
  3. Write MyComponent.css: All CSS vars must be from tokens-light/dark.css. No hardcoded hex, px values from primitives, or magic numbers.
  4. Write MyComponent.stories.ts: Export a meta (with title: 'Components/MyComponent', tags: ['autodocs']) and at least a Default story plus one per meaningful variant.
  5. Add a website page: Create website/src/app/components/my-component/page.tsx + page.module.css. Follow the pattern in an existing page (e.g., website/src/app/components/button/page.tsx).
  6. Register in navigation if needed: check website/src/config/navigation.ts.

Checklist before shipping a component:

  • All colors via semantic tokens
  • Dark mode verified (toggle data-theme="dark" in Storybook)
  • Disabled state at opacity: 0.4, cursor: not-allowed
  • Interactive elements have ARIA roles and keyboard navigation
  • At least one Storybook story per variant
  • Website showcase page added

Design Principles (distilled from design.md)

  • Single typeface: Nunito Sans only. Weight 300 for display/marketing, 600 for in-app headings, 500/400 for body. Inter is an acceptable prototype substitute; avoid Arial/Helvetica.
  • White-floor UI: page background is pure white (#FFFFFF light / #050505 dark). Depth comes from the container color ramp (container-primarysecondarytertiary) — not shadows.
  • Teal (#118AB2) is the action color: primary buttons, focus rings, active input borders. Using it decoratively on text or illustrations dilutes its CTA signal.
  • Five status variants — no more: info (blue), positive (green), warning (orange), error (red), neutral (gray). Badge, Alert, Toast, and ProgressBar all share the same --color-status-* token set.
  • No box shadows on standard containers: the elevation system is color-based. The only shadow in the system is on floating surfaces (popovers, dropdowns): 0 2px 8px rgba(5,5,5,0.08).
  • Material Symbols Rounded for all icons — 24px default, 20px compact.
  • Weight contrast is the heading hierarchy rule: h2 is 30px/300 (light), h3 is 22px/600 (bold). Never use the same weight for consecutive heading levels.

Key Files

FilePurpose
design.mdFull design spec — colors, typography, spacing, all component rules
src/tokens/tokens-primitives.cssRaw hex/px values
src/tokens/tokens-light.cssSemantic token definitions (light)
src/tokens/tokens-dark.cssSemantic token overrides (dark)
src/tokens/tokens-typography.cssFont size/weight/line-height scale
src/components/Button/Button.tsxReference implementation for a component
src/components/Button/Button.stories.tsReference for Storybook story structure
website/src/app/components/button/page.tsxReference for a website showcase page
website/src/config/navigation.tsNav links — update when adding pages
.storybook/main.tsStorybook config (addons, stories glob)

Known Gaps (from design.md)

  • No --motion-* token for animation timings — transitions are hardcoded 0.2s ease
  • No --icon-size-* tokens — icon sizes are hardcoded per component
  • No --chart-series-{n} formal token set for ordered chart series colors
  • No Figma file URL documented yet
  • No GitHub Actions CI — no automated lint/test/Storybook build on push