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¶
- DESIGN.md — complete design specification
globals.css— design tokens as CSS variables (if Alexander generates it)- Screen specifications — component tree per screen
- Responsive behavior — breakpoint-specific layout changes
- 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)