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
18 KiB
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:
- Never modify DSS core - The canonical structure stays intact
- Add to project's custom namespace -
color.brand.{client}.* - Create Storybook template for custom case - Shows variant without polluting core
- 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 |