Skip to content

Introducing Real Design System

One of the most common AI code generation failures is component duplication - AI creates new UI components instead of reusing existing ones. This happens because existing components are scattered, undocumented, and inconsistently named. A real design system solves this by providing a single source of truth for UI components.

Key Insight: AI cannot "discover" unorganized components. If components aren't in expected locations with clear documentation, they effectively don't exist to AI.

Problem Statement

Current State: Component Chaos

Evidence from Team Feedback

TeamIssueImpact
AndroidUI components scattered, no unified managementAI reimplements existing components
Web28,476 LOC in models directory, 60+ service classesAI context window exceeded
iOSNo component mapping in design-specAI doesn't know which components to use
AllDesign tokens not systematizedAI hardcodes style values

Real Examples

Android Team:

"UI components in the Android project mostly haven't been systematically organized. When AI was implementing Floor Plan, it would implement UI itself first, creating more duplicate code."

Web Team:

"DeviceFactory.js (232 lines) defines service mappings that create devices with dynamically composed services... AI context window cannot contain full service mapping context."

Proposal: Unified Design System

Target State

Design System Architecture

design-system/
├── README.md                    # Design system overview & AI guidelines
├── COMPONENT_INDEX.md           # Searchable component directory

├── tokens/
│   ├── colors.md               # Color palette definitions
│   ├── typography.md           # Font styles and sizes
│   ├── spacing.md              # Spacing scale
│   ├── shadows.md              # Shadow definitions
│   └── breakpoints.md          # Responsive breakpoints

├── foundations/
│   ├── grid.md                 # Layout grid system
│   ├── icons.md                # Icon library and usage
│   └── motion.md               # Animation guidelines

├── components/
│   ├── buttons/
│   │   ├── README.md           # Button variants and usage
│   │   ├── Button.vue          # Web implementation
│   │   ├── Button.swift        # iOS implementation
│   │   └── Button.kt           # Android implementation
│   │
│   ├── cards/
│   │   ├── README.md
│   │   ├── DeviceCard.vue
│   │   ├── DeviceCard.swift
│   │   └── DeviceCard.kt
│   │
│   ├── lists/
│   │   ├── README.md
│   │   ├── DeviceList.vue
│   │   ├── SiteList.vue
│   │   └── ...
│   │
│   └── forms/
│       ├── README.md
│       ├── Input.vue
│       ├── Select.vue
│       └── ...

├── patterns/
│   ├── error-handling.md       # Error display patterns
│   ├── loading-states.md       # Loading indicator patterns
│   ├── empty-states.md         # Empty state designs
│   └── navigation.md           # Navigation patterns

└── cross-platform/
    └── component-mapping.md    # Cross-platform equivalents

Component Documentation Standard

Component README Template

markdown
# DeviceCard

A card component for displaying device information with status indicators.

## Preview

[Screenshot or Figma link]

## Usage

### When to Use
- Displaying individual device in a list
- Device detail summary
- Device selection interfaces

### When NOT to Use
- Simple text-only device references (use DeviceLabel)
- Compact list views (use DeviceListItem)

## Variants

| Variant | Use Case | Props |
|---------|----------|-------|
| `default` | Standard device display | `device`, `onClick` |
| `compact` | Space-constrained views | `device`, `hideStatus` |
| `selectable` | Multi-select interfaces | `device`, `selected`, `onSelect` |

## Props

| Prop | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| `device` | `Device` | Yes | - | Device object to display |
| `onClick` | `Function` | No | - | Click handler |
| `variant` | `'default' \| 'compact' \| 'selectable'` | No | `'default'` | Visual variant |

## Platform Implementations

| Platform | File | Notes |
|----------|------|-------|
| Web | `components/DeviceCard.vue` | Uses Tailwind CSS |
| iOS | `Components/DeviceCard.swift` | SwiftUI implementation |
| Android | `ui/components/DeviceCard.kt` | Jetpack Compose |

## Examples

### Web (Vue)
```vue
<DeviceCard
  :device="camera"
  variant="default"
  @click="handleDeviceClick"
/>

iOS (SwiftUI)

swift
DeviceCard(device: camera, variant: .default) {
    handleDeviceClick()
}

Android (Compose)

kotlin
DeviceCard(
    device = camera,
    variant = DeviceCardVariant.Default,
    onClick = { handleDeviceClick() }
)

AI Guidelines

@ai-hint When displaying a device, use this component. Do not implement custom device cards. @ai-hint For lists of devices, combine with DeviceList component. @see DeviceList for displaying multiple devices @see DeviceListItem for compact list rows



## Cross-Platform Component Mapping

### Component Mapping Table

```markdown
# Cross-Platform Component Mapping

This table maps design system components to their platform-specific implementations.

| Component | Web | iOS | Android | Notes |
|-----------|-----|-----|---------|-------|
| **Navigation** |
| TabBar | `TabBar.vue` | `TabView` | `BottomNavigation` | Platform-native |
| NavHeader | `NavHeader.vue` | `NavigationBar` | `TopAppBar` | Custom styling |
| **Content** |
| DeviceCard | `DeviceCard.vue` | `DeviceCard.swift` | `DeviceCard.kt` | Unified design |
| DeviceList | `DeviceList.vue` | `DeviceListView.swift` | `DeviceListComposable.kt` | Virtual scrolling |
| SiteCard | `SiteCard.vue` | `SiteCard.swift` | `SiteCard.kt` | Unified design |
| **Forms** |
| Input | `Input.vue` | `TextField` | `OutlinedTextField` | Platform-native base |
| Select | `Select.vue` | `Picker` | `DropdownMenu` | Custom styling |
| Button | `Button.vue` | `Button.swift` | `Button.kt` | Design system |
| **Feedback** |
| Toast | `Toast.vue` | `Toast.swift` | `Snackbar` | Platform conventions |
| LoadingSpinner | `Loading.vue` | `ProgressView` | `CircularProgressIndicator` | Consistent timing |
| ErrorState | `ErrorState.vue` | `ErrorView.swift` | `ErrorComposable.kt` | Unified messaging |

## AI Usage

When implementing features across platforms:

1. Check this mapping first
2. Use existing components before creating new ones
3. If creating new component, add to this mapping
4. Ensure consistent props/parameters across platforms

Design Tokens

Token Documentation Format

markdown
# Colors

## Semantic Colors

Use semantic colors for UI elements. Never use raw color values.

| Token | Light Mode | Dark Mode | Usage |
|-------|------------|-----------|-------|
| `--color-primary` | `#0066CC` | `#4D9FFF` | Primary actions, links |
| `--color-secondary` | `#6B7280` | `#9CA3AF` | Secondary text, icons |
| `--color-success` | `#10B981` | `#34D399` | Success states |
| `--color-warning` | `#F59E0B` | `#FBBF24` | Warning states |
| `--color-error` | `#EF4444` | `#F87171` | Error states |
| `--color-background` | `#FFFFFF` | `#1F2937` | Page background |
| `--color-surface` | `#F9FAFB` | `#374151` | Card backgrounds |

## Device Status Colors

| Token | Value | Usage |
|-------|-------|-------|
| `--device-online` | `#10B981` | Online device indicator |
| `--device-offline` | `#6B7280` | Offline device indicator |
| `--device-error` | `#EF4444` | Device error state |
| `--device-recording` | `#EF4444` | Recording indicator |

## AI Guidelines

@ai-hint Always use semantic tokens, never hardcode colors.
@ai-hint For device status, use the device status color tokens.
@ai-hint Check dark mode compatibility for all color usage.

Implementation Roadmap

Phase 1: Inventory (Week 1-2)

Goal: Document existing components across all platforms.

Deliverables:

  • [ ] List of all existing UI components per platform
  • [ ] Duplicate component identification
  • [ ] Initial cross-platform mapping table

Phase 2: Foundation (Week 3-4)

Goal: Establish design tokens and core components.

Deliverables:

  • [ ] Design tokens defined (colors, typography, spacing)
  • [ ] 5 core components documented (Button, Input, Card, List, Modal)
  • [ ] Component README template established
  • [ ] COMPONENT_INDEX.md created

Phase 3: Migration (Week 5-8)

Goal: Consolidate existing components into design system.

Deliverables:

  • [ ] Move shared components to design system directory
  • [ ] Update imports across codebase
  • [ ] Add deprecation notices to old component locations
  • [ ] Update CLAUDE.md with design system guidelines

Phase 4: AI Integration (Week 9-10)

Goal: Ensure AI consistently uses design system.

Deliverables:

  • [ ] Add AI hints to all component documentation
  • [ ] Create design system search guidelines in CLAUDE.md
  • [ ] Test AI component generation accuracy
  • [ ] Iterate on documentation based on AI behavior

CLAUDE.md Integration

Add to project CLAUDE.md:

markdown
## Design System

### Component Usage
- **Always check** `design-system/COMPONENT_INDEX.md` before creating new components
- **Use existing components** from `design-system/components/`
- **Follow patterns** from `design-system/patterns/`

### Search Strategy
When looking for UI components:
1. First search in `design-system/components/`
2. Check `COMPONENT_INDEX.md` for component names
3. Only create new component if nothing exists

### Prohibited
- Creating new components without checking design system
- Hardcoding colors (use tokens from `design-system/tokens/`)
- Duplicating existing component functionality
- Using platform-native components when design system equivalent exists

### Adding New Components
If a new component is needed:
1. Create in `design-system/components/[category]/`
2. Follow README template
3. Add to COMPONENT_INDEX.md
4. Create implementations for all platforms

Success Metrics

MetricBeforeTargetHow to Measure
Component duplicationHighNear zeroAudit for similar components
AI component reuse rate~40%>90%Track AI-generated PRs
Time to find componentMinutesSecondsDeveloper survey
Cross-platform consistencyLowHighVisual comparison audit
Design token adoptionPartial100%grep for hardcoded values

Anti-Patterns to Avoid

1. Design System as Afterthought

Problem: Creating design system documentation but not enforcing usage.

Solution: Add pre-commit checks for component usage, integrate with PR reviews.

2. Platform-First Thinking

Problem: Each platform creates components independently, then tries to map.

Solution: Design components platform-agnostic first, then create platform implementations.

3. Over-Engineering

Problem: Creating complex component APIs that AI can't understand.

Solution: Simple, consistent prop interfaces. Prefer composition over configuration.

4. Stale Documentation

Problem: Component documentation doesn't match implementation.

Solution: Generate documentation from code where possible. Regular audits.

Reference Implementation: @vivotek/design-tokens

An existing implementation demonstrates these principles in practice. The @vivotek/design-tokens package provides a real-world example of how to build a design token system that supports both AI comprehension and cross-platform consistency.

Key Implementation Features

W3C DTCG Compliance

Tokens follow the W3C Design Tokens Community Group specification:

json
{
  "colors": {
    "$type": "color",
    "$description": "VIVOTEK brand color tokens - primitive color scales",
    "primary": {
      "base": {
        "$value": "#006bd6",
        "$description": "Primary color - darkened from brand 500 to meet WCAG AA contrast"
      },
      "foreground": {
        "$value": "{colors.white}",
        "$description": "Text color on primary background"
      }
    }
  }
}

The $description property provides human and AI-readable context, while $value with reference syntax ({colors.white}) enables token aliasing.

Multi-Format Output

Using Style Dictionary v5, the same token source generates:

Output FormatUse CaseFile
CSS Custom PropertiesWeb applicationstokens.css
TypeScript/JavaScriptProgrammatic accessindex.ts
Tailwind CSS PresetUtility-first CSStailwind-preset.js
iOS SwiftNative iOS appsDesignTokens.swift
Android ComposeJetpack ComposeColor.kt, Spacing.kt
Android XMLLegacy Androidcolors.xml, dimens.xml

Domain-Specific Semantic Colors

Beyond generic UI colors, the system includes domain-specific tokens for VSaaS features:

json
{
  "colors": {
    "status": {
      "online": { "base": "{colors.success.base}" },
      "offline": { "base": "{colors.secondary.base}" },
      "recording": { "base": "{colors.info.base}" },
      "error": { "base": "{colors.error.base}" }
    },
    "detection": {
      "motion": { "base": "{colors.info.base}" },
      "intrusion": { "base": "{colors.error.base}" },
      "loitering": { "base": "{colors.warning.base}" }
    },
    "analytics": {
      "human": { "base": "{colors.primary.base}" },
      "vehicle": { "base": "{colors.warning.base}" },
      "face": { "base": "{colors.primary.base}" }
    }
  }
}

This enables AI to understand domain semantics:

  • Device status colors map to operational states
  • Detection event colors indicate severity levels
  • Analytics colors distinguish object types

Theme Support

Light and dark themes use separate token files with the same structure:

tokens/vivotek/
├── colors.tokens.json           # Primitive colors
├── colors-light.tokens.json     # Light theme semantics
├── colors-dark.tokens.json      # Dark theme semantics
├── colors-domain-light.tokens.json
└── colors-domain-dark.tokens.json

Generated CSS automatically handles theme switching:

css
:root {
  --primary: #006bd6;
  --status-online: #22c55e;
}

.dark {
  --primary: #3d8fe8;
  --status-online: #4ade80;
}

Validation Pipeline

Automated validation ensures token quality:

bash
pnpm validate

# Validates:
# 1. DTCG Schema - All tokens have required properties
# 2. Token References - All aliases point to existing tokens
# 3. WCAG Contrast - Semantic color pairs meet AA standards (4.5:1)

This prevents accessibility regressions and ensures AI-generated code using these tokens will be compliant.

Lessons for AI Integration

  1. Descriptive Metadata: Every token includes $description for AI comprehension
  2. Consistent Structure: Predictable paths (colors.status.online.base) enable reliable code generation
  3. Reference-Based Aliases: Semantic tokens reference primitives, showing relationships
  4. Multi-Platform Parity: Same token names across all output formats reduce AI confusion
  5. Domain Vocabulary: Domain-specific color groups align with ubiquitous language

Related: shadcn/ui as Foundation | Back: Proposals Overview

References