Skip to content

DOMAIN:DESIGN:DESIGN_SYSTEM_ENGINEERING

OWNER: alexander (Design System Engineer, shared) UPDATED: 2026-03-24 SCOPE: design system creation, DESIGN.md authoring, shadcn/ui theming, Stitch MCP integration PREREQUISITE: formal-specification.md (Anna's spec defines screens and interactions)


PRINCIPLE: DESIGN_IS_CODE_NOT_ART

RULE: in agentic development, design is a specification — not a visual artifact. RULE: DESIGN.md is the single source of truth for design decisions. RULE: developers consume design tokens and component selections, not Figma files. REASON: agents cannot interpret screenshots or mockups. They need structured, machine-readable design specs. DESIGN.md bridges the gap between visual design intent and code implementation.


THE_THREE_LAYER_DESIGN_MODEL

LAYER 1 (80% of screens): STANDARD
  shadcn/ui components + DESIGN.md tokens
  No Stitch needed. Alexander selects components, defines tokens.
  Developers implement directly from DESIGN.md.

LAYER 2 (15% of screens): CUSTOM
  Alexander describes screen → Stitch generates visual UI
  Human (Dirk-Jan) reviews Stitch output
  DESIGN.md updated with custom component specs

LAYER 3 (5% of screens): PREMIUM
  External designer creates mockup with DESIGN.md constraints
  Alexander translates to component spec
  Rare — only for showcase/marketing pages

RULE: always start with Layer 1. Only escalate to Layer 2 when shadcn/ui components cannot express the design. RULE: Layer 3 requires human approval before engaging external designer.


DESIGN_MD_STRUCTURE

COMPLETE_TEMPLATE

# DESIGN.md — {Project Name}

## Design System Configuration

### Brand Identity
- Primary color: oklch(0.65 0.15 250)
- Primary foreground: oklch(0.98 0 0)
- Secondary color: oklch(0.95 0.02 250)
- Accent color: oklch(0.65 0.18 30)
- Destructive color: oklch(0.55 0.22 25)
- Background: oklch(1 0 0)
- Foreground: oklch(0.14 0 0)
- Muted: oklch(0.96 0.005 250)
- Muted foreground: oklch(0.55 0.01 250)
- Border: oklch(0.91 0.005 250)
- Ring: oklch(0.65 0.15 250)

### Dark Mode (if applicable)
- Background: oklch(0.14 0.005 250)
- Foreground: oklch(0.98 0 0)
- Primary: oklch(0.75 0.12 250)
- (mirror all light mode tokens with dark variants)

### Typography
- Font family: "Inter", system-ui, sans-serif
- Font size scale: 0.75rem, 0.875rem, 1rem, 1.125rem, 1.25rem, 1.5rem, 2rem, 3rem
- Font weight: 400 (body), 500 (labels), 600 (headings), 700 (emphasis)
- Line height: 1.5 (body), 1.25 (headings), 1.75 (relaxed/readable)
- Letter spacing: -0.01em (headings), 0 (body), 0.05em (uppercase labels)

### Spacing Scale
- 0.25rem (4px): tight spacing, icon gaps
- 0.5rem (8px): compact element spacing
- 0.75rem (12px): form field padding
- 1rem (16px): standard component padding
- 1.5rem (24px): card padding, section gaps
- 2rem (32px): section spacing
- 3rem (48px): page section spacing
- 4rem (64px): major section spacing

### Border Radius
- Small: 0.375rem (buttons, inputs, badges)
- Medium: 0.5rem (cards, dialogs)
- Large: 0.75rem (larger containers)
- Full: 9999px (avatars, circular elements)

### Shadows
- Small: 0 1px 2px oklch(0 0 0 / 0.05)
- Medium: 0 4px 6px oklch(0 0 0 / 0.07)
- Large: 0 10px 15px oklch(0 0 0 / 0.1)

---

## Screen Specifications

### Screen: {screen_name}
- Route: /path/to/screen
- Auth: required | public
- Roles: admin, staff | all
- Layout: sidebar | full-width | centered
- Source: REQ-{nnn}-{nnn}

#### Components:
- PageHeader: title="{Screen Title}", breadcrumbs=[{path}]
- DataTable: columns=[{col_specs}], pagination=true, pageSize=20
- Button(primary): "Create New", icon=Plus, onClick=navigate(/new)
- EmptyState: icon=Inbox, title="No items yet", action="Create your first"
- Dialog: trigger=Button, title="Confirm Delete", variant=destructive

#### Responsive Behavior:
- Desktop (>=1024px): sidebar visible, table with all columns
- Tablet (768-1023px): sidebar collapsible, table hides low-priority columns
- Mobile (<768px): no sidebar (bottom nav), card layout replaces table

#### States:
- Loading: Skeleton placeholders matching layout
- Empty: EmptyState component centered
- Error: Alert variant=destructive with retry button
- Populated: Standard layout with data

SHADCN_UI_COMPONENT_SELECTION

COMPONENT_CATALOG_FOR_GE_PROJECTS

Alexander selects from the shadcn/ui catalog. These are the standard components used across all GE projects:

LAYOUT:
- Card: content containers, dashboard widgets
- Separator: visual dividers
- Sheet: slide-out panels (mobile nav, detail views)
- Tabs: content organization within a page
- Collapsible: expandable sections
- Resizable: split-pane layouts

NAVIGATION:
- Sidebar: app navigation (shadcn/ui sidebar component)
- Breadcrumb: page hierarchy
- NavigationMenu: top-level nav (marketing pages)
- Pagination: data table pagination
- Command: command palette (Cmd+K)

DATA DISPLAY:
- Table: data tables with sorting and filtering
- Badge: status indicators, tags
- Avatar: user profiles
- HoverCard: preview on hover
- Tooltip: helper text
- Accordion: FAQ, grouped information

FORMS:
- Input: text input fields
- Textarea: multi-line text
- Select: dropdown selection
- Checkbox: boolean/multi-select
- RadioGroup: single selection from options
- Switch: toggle on/off
- Slider: range selection
- DatePicker: date selection (with calendar)
- Combobox: searchable select
- Form: react-hook-form integration wrapper

FEEDBACK:
- Button: actions (primary, secondary, destructive, outline, ghost)
- Alert: informational banners
- AlertDialog: confirmation dialogs
- Dialog: modal windows
- Toast / Sonner: transient notifications
- Progress: loading/progress indication
- Skeleton: loading placeholders

OVERLAY:
- DropdownMenu: context menus, action menus
- ContextMenu: right-click menus
- Popover: floating content
- Drawer: bottom sheet (mobile)

COMPONENT_SELECTION_RULES

RULE: use shadcn/ui components for everything. Do not create custom components unless no shadcn/ui component fits. RULE: if a custom component is needed, it must be built from shadcn/ui primitives (Radix UI under the hood). RULE: never use a different UI library alongside shadcn/ui. No Material UI, no Ant Design, no Chakra. RULE: component variants (size, color) come from design tokens, not inline styles.

SELECTION_DECISION_MATRIX

| UI Need                    | Component          | Notes                              |
|----------------------------|--------------------|------------------------------------|
| List of records            | Table              | Always with pagination             |
| Record detail view         | Card + form fields | Read-only fields or editable form  |
| Create/edit form           | Form + inputs      | react-hook-form + Zod validation   |
| Confirmation               | AlertDialog        | For destructive actions            |
| Settings/config            | Tabs + form        | Tabs for sections, forms for input |
| Search                     | Command            | Cmd+K global search                |
| Status display             | Badge              | Colored by status                  |
| Notifications              | Sonner (toast)     | Bottom-right, auto-dismiss         |
| Navigation                 | Sidebar            | Collapsible, with icons            |
| Filters                    | Select/Combobox    | Above table, inline                |
| Date selection             | DatePicker         | Calendar popup                     |
| Boolean toggle             | Switch             | Not checkbox (Switch is clearer)   |
| Multi-select               | Checkbox group     | Vertical list                      |
| File upload                | Custom (dropzone)  | Built from Input + drag events     |
| Rich text                  | Custom (tiptap)    | Only when needed, adds complexity  |

DESIGN_TOKEN_IMPLEMENTATION

CSS_VARIABLES_IN_TAILWIND_V4

All design tokens from DESIGN.md translate to CSS variables in globals.css:

/* styles/globals.css */
@import "tailwindcss";
@import "tw-animate-css";

@theme inline {
  /* From DESIGN.md Brand Identity */
  --color-background: oklch(1 0 0);
  --color-foreground: oklch(0.14 0 0);
  --color-primary: oklch(0.65 0.15 250);
  --color-primary-foreground: oklch(0.98 0 0);
  --color-secondary: oklch(0.95 0.02 250);
  --color-secondary-foreground: oklch(0.14 0 0);
  --color-accent: oklch(0.65 0.18 30);
  --color-accent-foreground: oklch(0.98 0 0);
  --color-destructive: oklch(0.55 0.22 25);
  --color-destructive-foreground: oklch(0.98 0 0);
  --color-muted: oklch(0.96 0.005 250);
  --color-muted-foreground: oklch(0.55 0.01 250);
  --color-border: oklch(0.91 0.005 250);
  --color-ring: oklch(0.65 0.15 250);

  /* From DESIGN.md Typography */
  --font-sans: "Inter", system-ui, sans-serif;

  /* From DESIGN.md Border Radius */
  --radius-sm: 0.375rem;
  --radius-md: 0.5rem;
  --radius-lg: 0.75rem;

  /* From DESIGN.md Shadows */
  --shadow-sm: 0 1px 2px oklch(0 0 0 / 0.05);
  --shadow-md: 0 4px 6px oklch(0 0 0 / 0.07);
  --shadow-lg: 0 10px 15px oklch(0 0 0 / 0.1);
}

/* Dark mode */
.dark {
  --color-background: oklch(0.14 0.005 250);
  --color-foreground: oklch(0.98 0 0);
  /* ... mirror all tokens ... */
}

TOKEN_TO_USAGE_MAPPING

| DESIGN.md Token     | CSS Variable            | Tailwind Usage           |
|---------------------|-------------------------|--------------------------|
| Primary color       | --color-primary         | bg-primary text-primary  |
| Background          | --color-background      | bg-background            |
| Border              | --color-border          | border-border            |
| Border radius (sm)  | --radius-sm             | rounded-sm               |
| Shadow (md)         | --shadow-md             | shadow-md                |
| Font family         | --font-sans             | font-sans                |

RESPONSIVE_DESIGN_PATTERNS

BREAKPOINT_STRATEGY

MOBILE FIRST: all styles apply to mobile by default.
Breakpoints add complexity for larger screens.

sm: 640px   — large phones, landscape
md: 768px   — tablets
lg: 1024px  — small desktops, landscape tablets
xl: 1280px  — standard desktops
2xl: 1536px — large desktops

STANDARD_RESPONSIVE_PATTERNS

PATTERN_1: STACK_TO_GRID - Mobile: single column, components stacked vertically - Desktop: multi-column grid layout - Implementation: grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4

PATTERN_2: TABLE_TO_CARDS - Mobile: each row becomes a card with key-value pairs - Desktop: standard table with columns - Implementation: hide table on mobile, show card list. Hide cards on desktop.

PATTERN_3: SIDEBAR_COLLAPSE - Mobile: no sidebar, bottom navigation bar - Tablet: collapsible sidebar (hamburger trigger) - Desktop: persistent sidebar - Implementation: shadcn/ui Sidebar with collapsible="icon" on tablet

PATTERN_4: DIALOG_TO_PAGE - Mobile: full-screen page for create/edit (better UX) - Desktop: dialog/modal for create/edit - Implementation: check viewport, render Sheet (mobile) or Dialog (desktop)

TOUCH_TARGET_RULES

RULE: minimum touch target size is 44x44px (Apple HIG) / 48x48px (Material Design). RULE: GE standard: 44px minimum, 48px preferred. RULE: buttons, links, and interactive elements must meet this minimum. RULE: spacing between touch targets must be at least 8px to prevent mis-taps.


ACCESSIBILITY_IN_DESIGN

COLOR_AND_CONTRAST

RULE: text on background must meet WCAG 2.1 AA contrast ratio. - Normal text (< 18px): 4.5:1 minimum - Large text (>= 18px bold or >= 24px): 3:1 minimum - Non-text elements (icons, borders): 3:1 minimum

TOOL: use oklch color space for perceptual uniformity. Adjust lightness channel for contrast.

VERIFICATION:

CHECK: primary text on background → oklch(0.14) on oklch(1) = 18.5:1 ✓
CHECK: muted text on background → oklch(0.55) on oklch(1) = 5.2:1 ✓
CHECK: primary button text → oklch(0.98) on oklch(0.65) = 4.6:1 ✓

FOCUS_INDICATORS

RULE: every interactive element must have a visible focus indicator. RULE: focus indicator must have 3:1 contrast against adjacent colors. RULE: shadcn/ui provides default focus-visible rings — do not override them to be less visible.

/* Default focus ring from shadcn/ui — preserve this */
focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2

MOTION_AND_ANIMATION

RULE: all animations must respect prefers-reduced-motion. RULE: no animation should exceed 500ms duration. RULE: essential information must never be conveyed only through animation.

@media (prefers-reduced-motion: reduce) {
  * {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

SEMANTIC_HTML

RULE: shadcn/ui components are built on Radix UI, which provides correct ARIA attributes. RULE: Alexander must specify semantic structure in DESIGN.md: - Page title → <h1> - Section titles → <h2>, <h3> - Navigation → <nav> with aria-label - Main content → <main> - Form fields → <label> associated with input via htmlFor - Tables → <table> with <thead>, <tbody>, <th scope> - Lists → <ul> or <ol> (not <div> with visual bullets)


STITCH_MCP_INTEGRATION

WHEN_TO_USE_STITCH

USE_STITCH: custom layouts not achievable with standard shadcn/ui composition USE_STITCH: marketing/landing pages with unique visual treatment USE_STITCH: complex dashboard layouts with custom widget arrangements USE_STITCH: when client needs to see a visual mockup before approving design

DO_NOT_USE_STITCH: standard CRUD screens (table, form, detail view) DO_NOT_USE_STITCH: settings pages DO_NOT_USE_STITCH: login/register pages (standard patterns)

STITCH_WORKFLOW

STEP 1: Alexander writes text description of the screen
         "A dashboard with 4 KPI cards at top, a line chart showing revenue
          over time on the left, a recent orders table on the right,
          and a notification panel at the bottom"

STEP 2: Alexander invokes Stitch MCP to generate the UI
         Stitch returns HTML/CSS + screenshot

STEP 3: Human (Dirk-Jan) reviews the visual output
         Approves or requests changes

STEP 4: Alexander extracts component structure from Stitch output
         Maps to shadcn/ui equivalents where possible
         Documents custom components needed

STEP 5: DESIGN.md updated with screen spec from Stitch output
         Component tree, layout grid, responsive behavior

STITCH_MCP_USAGE

// Alexander's interaction with Stitch via MCP
// Tool: stitch_generate_ui
{
  prompt: "A responsive order management dashboard with...",
  style: "clean, professional, uses Inter font",
  framework: "react",
  component_library: "shadcn/ui"
}

RULE: always specify shadcn/ui as the component library in Stitch prompts. RULE: always specify the design tokens (colors, fonts) so Stitch output matches DESIGN.md. RULE: Stitch output is a starting point, not the final spec. Alexander maps it to GE conventions.


DESIGN_HANDOFF_TO_DEVELOPERS

WHAT_DEVELOPERS_RECEIVE

  1. DESIGN.md — complete design specification
  2. globals.css — design tokens as CSS variables (if Alexander generates it)
  3. Screen specifications — component tree per screen
  4. Responsive behavior — breakpoint-specific layout changes
  5. State specifications — loading, empty, error, populated states per screen

WHAT_DEVELOPERS_DO_NOT_RECEIVE

  • Figma files (agents cannot interpret them)
  • Screenshots (except as reference for Stitch Layer 2 screens)
  • Subjective guidance ("make it look nice")
  • Unspecified spacing ("add some padding")

HANDOFF_CHECKLIST

[ ] DESIGN.md has all design tokens defined
[ ] Every screen from Anna's spec has a screen specification
[ ] Every screen spec lists exact shadcn/ui components
[ ] Every screen has responsive behavior defined for mobile/tablet/desktop
[ ] Every screen has loading/empty/error/populated states defined
[ ] Color contrast verified for all text/background combinations
[ ] Touch targets verified (>= 44px)
[ ] Dark mode tokens defined (if project requires it)
[ ] globals.css template provided with CSS variables

DESIGN_REVIEW_BY_FELICE

After development, Felice (Visual Asset Producer) reviews the implemented UI against DESIGN.md:

FELICE_CHECKS: - Design tokens correctly applied (colors match, spacing matches) - Component selection matches DESIGN.md specification - Responsive behavior works across breakpoints - Accessibility requirements met (contrast, focus, screen reader) - Visual consistency across all screens - State handling (loading, empty, error) implemented

FELICE_OUTPUT: list of deviations from DESIGN.md, categorized as: - BLOCKER: breaks usability or accessibility (must fix) - SHOULD_FIX: noticeable deviation from design intent (should fix) - NITPICK: minor visual imperfection (nice to fix)