Skip to content

DOMAIN:DESIGN:DESIGN_FOR_AGENTS

OWNER: alexander (Design System Engineer, shared) UPDATED: 2026-03-24 SCOPE: how design works in an agentic development context PREREQUISITE: design-system-engineering.md (DESIGN.md structure and component catalog) ALSO_RELEVANT_TO: floris (Team Alpha frontend), floor (Team Beta frontend), felice (visual QA)


PRINCIPLE: AGENTS_READ_SPECS_NOT_MOCKUPS

RULE: agents cannot see. They cannot interpret images, screenshots, or Figma files. RULE: every design decision must be expressed as structured text in DESIGN.md. RULE: if a design detail is not in DESIGN.md, it does not exist for the development agents. REASON: LLMs process text. A human developer can look at a Figma mockup and infer spacing, hierarchy, and intent. An agent needs explicit instructions: "Card padding is 1.5rem. Title is h3 with font-weight 600. Status badge uses variant 'secondary' for draft status."


DESIGN_MD_AS_MACHINE_READABLE_SPEC

WHY_DESIGN_MD_EXISTS

Traditional design handoff:

Designer → Figma → Developer (interprets visually) → Code

Agentic design handoff:

Alexander → DESIGN.md → Developer agent (reads spec) → Code

DESIGN.md replaces Figma, Sketch, Adobe XD, InVision, and Zeplin. It is: - Machine-readable (structured markdown that agents parse) - Version-controlled (in git, like code) - Diffable (changes are visible in PRs) - Composable (references shadcn/ui component names directly) - Self-contained (no external tools needed to read it)

DESIGN_MD_PARSING_BY_AGENTS

When a frontend agent (floris/floor) receives a WP, they:

STEP_1: read DESIGN.md to understand the design system (tokens, components) STEP_2: find the screen specification for the screen they are building STEP_3: implement the component tree exactly as specified STEP_4: apply design tokens via Tailwind CSS classes (not hardcoded values) STEP_5: implement responsive behavior per the breakpoint specifications STEP_6: implement all states (loading, empty, error, populated)

WHAT_AGENTS_NEED_FROM_DESIGN_MD

MUST HAVE (agent cannot build without it):
- Design token values (colors, spacing, typography, radii, shadows)
- Component selection per screen (which shadcn/ui components)
- Component configuration (props, variants, sizes)
- Layout structure (grid columns, flex direction, spacing between sections)
- Data binding (which API field maps to which UI element)

SHOULD HAVE (agent can build but result may be wrong):
- Responsive behavior per breakpoint
- State specifications (loading, empty, error)
- Interaction behavior (hover, focus, active states)
- Animation specifications (if any)

NICE TO HAVE (agent can infer from conventions):
- Icon selection (agent picks from Lucide catalog)
- Exact pixel measurements (agent uses spacing scale)
- Color shade selection (agent uses token names)

DESIGN_TOKEN_FORMAT_FOR_LLM_CONSUMPTION

OPTIMAL_FORMAT

Agents parse markdown. The format must be: - Flat (no deeply nested structures) - Named (every value has a semantic name) - Typed (agent knows if value is a color, size, or string) - Contextual (agent knows where to use each token)

TOKEN_SPECIFICATION_FORMAT

## Design Tokens

### Colors
| Token Name          | Value                   | Usage                              |
|---------------------|-------------------------|------------------------------------|
| primary             | oklch(0.65 0.15 250)   | Buttons, links, active states      |
| primary-foreground  | oklch(0.98 0 0)        | Text on primary backgrounds        |
| secondary           | oklch(0.95 0.02 250)   | Secondary buttons, hover states    |
| destructive         | oklch(0.55 0.22 25)    | Delete buttons, error states       |
| muted               | oklch(0.96 0.005 250)  | Disabled backgrounds, subtle areas |
| muted-foreground    | oklch(0.55 0.01 250)   | Placeholder text, labels           |
| border              | oklch(0.91 0.005 250)  | Input borders, card borders        |
| background          | oklch(1 0 0)           | Page background                    |
| foreground          | oklch(0.14 0 0)        | Body text                          |

### Typography
| Token Name    | Value                          | Usage                        |
|---------------|--------------------------------|------------------------------|
| font-sans     | "Inter", system-ui, sans-serif | All text                     |
| text-xs       | 0.75rem / 1rem                 | Captions, footnotes          |
| text-sm       | 0.875rem / 1.25rem             | Labels, table cells          |
| text-base     | 1rem / 1.5rem                  | Body text                    |
| text-lg       | 1.125rem / 1.75rem             | Sub-headings                 |
| text-xl       | 1.25rem / 1.75rem              | Section headings             |
| text-2xl      | 1.5rem / 2rem                  | Page headings                |
| text-3xl      | 2rem / 2.25rem                 | Hero headings                |

### Spacing
| Token  | Value   | Usage                                      |
|--------|---------|--------------------------------------------|
| 1      | 0.25rem | Icon-to-text gap, tight spacing             |
| 2      | 0.5rem  | Input padding-y, compact gaps               |
| 3      | 0.75rem | Input padding-x, form field gaps            |
| 4      | 1rem    | Card padding, standard component spacing    |
| 6      | 1.5rem  | Card padding (spacious), section gaps       |
| 8      | 2rem    | Section spacing                             |
| 12     | 3rem    | Page section spacing                        |
| 16     | 4rem    | Major section spacing, page margins         |

WHY_THIS_FORMAT_WORKS: - Agents can scan the table and find the right token by usage description - Token names match Tailwind classes directly (e.g., text-sm, p-4, bg-primary) - No ambiguity about when to use which value


COMPONENT_SELECTION_FROM_SHADCN_CATALOG

THE_SELECTION_PROCESS

Alexander reads Anna's spec and maps each UI need to a shadcn/ui component:

ANNA'S SPEC SAYS:                    ALEXANDER SELECTS:
"Paginated list of orders"       →   Table + Pagination
"Create order form"              →   Form + Input + Select + Button
"Order status indicator"         →   Badge (variant by status)
"Confirm before delete"          →   AlertDialog (destructive)
"Success notification"           →   Sonner toast
"Date range filter"              →   DatePicker (range mode)
"User profile dropdown"          →   DropdownMenu + Avatar
"Sidebar navigation"             →   Sidebar + SidebarMenu
"Search across all records"      →   Command (Cmd+K palette)
"Settings organized by topic"    →   Tabs + Form sections
"Expandable order details"       →   Collapsible or Accordion

COMPONENT_SPECIFICATION_FORMAT

Each screen in DESIGN.md specifies components with enough detail for an agent to implement:

### Screen: Order List (/orders)

#### Layout
- Sidebar (left, collapsible on mobile)
- Main content area with PageHeader + content

#### Component Tree
PageHeader ├── Breadcrumb: Home > Orders ├── title: "Orders" └── action: Button(variant="default", size="default") "New Order" icon=Plus

FilterBar (flex row, gap-2, mb-4) ├── Input(type="search", placeholder="Search orders...") ├── Select(placeholder="Status") options=[All, Draft, Submitted, InProgress, Completed] ├── DatePicker(mode="range", placeholder="Date range") └── Button(variant="outline", size="sm") "Clear filters"

DataTable ├── columns: │ ├── order_number: sortable, link to /orders/{id} │ ├── client_name: sortable │ ├── status: Badge component │ │ ├── draft → variant="secondary" │ │ ├── submitted → variant="default" │ │ ├── in_progress → variant="default" + blue custom │ │ ├── completed → variant="default" + green custom │ │ └── cancelled → variant="destructive" │ ├── total: right-aligned, formatted EUR │ ├── created_at: relative time ("2 hours ago") │ └── actions: DropdownMenu [View, Edit, Delete] ├── pagination: bottom, 20 rows per page ├── empty: EmptyState icon=Package title="No orders yet" │ description="Create your first order to get started" │ action=Button "New Order" └── loading: Skeleton rows matching column layout

#### Responsive
- Desktop: full table with all columns
- Tablet: hide created_at column, compact padding
- Mobile: card layout replacing table
  - Each card shows: order_number, client_name, status badge, total
  - Tap card → navigate to detail

WHEN_TO_USE_STITCH_VS_MANUAL

DECISION_FRAMEWORK

| Scenario                          | Approach        | Reason                              |
|-----------------------------------|-----------------|-------------------------------------|
| Standard CRUD list page           | Manual (L1)     | Table + Form = well-known pattern   |
| Standard form page                | Manual (L1)     | shadcn Form + inputs = sufficient   |
| Login/register page               | Manual (L1)     | Standard auth pattern               |
| Settings page                     | Manual (L1)     | Tabs + forms = well-known pattern   |
| Dashboard with KPI cards          | Manual (L1)     | Card grid = simple layout           |
| Dashboard with custom charts      | Stitch (L2)     | Chart layout is visual, needs help  |
| Landing/marketing page            | Stitch (L2)     | Creative layout, not standard CRUD  |
| Client-facing portal (branded)    | Stitch (L2)     | Client brand requires visual design |
| Complex wizard/multi-step flow    | Stitch (L2)     | Step visualization needs design     |
| Showcase page for GE itself       | External (L3)   | Brand-critical, needs human design  |

STITCH_PROMPT_ENGINEERING

When using Stitch MCP, Alexander writes prompts that constrain the output to GE conventions:

GOOD PROMPT:
"A professional order management dashboard using a clean, minimal style.
 4 KPI cards in a row at the top (total orders, pending, completed, revenue).
 Below, a 2-column layout: left column has a line chart showing orders over
 the last 30 days, right column has a table of 5 most recent orders.
 Use Inter font, blue primary color (#4A73E8), white background.
 Cards have subtle shadows and rounded corners.
 Responsive: stack to single column on mobile."

BAD PROMPT:
"Make a nice dashboard for orders"

PROMPT_RULES: - Specify layout (grid, columns, positioning) - Specify content (what data appears where) - Specify style constraints (font, colors, borders, shadows) - Specify responsive behavior - Do not specify implementation details (no React, no CSS class names)

POST_STITCH_WORKFLOW

After Stitch generates output:

STEP 1: Alexander reviews Stitch HTML/CSS output
STEP 2: Alexander maps Stitch components to shadcn/ui equivalents
         Stitch <div class="card"> → shadcn Card
         Stitch <table> → shadcn Table
         Stitch <button> → shadcn Button
STEP 3: Alexander adjusts design tokens to match project DESIGN.md
         Stitch colors → project oklch tokens
         Stitch font → project font-sans
STEP 4: Alexander writes screen spec in DESIGN.md
         Component tree, responsive behavior, states
STEP 5: Human (Dirk-Jan) reviews Stitch mockup + DESIGN.md spec
STEP 6: Developer agent implements from DESIGN.md (not from Stitch HTML)

CRITICAL: developers NEVER implement from Stitch HTML directly. Stitch output is reference material for Alexander. DESIGN.md is the implementation spec.


VISUAL_QA_BY_FELICE

FELICE_ROLE

Felice is the Visual Asset Producer. After development, Felice compares the implemented UI against DESIGN.md.

FELICE_CANNOT: see the running application (agents cannot view browsers). FELICE_CAN: read the source code and compare it against DESIGN.md specifications.

WHAT_FELICE_CHECKS

CODE-LEVEL VERIFICATION:
[ ] Tailwind classes use design token names (bg-primary not bg-blue-500)
[ ] Component selections match DESIGN.md (Table not custom <div> grid)
[ ] Spacing uses token scale (p-4 not p-[17px])
[ ] Typography uses token scale (text-sm not text-[13px])
[ ] Color usage matches token purpose (destructive for errors, not red-500)
[ ] Border radius uses token (rounded-md not rounded-[7px])
[ ] Dark mode tokens applied where specified

RESPONSIVE VERIFICATION:
[ ] Mobile-first classes present (base styles for mobile)
[ ] Breakpoint modifiers match DESIGN.md (md: for tablet, lg: for desktop)
[ ] Hidden elements at correct breakpoints (hidden md:block for desktop-only)
[ ] Touch targets >= 44px on mobile (h-11 w-11 minimum for interactive)

ACCESSIBILITY VERIFICATION:
[ ] Alt text on images
[ ] ARIA labels on icon-only buttons
[ ] Form labels associated with inputs (htmlFor matches id)
[ ] Heading hierarchy correct (h1 > h2 > h3, no skipping)
[ ] Focus-visible styles not suppressed
[ ] prefers-reduced-motion respected for animations

STATE VERIFICATION:
[ ] Loading state uses Skeleton components
[ ] Empty state uses EmptyState pattern
[ ] Error state uses Alert with retry
[ ] All states render without console errors

FELICE_OUTPUT_FORMAT

## Visual QA: {screen_name}

### Status: PASS | NEEDS_FIXES

### Findings

#### BLOCKER
- [ ] BUG: Button in header uses `bg-blue-500` instead of `bg-primary`
  File: components/orders/order-header.tsx:14
  Fix: replace `bg-blue-500` with `bg-primary`

#### SHOULD_FIX
- [ ] DEVIATION: Card padding is p-3 but DESIGN.md specifies p-6
  File: components/orders/order-card.tsx:8
  Fix: change `p-3` to `p-6`

#### NITPICK
- [ ] MINOR: Icon could be Package instead of Box (closer to DESIGN.md intent)
  File: components/orders/empty-state.tsx:5
  Suggestion: change `<Box>` to `<Package>`

DESIGN_SYSTEM_EVOLUTION

WHEN_THE_DESIGN_SYSTEM_CHANGES

TRIGGER_1: new project with different brand → new DESIGN.md, different tokens TRIGGER_2: shadcn/ui releases new component → Alexander evaluates for GE catalog TRIGGER_3: Stitch adds new capability → Alexander evaluates for Layer 2 workflow TRIGGER_4: accessibility standard updates → Alexander updates a11y requirements TRIGGER_5: Tailwind CSS update → Alexander updates token implementation

DESIGN_SYSTEM_VERSIONING

RULE: each project has its own DESIGN.md in the project repository. RULE: GE maintains a base DESIGN.md template with defaults. RULE: project DESIGN.md overrides base tokens for client branding. RULE: structural patterns (component selection, responsive strategy) are shared across projects.

BASE_DESIGN_MD_TEMPLATE

The base template lives in GE's wiki and is used as the starting point for every project:

# DESIGN.md — {Project Name} (base template)

## Design System: GE Default

### Brand Identity
- Override these tokens with client's brand colors
- Default: professional blue (#4A73E8) primary

### Component Library
- shadcn/ui (latest, Tailwind v4 compatible)
- Icons: Lucide React

### Layout Conventions
- Max content width: 1280px (7xl)
- Sidebar width: 256px (64)
- Page padding: 1.5rem (6) mobile, 2rem (8) desktop
- Content gap: 1.5rem (6)

### Form Conventions
- Labels above inputs (not inline)
- Required fields marked with asterisk
- Validation errors below input in text-destructive
- Submit button right-aligned
- Cancel button left of submit, variant="outline"

### Table Conventions
- Zebra striping off (clean look)
- Hover row highlight: bg-muted/50
- Pagination always visible
- Default page size: 20
- Sortable columns indicated with icon

### Dialog Conventions
- Max width: sm for confirmations, lg for forms
- Close button top-right
- Primary action right-aligned
- Destructive actions use AlertDialog, not Dialog

DESIGN_ANTI_PATTERNS_IN_AGENTIC_CONTEXT

ANTI_PATTERN_1: "Figma-first design" WHY_BAD: no agent can read a Figma file. Design work in Figma is wasted effort. INSTEAD: DESIGN.md first. Stitch for visual validation. Figma only if external designer (Layer 3).

ANTI_PATTERN_2: "Hardcoded colors and sizes" WHY_BAD: bg-blue-500 bypasses the design system. Changing the brand requires touching every file. INSTEAD: bg-primary. Always use design tokens.

ANTI_PATTERN_3: "Custom components when shadcn has one" WHY_BAD: custom components lack Radix UI accessibility, keyboard nav, and ARIA. More code to maintain. INSTEAD: use shadcn/ui. Customize via tokens and Tailwind classes, not by rewriting the component.

ANTI_PATTERN_4: "Design tokens in JavaScript" WHY_BAD: tokens in JS are not accessible to Tailwind's JIT compiler. Double source of truth. INSTEAD: tokens in CSS variables (globals.css). Tailwind reads them via @theme.

ANTI_PATTERN_5: "No empty/loading/error states in DESIGN.md" WHY_BAD: developer agent implements the happy path only. First API delay = broken UI. INSTEAD: every screen in DESIGN.md must specify all four states.

ANTI_PATTERN_6: "Pixel-perfect specs" WHY_BAD: agents do not measure pixels. They use spacing scale tokens. INSTEAD: use token names (p-4, gap-6, text-sm), not pixel values (16px, 24px, 13px).


INTEGRATION_WITH_GE_PIPELINE

DESIGN_IN_THE_PIPELINE

Aimee (scope) → Anna (spec) → ALEXANDER (design) → Faye/Sytske (WPs) → Devs → Felice (QA)
                                    ↑                                            ↑
                              DESIGN.md created                           DESIGN.md verified

TIMING

Alexander works AFTER Anna's formal spec is approved (Gate 4) and BEFORE Faye/Sytske create WPs (Phase 6).

REASON: Faye needs DESIGN.md to size frontend WPs correctly. A complex custom dashboard (Layer 2) takes more WPs than a standard CRUD screen (Layer 1).

DESIGN_WP_IN_THE_WP_SET

Faye/Sytske always include a design WP as the first frontend-related WP:

- id: WP-003
  title: "Create DESIGN.md and global theme tokens"
  lane: LANE_DESIGN
  assigned_to: alexander
  size: S (Layer 1 only) | M (Layer 1 + Layer 2 screens)
  depends_on: []  # Alexander reads Anna's spec, not other WPs
  spec_refs: []   # Design is cross-cutting, not tied to one REQ
  produces:
    - "DESIGN.md"
    - "styles/globals.css" (if project needs custom token setup)

RULE: the design WP has no dependencies (Alexander only needs Anna's spec, which passed the gate). RULE: all frontend WPs depend on the design WP (they need DESIGN.md to implement correctly). RULE: backend WPs do NOT depend on the design WP (APIs are design-agnostic).