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
This commit is contained in:
470
DSS_PRINCIPLES.md
Normal file
470
DSS_PRINCIPLES.md
Normal file
@@ -0,0 +1,470 @@
|
||||
# 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:**
|
||||
```json
|
||||
{
|
||||
"$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
|
||||
|
||||
```typescript
|
||||
// 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
|
||||
|
||||
```python
|
||||
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
|
||||
|
||||
```json
|
||||
{
|
||||
"$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
|
||||
|
||||
```json
|
||||
{
|
||||
"$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
|
||||
|
||||
```json
|
||||
{
|
||||
"$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 |
|
||||
Reference in New Issue
Block a user