Files
dss/DSS_PRINCIPLES.md
Digital Production Factory 276ed71f31 Initial commit: Clean DSS implementation
Migrated from design-system-swarm with fresh git history.
Old project history preserved in /home/overbits/apps/design-system-swarm

Core components:
- MCP Server (Python FastAPI with mcp 1.23.1)
- Claude Plugin (agents, commands, skills, strategies, hooks, core)
- DSS Backend (dss-mvp1 - token translation, Figma sync)
- Admin UI (Node.js/React)
- Server (Node.js/Express)
- Storybook integration (dss-mvp1/.storybook)

Self-contained configuration:
- All paths relative or use DSS_BASE_PATH=/home/overbits/dss
- PYTHONPATH configured for dss-mvp1 and dss-claude-plugin
- .env file with all configuration
- Claude plugin uses ${CLAUDE_PLUGIN_ROOT} for portability

Migration completed: $(date)
🤖 Clean migration with full functionality preserved
2025-12-09 18:45:48 -03:00

18 KiB

DSS Core Principles

1. Monolithic Design System Structure

DSS defines THE canonical design system structure. It does not change.

DSS Core Structure (Immutable)
├── tokens/
│   ├── colors/          # color.primary.500, color.neutral.100
│   ├── spacing/         # spacing.xs, spacing.sm, spacing.md
│   ├── typography/      # font.size.base, font.weight.bold
│   ├── borders/         # border.radius.sm, border.width.default
│   ├── shadows/         # shadow.sm, shadow.md, shadow.lg
│   └── motion/          # duration.fast, easing.default
├── components/
│   ├── Button/          # Canonical Button implementation
│   ├── Input/           # Canonical Input implementation
│   ├── Card/            # Canonical Card implementation
│   └── ...
└── patterns/
    ├── forms/
    ├── navigation/
    └── layouts/

This structure is sacred. External systems adapt to us, not the reverse.


2. Translation Dictionaries (Per-Project)

Each client project maintains a Translation Dictionary that maps their legacy tokens/styles to DSS canonical tokens.

project-acme/
├── .dss/
│   ├── config.json
│   └── translations/
│       ├── figma.json       # Figma → DSS mappings
│       ├── legacy-css.json  # Legacy CSS → DSS mappings
│       └── custom.json      # Custom props specific to ACME

Translation Dictionary Example:

{
  "$schema": "dss-translation-v1",
  "project": "acme-corp",
  "source": "legacy-css",
  "mappings": {
    "tokens": {
      "--brand-blue": "color.primary.500",
      "--brand-dark": "color.primary.700",
      "--text-main": "color.neutral.900",
      "$spacing-unit": "spacing.base",
      "var(--gap-small)": "spacing.sm"
    },
    "components": {
      ".btn-primary": "Button[variant=primary]",
      ".card-wrapper": "Card",
      ".input-field": "Input"
    }
  },
  "custom_props": {
    "color.brand.acme": "#1E40AF",
    "color.brand.acme.light": "#3B82F6"
  }
}

3. Custom Props Strategy

When a client needs something outside DSS core:

  1. Never modify DSS core - The canonical structure stays intact
  2. Add to project's custom namespace - color.brand.{client}.*
  3. Create Storybook template for custom case - Shows variant without polluting core
  4. Document in translation dictionary - Full traceability
DSS Core (immutable)     Client Custom (per-project)
─────────────────────    ─────────────────────────────
color.primary.500        color.brand.acme.primary
color.neutral.100        color.brand.acme.secondary
spacing.md               spacing.brand.acme.card-gap
Button                   Button + acme-specific props

4. Multi-System Ingestion Flow

┌─────────────────┐   ┌─────────────────┐   ┌─────────────────┐
│  Figma Tokens   │   │  Legacy CSS     │   │  Other MCP      │
│  (client-a)     │   │  (client-b)     │   │  (shadcn)       │
└────────┬────────┘   └────────┬────────┘   └────────┬────────┘
         │                     │                     │
         ▼                     ▼                     ▼
┌─────────────────────────────────────────────────────────────┐
│                    TRANSLATION LAYER                         │
│  • Map to DSS canonical tokens                              │
│  • Identify custom props (not in DSS)                       │
│  • Store mappings in project translation dictionary         │
└─────────────────────────────────────────────────────────────┘
         │
         ▼
┌─────────────────────────────────────────────────────────────┐
│                    DSS CORE (immutable)                      │
│  + Project Custom Props (isolated namespace)                │
└─────────────────────────────────────────────────────────────┘
         │
         ▼
┌─────────────────────────────────────────────────────────────┐
│                    OUTPUT                                    │
│  • Storybook with core + custom stories                     │
│  • Token files (CSS/SCSS/TS)                                │
│  • Component library                                         │
└─────────────────────────────────────────────────────────────┘

5. Storybook Strategy

  • Core Stories - All DSS canonical components (never modified)
  • Client Stories - Custom variations in isolated /stories/clients/{client}/
  • Template Stories - Edge cases, specific customizations
storybook/
├── core/
│   ├── Button.stories.tsx      # DSS canonical Button
│   ├── Card.stories.tsx        # DSS canonical Card
│   └── ...
├── clients/
│   ├── acme/
│   │   ├── Button.acme.stories.tsx   # ACME-specific Button variant
│   │   └── CustomWidget.stories.tsx  # ACME-only component
│   └── globex/
│       └── Button.globex.stories.tsx # Globex-specific Button variant
└── templates/
    ├── dark-mode.stories.tsx
    └── rtl-support.stories.tsx

6. Component Extension Model

// DSS Core Component (never changes)
interface ButtonProps {
  variant: 'primary' | 'secondary' | 'ghost';
  size: 'sm' | 'md' | 'lg';
  children: React.ReactNode;
  onClick?: () => void;
}

// Client Extension (in client's codebase, not DSS)
interface AcmeButtonProps extends ButtonProps {
  // ACME-specific props
  acmeIcon?: 'rocket' | 'star' | 'badge';
  acmeTracking?: string;
}

// Usage: Client wraps DSS component
const AcmeButton: React.FC<AcmeButtonProps> = ({ acmeIcon, acmeTracking, ...props }) => {
  return (
    <Button {...props} data-tracking={acmeTracking}>
      {acmeIcon && <AcmeIcon name={acmeIcon} />}
      {props.children}
    </Button>
  );
};

7. Token Merge System

DSS provides intelligent token merging from multiple sources with conflict resolution.

Merge Strategies

Strategy Behavior Use Case
FIRST Keep first occurrence Preserve original values
LAST Override with latest Latest source wins
PREFER_FIGMA Prioritize Figma source Design-led workflow
PREFER_CODE Prioritize CSS/SCSS Code-led workflow
PREFER_SPECIFIC Prefer concrete values over references Resolve var() references
MERGE_METADATA Combine metadata, use latest value Preserve history

Merge Flow

┌─────────────┐   ┌─────────────┐   ┌─────────────┐
│  Source A   │   │  Source B   │   │  Source C   │
│  (CSS)      │   │  (SCSS)     │   │  (Figma)    │
└──────┬──────┘   └──────┬──────┘   └──────┬──────┘
       │                 │                 │
       └────────────┬────┴────────────────┘
                    ▼
         ┌──────────────────────┐
         │    TOKEN MERGER      │
         │  • Detect conflicts  │
         │  • Apply strategy    │
         │  • Track resolution  │
         └──────────┬───────────┘
                    ▼
         ┌──────────────────────┐
         │   MERGE RESULT       │
         │  • Unified tokens    │
         │  • Conflict report   │
         │  • Resolution log    │
         └──────────────────────┘

Conflict Resolution Example

from tools.ingest import TokenMerger, MergeStrategy

# Merge with Figma priority
merger = TokenMerger(strategy=MergeStrategy.PREFER_FIGMA)
result = merger.merge([css_tokens, scss_tokens, figma_tokens])

# Check conflicts
for conflict in result.conflicts:
    print(f"{conflict.token_name}: {conflict.resolution}")
    print(f"  Kept: {conflict.resolved_token.value}")

8. UI Library Atomic Structure Comparison

Different UI libraries use fundamentally different atomic structures. DSS normalizes them all.

Comparison Table

Feature HeroUI shadcn Legacy CSS DSS Canonical
Color System Numeric scales (50-900) Semantic pairs Inconsistent Numeric scales
Granularity HIGH (10 shades) LOW (2 values) VARIES HIGH (10 shades)
Naming --heroui-primary-500 --primary --brand-blue color.primary.500
CSS Prefix heroui- None Various None (dot notation)
Theme Layers content1-4 card, popover, muted Random neutral.50-900
Spacing --heroui-spacing-unit None (Tailwind) --space-* spacing.xs-2xl
Radius --heroui-radius-{size} --radius Various radius.sm-full

Translation Patterns

HeroUI → DSS (Direct 1:1 mapping, strip prefix):

--heroui-primary-500     →  color.primary.500
--heroui-primary-600     →  color.primary.600
--heroui-content1        →  color.neutral.50
--heroui-content2        →  color.neutral.100
--heroui-radius-small    →  radius.sm
--heroui-radius-medium   →  radius.md
--heroui-shadow-small    →  shadow.sm

shadcn → DSS (Expand semantic to scale):

--primary                →  color.primary.500   (default value)
--primary-foreground     →  color.primary.50    (contrast)
--secondary              →  color.secondary.500
--muted                  →  color.neutral.200
--muted-foreground       →  color.neutral.600
--destructive            →  color.danger.500
--border                 →  color.neutral.200
--radius                 →  radius.md

Legacy CSS → DSS (Normalize chaos):

--brand-blue             →  color.primary.500
--brand-dark-blue        →  color.primary.700
--brandAccent            →  color.warning.500   (camelCase normalized)
--SPACING_LG             →  spacing.lg          (SCREAMING_CASE normalized)
--space-xs               →  spacing.xs
--spacing-md             →  spacing.md          (different prefix normalized)

Key Insight: Headless vs Full Design Systems

┌─────────────────────────────────────────────────────────────────────┐
│                    ATOMIC STRUCTURE TYPES                            │
├─────────────────────────────────────────────────────────────────────┤
│                                                                      │
│  FULL DESIGN SYSTEM (HeroUI)        HEADLESS (shadcn)               │
│  ─────────────────────────────      ─────────────────               │
│  • Complete color scales            • Semantic tokens only          │
│  • 10 shades per color              • 2 values (color + contrast)   │
│  • Ready-to-use values              • Expects Tailwind to fill      │
│  • Opinionated styling              • Minimal, composable           │
│                                                                      │
│  DSS APPROACH:                                                       │
│  • HeroUI: Direct mapping (strip prefix)                            │
│  • shadcn: Expand semantics to full scales                          │
│  • Both: Translate TO canonical structure                           │
│                                                                      │
└─────────────────────────────────────────────────────────────────────┘

9. Translation Dictionary Schema

Full Schema Definition

{
  "$schema": "dss-translation-v1",
  "project": "project-name",
  "source": "heroui | shadcn | css | scss | figma | tailwind",
  "version": "1.0.0",
  "created": "2025-01-15",
  "mappings": {
    "tokens": {
      "<source-token>": "<dss-canonical-token>"
    },
    "components": {
      "<source-component>": "<dss-component>[variant=value]"
    },
    "patterns": {
      "<source-pattern>": "<dss-pattern>"
    }
  },
  "custom_props": {
    "<dss-namespaced-token>": "<value>"
  },
  "unmapped": [
    "List of source tokens that couldn't be mapped"
  ],
  "notes": [
    "Human-readable notes about this translation"
  ]
}

Example: Complete HeroUI Translation

{
  "$schema": "dss-translation-v1",
  "project": "heroui-migration",
  "source": "heroui",
  "version": "1.0.0",
  "mappings": {
    "tokens": {
      "--heroui-primary-50": "color.primary.50",
      "--heroui-primary-100": "color.primary.100",
      "--heroui-primary-200": "color.primary.200",
      "--heroui-primary-300": "color.primary.300",
      "--heroui-primary-400": "color.primary.400",
      "--heroui-primary-500": "color.primary.500",
      "--heroui-primary-600": "color.primary.600",
      "--heroui-primary-700": "color.primary.700",
      "--heroui-primary-800": "color.primary.800",
      "--heroui-primary-900": "color.primary.900",
      "--heroui-content1": "color.neutral.50",
      "--heroui-content2": "color.neutral.100",
      "--heroui-content3": "color.neutral.200",
      "--heroui-content4": "color.neutral.300",
      "--heroui-radius-small": "radius.sm",
      "--heroui-radius-medium": "radius.md",
      "--heroui-radius-large": "radius.lg",
      "--heroui-shadow-small": "shadow.sm",
      "--heroui-shadow-medium": "shadow.md",
      "--heroui-shadow-large": "shadow.lg"
    },
    "components": {
      "Button": "Button",
      "Card": "Card",
      "Input": "Input",
      "Modal": "Modal",
      "Dropdown": "Select"
    }
  },
  "custom_props": {},
  "notes": [
    "HeroUI uses numeric scales - direct 1:1 mapping",
    "Content layers map to neutral scale",
    "Component APIs are similar, minimal translation needed"
  ]
}

Example: Complete shadcn Translation

{
  "$schema": "dss-translation-v1",
  "project": "shadcn-migration",
  "source": "shadcn",
  "version": "1.0.0",
  "mappings": {
    "tokens": {
      "--background": "color.neutral.50",
      "--foreground": "color.neutral.900",
      "--primary": "color.primary.500",
      "--primary-foreground": "color.primary.50",
      "--secondary": "color.secondary.500",
      "--secondary-foreground": "color.secondary.50",
      "--muted": "color.neutral.200",
      "--muted-foreground": "color.neutral.600",
      "--accent": "color.accent.500",
      "--accent-foreground": "color.accent.50",
      "--destructive": "color.danger.500",
      "--card": "color.neutral.50",
      "--card-foreground": "color.neutral.900",
      "--popover": "color.neutral.50",
      "--popover-foreground": "color.neutral.900",
      "--border": "color.neutral.200",
      "--input": "color.neutral.200",
      "--ring": "color.primary.500",
      "--radius": "radius.md"
    },
    "components": {
      "Button": "Button",
      "Card": "Card",
      "Input": "Input",
      "Dialog": "Modal",
      "Popover": "Popover",
      "Select": "Select",
      "Checkbox": "Checkbox",
      "RadioGroup": "RadioGroup"
    }
  },
  "custom_props": {
    "color.chart.1": "hsl(12 76% 61%)",
    "color.chart.2": "hsl(173 58% 39%)",
    "color.chart.3": "hsl(197 37% 24%)",
    "color.chart.4": "hsl(43 74% 66%)",
    "color.chart.5": "hsl(27 87% 67%)",
    "color.sidebar.primary": "var(--sidebar-primary)",
    "color.sidebar.accent": "var(--sidebar-accent)"
  },
  "notes": [
    "shadcn is HEADLESS - no numeric color scales",
    "Semantic names expand to 500 (default) DSS values",
    "foreground variants map to contrast colors (50)",
    "Chart colors are shadcn-specific, isolated in custom_props",
    "Sidebar colors are shadcn-specific, isolated in custom_props"
  ]
}

Summary

Principle Rule
Structure DSS core is monolithic and immutable
Translation Each project has translation dictionaries
Custom Props Isolated namespace, never pollute core
Storybook Core + client-specific stories separated
Components Clients extend/wrap, never modify core
Ingestion All external systems translate TO DSS
Merge Multiple strategies for conflict resolution
Atomic Structure Normalize all UI libraries to canonical format