Back to skills
SkillHub ClubDesign ProductFull StackFrontendData / AI

assembling-components

Assembles component outputs from AI Design Components skills into unified, production-ready component systems with validated token integration, proper import chains, and framework-specific scaffolding. Use as the capstone skill after running theming, layout, dashboard, data-viz, or feedback skills to wire components into working React/Next.js, Python, or Rust projects.

Packaged view

This page reorganizes the original catalog entry around fit, installability, and workflow context first. The original raw source lives below.

Stars
318
Hot score
99
Updated
March 20, 2026
Overall rating
C4.3
Composite score
4.3
Best-practice grade
C62.8

Install command

npx @skill-hub/cli install ancoleman-ai-design-components-assembling-components

Repository

ancoleman/ai-design-components

Skill path: skills/assembling-components

Assembles component outputs from AI Design Components skills into unified, production-ready component systems with validated token integration, proper import chains, and framework-specific scaffolding. Use as the capstone skill after running theming, layout, dashboard, data-viz, or feedback skills to wire components into working React/Next.js, Python, or Rust projects.

Open repository

Best for

Primary workflow: Design Product.

Technical facets: Full Stack, Frontend, Data / AI, Designer, Integration.

Target audience: everyone.

License: Unknown.

Original source

Catalog source: SkillHub Club.

Repository owner: ancoleman.

This is still a mirrored public skill entry. Review the repository before installing into production workflows.

What it helps with

  • Install assembling-components into Claude Code, Codex CLI, Gemini CLI, or OpenCode workflows
  • Review https://github.com/ancoleman/ai-design-components before adding assembling-components to shared team environments
  • Use assembling-components for development workflows

Works across

Claude CodeCodex CLIGemini CLIOpenCode

Favorites: 0.

Sub-skills: 0.

Aggregator: No.

Original source / Raw SKILL.md

---
name: assembling-components
description: Assembles component outputs from AI Design Components skills into unified, production-ready component systems with validated token integration, proper import chains, and framework-specific scaffolding. Use as the capstone skill after running theming, layout, dashboard, data-viz, or feedback skills to wire components into working React/Next.js, Python, or Rust projects.
---

# Assembling Components

## Purpose

This skill transforms the outputs of AI Design Components skills into production-ready applications. It provides library-specific context for our token system, component patterns, and skill chain workflow - knowledge that generic assembly patterns cannot provide. The skill validates token integration, generates proper scaffolding, and wires components together correctly.

## When to Use

Activate this skill when:
- Completing a skill chain workflow (theming → layout → dashboards → data-viz → feedback)
- Generating new project scaffolding for React/Vite, Next.js, FastAPI, Flask, or Rust/Axum
- Validating that all generated CSS uses design tokens (not hardcoded values)
- Creating barrel exports and wiring component imports correctly
- Assembling components from multiple skills into a unified application
- Debugging integration issues (missing entry points, broken imports, theme not switching)
- Preparing generated code for production deployment

## Skill Chain Context

This skill understands the output of every AI Design Components skill:

```
┌──────────────────┐     ┌──────────────────┐     ┌──────────────────┐
│ theming-         │────▶│ designing-       │────▶│ creating-        │
│ components       │     │ layouts          │     │ dashboards       │
└──────────────────┘     └──────────────────┘     └──────────────────┘
        │                        │                        │
        ▼                        ▼                        ▼
    tokens.css               Layout.tsx             Dashboard.tsx
    theme-provider.tsx       Header.tsx             KPICard.tsx
        │                        │                        │
        └────────────────────────┴────────────────────────┘
                                 │
                                 ▼
                    ┌──────────────────────┐
                    │ visualizing-data     │
                    │ providing-feedback   │
                    └──────────────────────┘
                                 │
                                 ▼
                         DonutChart.tsx
                         Toast.tsx, Spinner.tsx
                                 │
                                 ▼
                    ┌──────────────────────┐
                    │ ASSEMBLING-          │
                    │ COMPONENTS           │
                    │ (THIS SKILL)         │
                    └──────────────────────┘
                                 │
                                 ▼
                       WORKING COMPONENT SYSTEM
```

### Expected Outputs by Skill

| Skill | Primary Outputs | Token Dependencies |
|-------|-----------------|-------------------|
| `theming-components` | tokens.css, theme-provider.tsx | Foundation |
| `designing-layouts` | Layout.tsx, Header.tsx, Sidebar.tsx | --spacing-*, --color-border-* |
| `creating-dashboards` | Dashboard.tsx, KPICard.tsx | All layout + chart tokens |
| `visualizing-data` | Chart components, legends | --chart-color-*, --font-size-* |
| `building-forms` | Form inputs, validation | --spacing-*, --radius-*, --color-error |
| `building-tables` | Table, pagination | --color-*, --spacing-* |
| `providing-feedback` | Toast, Spinner, EmptyState | --color-success/error/warning |

## Token Validation

### Run Validation Script (Token-Free Execution)

```bash
# Basic validation
python scripts/validate_tokens.py src/styles

# Strict mode with fix suggestions
python scripts/validate_tokens.py src --strict --fix-suggestions

# JSON output for CI/CD
python scripts/validate_tokens.py src --json
```

### Our Token Naming Conventions

```css
/* Colors - semantic naming */
--color-primary: #FA582D;          /* Brand primary */
--color-success: #00CC66;          /* Positive states */
--color-warning: #FFCB06;          /* Caution states */
--color-error: #C84727;            /* Error states */
--color-info: #00C0E8;             /* Informational */

--color-bg-primary: #FFFFFF;       /* Main background */
--color-bg-secondary: #F8FAFC;     /* Elevated surfaces */
--color-text-primary: #1E293B;     /* Body text */
--color-text-secondary: #64748B;   /* Muted text */

/* Spacing - 4px base unit */
--spacing-xs: 0.25rem;   /* 4px */
--spacing-sm: 0.5rem;    /* 8px */
--spacing-md: 1rem;      /* 16px */
--spacing-lg: 1.5rem;    /* 24px */
--spacing-xl: 2rem;      /* 32px */

/* Typography */
--font-size-xs: 0.75rem;   /* 12px */
--font-size-sm: 0.875rem;  /* 14px */
--font-size-base: 1rem;    /* 16px */
--font-size-lg: 1.125rem;  /* 18px */

/* Component sizes */
--icon-size-sm: 1rem;      /* 16px */
--icon-size-md: 1.5rem;    /* 24px */
--radius-sm: 4px;
--radius-md: 8px;
--shadow-sm: 0 1px 2px rgba(0,0,0,0.05);
```

### Validation Rules

| Must Use Tokens (Errors) | Example Fix |
|--------------------------|-------------|
| Colors | `#FA582D` → `var(--color-primary)` |
| Spacing (≥4px) | `16px` → `var(--spacing-md)` |
| Font sizes | `14px` → `var(--font-size-sm)` |

| Should Use Tokens (Warnings) | Example Fix |
|------------------------------|-------------|
| Border radius | `8px` → `var(--radius-md)` |
| Shadows | `0 4px...` → `var(--shadow-md)` |
| Z-index (≥100) | `1000` → `var(--z-dropdown)` |

## Framework Selection

### React/TypeScript

**Choose Vite + React when:**
- Building single-page applications
- Lightweight, fast development builds
- Maximum control over configuration
- No server-side rendering needed

**Choose Next.js 14/15 when:**
- Need server-side rendering or static generation
- Building full-stack with API routes
- SEO is important
- Using React Server Components

### Python

**Choose FastAPI when:**
- Building modern async APIs
- Need automatic OpenAPI documentation
- High performance is required
- Using Pydantic for validation

**Choose Flask when:**
- Simpler, more flexible setup
- Familiar with Flask ecosystem
- Template rendering (Jinja2)
- Smaller applications

### Rust

**Choose Axum when:**
- Modern tower-based architecture
- Type-safe extractors
- Async-first design
- Growing ecosystem

**Choose Actix Web when:**
- Maximum performance required
- Actor model benefits your use case
- More mature ecosystem

## Implementation Approach

### 1. Validate Token Integration

Before assembly, check all CSS uses tokens:

```bash
python scripts/validate_tokens.py <component-directory>
```

Fix any violations before proceeding.

### 2. Generate Project Scaffolding

**React/Vite:**
```tsx
// src/main.tsx - Entry point
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import { ThemeProvider } from '@/context/theme-provider'
import App from './App'
import './styles/tokens.css'   // FIRST - token definitions
import './styles/globals.css'  // SECOND - global resets

createRoot(document.getElementById('root')!).render(
  <StrictMode>
    <ThemeProvider>
      <App />
    </ThemeProvider>
  </StrictMode>,
)
```

**index.html:**
```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>{{PROJECT_TITLE}}</title>
  </head>
  <body>
    <div id="root"></div>
    <script type="module" src="/src/main.tsx"></script>
  </body>
</html>
```

### 3. Wire Components Together

**Theme Provider:**
```tsx
// src/context/theme-provider.tsx
import { createContext, useContext, useEffect, useState } from 'react'

type Theme = 'light' | 'dark' | 'system'

const ThemeContext = createContext<{
  theme: Theme
  setTheme: (theme: Theme) => void
} | undefined>(undefined)

export function ThemeProvider({ children }: { children: React.ReactNode }) {
  const [theme, setTheme] = useState<Theme>('system')

  useEffect(() => {
    const root = document.documentElement
    const systemTheme = window.matchMedia('(prefers-color-scheme: dark)').matches
      ? 'dark' : 'light'
    root.setAttribute('data-theme', theme === 'system' ? systemTheme : theme)
    localStorage.setItem('theme', theme)
  }, [theme])

  return (
    <ThemeContext.Provider value={{ theme, setTheme }}>
      {children}
    </ThemeContext.Provider>
  )
}

export const useTheme = () => {
  const context = useContext(ThemeContext)
  if (!context) throw new Error('useTheme must be used within ThemeProvider')
  return context
}
```

**Barrel Exports:**
```tsx
// src/components/ui/index.ts
export { Button } from './button'
export { Card } from './card'

// src/components/features/dashboard/index.ts
export { KPICard } from './kpi-card'
export { DonutChart } from './donut-chart'
export { Dashboard } from './dashboard'
```

### 4. Configure Build System

**vite.config.ts:**
```typescript
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import path from 'path'

export default defineConfig({
  plugins: [react()],
  resolve: {
    alias: {
      '@': path.resolve(__dirname, './src'),
    },
  },
})
```

**tsconfig.json:**
```json
{
  "compilerOptions": {
    "target": "ES2020",
    "lib": ["ES2020", "DOM", "DOM.Iterable"],
    "module": "ESNext",
    "moduleResolution": "bundler",
    "jsx": "react-jsx",
    "strict": true,
    "baseUrl": ".",
    "paths": { "@/*": ["./src/*"] }
  },
  "include": ["src"]
}
```

## Cross-Skill Integration

### Using Theming Components

```tsx
// Import tokens first, components inherit token values
import './styles/tokens.css'

// Use ThemeProvider at root
<ThemeProvider>
  <App />
</ThemeProvider>
```

### Using Dashboard Components

```tsx
// Components from creating-dashboards skill
import { Dashboard, KPICard } from '@/components/features/dashboard'

// Wire with data
<Dashboard>
  <KPICard
    label="Total Threats"
    value={1234}
    severity="critical"
    trend={{ value: 15.3, direction: 'up' }}
  />
</Dashboard>
```

### Using Data Visualization

```tsx
// Charts from visualizing-data skill
import { DonutChart } from '@/components/charts'

// Charts use --chart-color-* tokens automatically
<DonutChart
  data={threatData}
  title="Threats by Severity"
/>
```

### Using Feedback Components

```tsx
// From providing-feedback skill
import { Toast, Spinner, EmptyState } from '@/components/feedback'

// Wire toast notifications
<ToastProvider>
  <App />
</ToastProvider>

// Use spinner for loading states
{isLoading ? <Spinner /> : <Dashboard />}
```

## Integration Checklist

Before delivery, verify:

- [ ] **Token file exists** (`tokens.css`) with all 7 categories
- [ ] **Token import order** correct (tokens.css → globals.css → components)
- [ ] **No hardcoded values** (run `validate_tokens.py`)
- [ ] **Theme toggle works** (`data-theme` attribute switches)
- [ ] **Reduced motion** supported (`@media (prefers-reduced-motion)`)
- [ ] **Build completes** without errors
- [ ] **Types pass** (TypeScript compiles)
- [ ] **Imports resolve** (no missing modules)
- [ ] **Barrel exports** exist for each component directory

## Bundled Resources

### Scripts (Token-Free Execution)
- `scripts/validate_tokens.py` - Validate CSS uses design tokens
- `scripts/generate_scaffold.py` - Generate project boilerplate
- `scripts/check_imports.py` - Validate import chains
- `scripts/generate_exports.py` - Create barrel export files

Run scripts directly without loading into context:
```bash
python scripts/validate_tokens.py demo/examples --fix-suggestions
```

### References (Detailed Patterns)
- `references/library-context.md` - AI Design Components library awareness
- `references/react-vite-template.md` - Full Vite + React setup
- `references/nextjs-template.md` - Next.js 14/15 patterns
- `references/python-fastapi-template.md` - FastAPI project structure
- `references/rust-axum-template.md` - Rust/Axum project structure
- `references/token-validation-rules.md` - Complete validation rules

### Examples (Complete Implementations)
- `examples/react-dashboard/` - Full Vite + React dashboard
- `examples/nextjs-dashboard/` - Next.js App Router dashboard
- `examples/fastapi-dashboard/` - Python FastAPI dashboard
- `examples/rust-axum-dashboard/` - Rust Axum dashboard

### Assets (Templates)
- `assets/templates/react/` - React project templates
- `assets/templates/python/` - Python project templates
- `assets/templates/rust/` - Rust project templates

## Application Assembly Workflow

1. **Validate Components**: Run `validate_tokens.py` on all generated CSS
2. **Choose Framework**: React/Vite, Next.js, FastAPI, or Rust based on requirements
3. **Generate Scaffolding**: Create project structure and configuration
4. **Wire Imports**: Set up entry point, import chain, barrel exports
5. **Add Providers**: ThemeProvider, ToastProvider at root
6. **Connect Components**: Import and compose feature components
7. **Configure Build**: vite.config, tsconfig, package.json
8. **Final Validation**: Build, type-check, lint
9. **Document**: README with setup and usage instructions

For library-specific patterns and complete context, see `references/library-context.md`.


---

## Referenced Files

> The following files are referenced in this skill and included for context.

### scripts/validate_tokens.py

```python
#!/usr/bin/env python3
"""
validate_tokens.py - CSS Design Token Validator

Scans CSS files for hardcoded values that should use design tokens.
Returns actionable fix suggestions with specific token recommendations.

ZERO CONTEXT TOKEN COST - Executed without loading into Claude's context.

Usage:
    python validate_tokens.py <directory> [--strict] [--json] [--fix-suggestions]

Examples:
    python validate_tokens.py src/styles
    python validate_tokens.py src --strict --json
    python validate_tokens.py demo/examples/palo-alto-security-dashboard --fix-suggestions
"""

import re
import sys
import json
import argparse
from pathlib import Path
from dataclasses import dataclass, asdict
from typing import List, Dict, Optional, Set
from collections import defaultdict


@dataclass
class Violation:
    """Represents a single token violation in a CSS file."""
    file: str
    line: int
    column: int
    property_name: str
    value: str
    category: str
    suggestion: str
    severity: str  # 'error' | 'warning' | 'info'
    fix: Optional[str] = None


@dataclass
class ValidationReport:
    """Complete validation report for a directory."""
    total_files: int
    files_with_violations: int
    total_violations: int
    errors: int
    warnings: int
    info: int
    violations: List[Violation]
    summary_by_category: Dict[str, int]


# ============================================================================
# TOKEN PATTERNS AND SUGGESTIONS
# ============================================================================

# Common token mappings for fix suggestions
TOKEN_MAPS = {
    'colors': {
        '#FA582D': '--color-cyber-orange',
        '#B23808': '--color-orange-dark',
        '#FF724D': '--color-orange-light',
        '#00C0E8': '--color-prisma-blue',
        '#00CC66': '--color-cortex-green',
        '#FFCB06': '--color-strata-yellow',
        '#C84727': '--color-unit42-red',
        '#FFFFFF': '--color-bg-primary',
        '#F8FAFC': '--color-bg-secondary',
        '#F1F5F9': '--color-bg-tertiary',
        '#1E293B': '--color-text-primary',
        '#64748B': '--color-text-secondary',
        '#94A3B8': '--color-text-tertiary',
        '#E2E8F0': '--color-border-primary',
        '#CBD5E1': '--color-border-secondary',
        '#0F172A': '--color-bg-primary (dark)',
        '#334155': '--color-bg-tertiary (dark)',
    },
    'spacing': {
        '4px': '--spacing-xs (--space-1)',
        '8px': '--spacing-sm (--space-2)',
        '12px': '--space-3',
        '16px': '--spacing-md (--space-4)',
        '20px': '--space-5',
        '24px': '--spacing-lg (--space-6)',
        '32px': '--spacing-xl (--space-8)',
        '40px': '--space-10',
        '48px': '--spacing-2xl (--space-12)',
        '64px': '--space-16',
    },
    'font-sizes': {
        '12px': '--font-size-xs',
        '14px': '--font-size-sm',
        '16px': '--font-size-base',
        '18px': '--font-size-lg',
        '20px': '--font-size-xl',
        '24px': '--font-size-2xl',
        '30px': '--font-size-3xl',
        '36px': '--font-size-4xl',
    },
    'radii': {
        '4px': '--radius-sm',
        '8px': '--radius-md',
        '12px': '--radius-lg',
        '16px': '--radius-xl',
        '9999px': '--radius-full',
    },
    'durations': {
        '150ms': '--duration-fast',
        '200ms': '--duration-normal',
        '300ms': '--duration-slow',
    },
}

# Validation rules with patterns
VALIDATION_RULES = {
    'hardcoded-colors': {
        'pattern': r'(?<!var\()(?<!-)#[0-9A-Fa-f]{3,8}\b',
        'property_pattern': r'(color|background|background-color|border|border-color|fill|stroke|box-shadow|text-shadow|outline)',
        'suggestion': 'Use semantic color token (e.g., --color-primary, --color-text-primary)',
        'severity': 'error',
        'category': 'colors',
    },
    'rgb-colors': {
        'pattern': r'(?<!var\()rgba?\([^)]+\)',
        'suggestion': 'Use semantic color token instead of rgb/rgba',
        'severity': 'error',
        'category': 'colors',
    },
    'hardcoded-spacing': {
        'pattern': r'(?<!var\()(?<!:)\b(\d{2,})(px)\b',
        'property_pattern': r'(padding|margin|gap|top|right|bottom|left|width|height|min-width|max-width|min-height|max-height)',
        'suggestion': 'Use spacing token (e.g., --spacing-md, --spacing-lg)',
        'severity': 'error',
        'category': 'spacing',
        'min_value': 4,  # Only flag values >= 4px
    },
    'hardcoded-font-sizes': {
        'pattern': r'font-size:\s*(\d+)(px|rem)',
        'suggestion': 'Use font-size token (e.g., --font-size-sm, --font-size-base)',
        'severity': 'error',
        'category': 'font-sizes',
    },
    'hardcoded-border-radius': {
        'pattern': r'border-radius:\s*(\d+)(px)',
        'suggestion': 'Use radius token (e.g., --radius-md, --radius-lg)',
        'severity': 'warning',
        'category': 'radii',
    },
    'hardcoded-box-shadow': {
        'pattern': r'box-shadow:\s*\d+px\s+\d+px[^;]*(?!var\()',
        'suggestion': 'Use shadow token (e.g., --shadow-sm, --shadow-md)',
        'severity': 'warning',
        'category': 'shadows',
    },
    'hardcoded-transitions': {
        'pattern': r'transition[^:]*:\s*(?!var\()(?!none)(?!inherit)[^;]*\d+(ms|s)',
        'suggestion': 'Use transition token (e.g., --transition-fast, --transition-normal)',
        'severity': 'info',
        'category': 'transitions',
    },
    'hardcoded-z-index': {
        'pattern': r'z-index:\s*(\d{3,})',
        'suggestion': 'Use z-index token (e.g., --z-dropdown, --z-modal)',
        'severity': 'warning',
        'category': 'z-index',
    },
}

# Patterns to skip (not violations)
SKIP_PATTERNS = [
    r'^\s*--',           # CSS custom property definitions
    r'^\s*/\*',          # Comment start
    r'^\s*\*',           # Comment continuation
    r'currentColor',     # CSS keyword
    r'transparent',      # CSS keyword
    r'inherit',          # CSS keyword
    r'initial',          # CSS keyword
    r'unset',            # CSS keyword
    r'@media',           # Media query line (breakpoints allowed)
    r'@keyframes',       # Keyframe definitions
    r'from\s*{',         # Keyframe from
    r'to\s*{',           # Keyframe to
    r'\d+%\s*{',         # Keyframe percentage
]

# Properties where hardcoded values are acceptable
EXCEPTION_PROPERTIES = [
    'outline',           # Accessibility focus indicators
    'outline-offset',    # Accessibility
    'transform',         # Animation transforms
    'animation',         # Animation definitions
    'content',           # Pseudo-element content
    'clip-path',         # Complex clipping
    'mask',              # Complex masking
]

# Values that are always acceptable
EXCEPTION_VALUES = [
    '0',
    '0px',
    '1px',              # Hairline borders
    '2px',              # Focus outlines
    '100%',
    '50%',
    'auto',
    'none',
    'inherit',
    'initial',
    'unset',
    'currentColor',
    'transparent',
]

# Layout values that are acceptable (container widths, breakpoints)
LAYOUT_EXCEPTION_VALUES = [
    '1400px',           # Common max-width container
    '1200px',           # Common max-width container
    '1024px',           # Common max-width container
    '768px',            # Tablet breakpoint
    '640px',            # Mobile breakpoint
    '480px',            # Small mobile breakpoint
]

# Patterns in lines to skip entirely
LINE_SKIP_PATTERNS = [
    r'max-width:\s*\d+px',     # Container max-widths
    r'min-width:\s*\d+px',     # Container min-widths
    r'minmax\(',               # Grid minmax functions
    r'grid-template',          # Grid templates
    r'repeat\(',               # Grid repeat
]


# ============================================================================
# VALIDATION LOGIC
# ============================================================================

def should_skip_line(line: str) -> bool:
    """Check if a line should be skipped from validation."""
    for pattern in SKIP_PATTERNS:
        if re.search(pattern, line, re.IGNORECASE):
            return True
    # Also skip layout-specific patterns
    for pattern in LINE_SKIP_PATTERNS:
        if re.search(pattern, line, re.IGNORECASE):
            return True
    return False


def is_exception_property(line: str) -> bool:
    """Check if the line contains an exception property."""
    for prop in EXCEPTION_PROPERTIES:
        if f'{prop}:' in line or f'{prop} :' in line:
            return True
    return False


def is_exception_value(value: str) -> bool:
    """Check if a value is in the exception list."""
    return value.strip() in EXCEPTION_VALUES


def get_token_suggestion(value: str, category: str) -> Optional[str]:
    """Get specific token suggestion for a hardcoded value."""
    if category in TOKEN_MAPS:
        # Normalize the value for lookup
        normalized = value.upper().strip()
        for hardcoded, token in TOKEN_MAPS[category].items():
            if hardcoded.upper() == normalized or hardcoded == value:
                return f'var({token})'
    return None


def validate_file(filepath: Path, strict: bool = False) -> List[Violation]:
    """Validate a single CSS file for token violations."""
    violations = []

    try:
        content = filepath.read_text(encoding='utf-8')
    except Exception as e:
        print(f"Warning: Could not read {filepath}: {e}", file=sys.stderr)
        return violations

    lines = content.split('\n')

    for line_num, line in enumerate(lines, 1):
        # Skip lines that shouldn't be validated
        if should_skip_line(line):
            continue

        # Skip exception properties
        if is_exception_property(line):
            continue

        # Check each validation rule
        for rule_name, rule in VALIDATION_RULES.items():
            pattern = rule['pattern']
            matches = list(re.finditer(pattern, line, re.IGNORECASE))

            for match in matches:
                value = match.group(0)
                column = match.start() + 1

                # Skip exception values
                if is_exception_value(value):
                    continue

                # For spacing, check minimum value
                if 'min_value' in rule:
                    num_match = re.search(r'(\d+)', value)
                    if num_match and int(num_match.group(1)) < rule['min_value']:
                        continue

                # Skip if already using var()
                if 'var(' in line[max(0, match.start()-4):match.start()]:
                    continue

                # Get specific token suggestion if available
                specific_fix = get_token_suggestion(value, rule['category'])

                # Skip non-strict warnings in non-strict mode
                if not strict and rule['severity'] in ['info']:
                    continue

                violations.append(Violation(
                    file=str(filepath),
                    line=line_num,
                    column=column,
                    property_name=rule_name,
                    value=value,
                    category=rule['category'],
                    suggestion=rule['suggestion'],
                    severity=rule['severity'],
                    fix=specific_fix
                ))

    return violations


def validate_directory(directory: Path, strict: bool = False) -> ValidationReport:
    """Validate all CSS files in a directory."""
    css_files = list(directory.rglob('*.css'))

    all_violations: List[Violation] = []
    files_with_violations: Set[str] = set()
    summary_by_category: Dict[str, int] = defaultdict(int)

    for css_file in css_files:
        # Skip token definition files
        if 'tokens' in css_file.name.lower():
            continue

        violations = validate_file(css_file, strict)

        if violations:
            files_with_violations.add(str(css_file))
            all_violations.extend(violations)

            for v in violations:
                summary_by_category[v.category] += 1

    errors = sum(1 for v in all_violations if v.severity == 'error')
    warnings = sum(1 for v in all_violations if v.severity == 'warning')
    info = sum(1 for v in all_violations if v.severity == 'info')

    return ValidationReport(
        total_files=len(css_files),
        files_with_violations=len(files_with_violations),
        total_violations=len(all_violations),
        errors=errors,
        warnings=warnings,
        info=info,
        violations=all_violations,
        summary_by_category=dict(summary_by_category)
    )


# ============================================================================
# OUTPUT FORMATTING
# ============================================================================

def format_console_report(report: ValidationReport, show_fixes: bool = False) -> str:
    """Format the validation report for console output."""
    lines = []

    lines.append("")
    lines.append("=" * 70)
    lines.append("  CSS DESIGN TOKEN VALIDATION REPORT")
    lines.append("=" * 70)
    lines.append("")

    if not report.violations:
        lines.append("  All CSS files use design tokens correctly!")
        lines.append("")
        lines.append(f"  Scanned: {report.total_files} files")
        lines.append("")
        return '\n'.join(lines)

    # Group violations by file
    by_file: Dict[str, List[Violation]] = defaultdict(list)
    for v in report.violations:
        by_file[v.file].append(v)

    for filepath, violations in by_file.items():
        lines.append(f"  {filepath}")
        lines.append("  " + "-" * 60)

        for v in violations:
            icon = {"error": "", "warning": "", "info": ""}.get(v.severity, "")
            lines.append(f"    {icon} Line {v.line}:{v.column} [{v.severity.upper()}]")
            lines.append(f"       Found: {v.value}")
            lines.append(f"       Rule: {v.category}")
            lines.append(f"       Fix: {v.suggestion}")
            if show_fixes and v.fix:
                lines.append(f"       Suggested: {v.fix}")
            lines.append("")

        lines.append("")

    # Summary
    lines.append("-" * 70)
    lines.append("  SUMMARY")
    lines.append("-" * 70)
    lines.append(f"  Files scanned:     {report.total_files}")
    lines.append(f"  Files with issues: {report.files_with_violations}")
    lines.append(f"  Total violations:  {report.total_violations}")
    lines.append(f"    - Errors:   {report.errors}")
    lines.append(f"    - Warnings: {report.warnings}")
    lines.append(f"    - Info:     {report.info}")
    lines.append("")

    if report.summary_by_category:
        lines.append("  By Category:")
        for category, count in sorted(report.summary_by_category.items()):
            lines.append(f"    - {category}: {count}")
        lines.append("")

    return '\n'.join(lines)


def format_json_report(report: ValidationReport) -> str:
    """Format the validation report as JSON."""
    return json.dumps({
        'total_files': report.total_files,
        'files_with_violations': report.files_with_violations,
        'total_violations': report.total_violations,
        'errors': report.errors,
        'warnings': report.warnings,
        'info': report.info,
        'summary_by_category': report.summary_by_category,
        'violations': [asdict(v) for v in report.violations]
    }, indent=2)


# ============================================================================
# MAIN
# ============================================================================

def main():
    parser = argparse.ArgumentParser(
        description='Validate CSS files for design token usage',
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="""
Examples:
  %(prog)s src/styles
  %(prog)s src --strict --json
  %(prog)s demo/examples --fix-suggestions
        """
    )
    parser.add_argument('directory', type=Path, help='Directory to scan')
    parser.add_argument('--strict', action='store_true',
                        help='Include info-level violations')
    parser.add_argument('--json', action='store_true',
                        help='Output as JSON')
    parser.add_argument('--fix-suggestions', action='store_true',
                        help='Show specific token suggestions where available')

    args = parser.parse_args()

    if not args.directory.exists():
        print(f"Error: Directory not found: {args.directory}", file=sys.stderr)
        sys.exit(2)

    report = validate_directory(args.directory, strict=args.strict)

    if args.json:
        print(format_json_report(report))
    else:
        print(format_console_report(report, show_fixes=args.fix_suggestions))

    # Exit with appropriate code
    if report.errors > 0:
        sys.exit(1)
    elif report.warnings > 0:
        sys.exit(0)  # Warnings don't fail the build
    else:
        sys.exit(0)


if __name__ == "__main__":
    main()

```

### scripts/generate_scaffold.py

```python
#!/usr/bin/env python3
"""
generate_scaffold.py - Project Scaffolding Generator

Generates project scaffolding for React/Vite, Next.js, Python FastAPI, or Rust Axum
based on templates from the assembling-components skill.

ZERO CONTEXT TOKEN COST - Executed without loading into Claude's context.

Usage:
    python generate_scaffold.py <project_name> <framework> [output_dir]

Examples:
    python generate_scaffold.py my-dashboard react-vite ./output
    python generate_scaffold.py my-app nextjs ./output
    python generate_scaffold.py my-api python-fastapi ./output
    python generate_scaffold.py my-server rust-axum ./output
"""

import os
import sys
import json
import argparse
from pathlib import Path
from dataclasses import dataclass
from typing import Dict, List, Optional


@dataclass
class ProjectConfig:
    """Project configuration."""
    name: str
    title: str
    description: str
    author: str
    version: str = "1.0.0"


FRAMEWORKS = {
    'react-vite': 'React + Vite (SPA)',
    'nextjs': 'Next.js 14/15 (SSR/SSG)',
    'python-fastapi': 'Python FastAPI',
    'rust-axum': 'Rust Axum',
}


# ============================================================================
# REACT/VITE SCAFFOLDING
# ============================================================================

def create_react_vite_scaffold(output_dir: Path, config: ProjectConfig) -> List[str]:
    """Generate React/Vite project scaffolding."""
    created_files = []

    # Directory structure
    dirs = [
        'src',
        'src/components/ui',
        'src/components/layout',
        'src/components/charts',
        'src/components/feedback',
        'src/components/features/dashboard',
        'src/context',
        'src/hooks',
        'src/lib',
        'src/styles',
        'src/types',
        'public',
    ]

    for d in dirs:
        (output_dir / d).mkdir(parents=True, exist_ok=True)

    # package.json
    package_json = {
        "name": config.name,
        "private": True,
        "version": config.version,
        "type": "module",
        "scripts": {
            "dev": "vite",
            "build": "tsc && vite build",
            "preview": "vite preview",
            "lint": "eslint . --ext ts,tsx",
            "validate:tokens": "python scripts/validate_tokens.py src"
        },
        "dependencies": {
            "react": "^18.3.1",
            "react-dom": "^18.3.1"
        },
        "devDependencies": {
            "@types/react": "^18.3.0",
            "@types/react-dom": "^18.3.0",
            "@vitejs/plugin-react": "^4.3.0",
            "typescript": "^5.4.0",
            "vite": "^5.4.0"
        }
    }
    write_json(output_dir / 'package.json', package_json)
    created_files.append('package.json')

    # vite.config.ts
    vite_config = '''import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import path from 'path'

export default defineConfig({
  plugins: [react()],
  resolve: {
    alias: {
      '@': path.resolve(__dirname, './src'),
    },
  },
})
'''
    write_file(output_dir / 'vite.config.ts', vite_config)
    created_files.append('vite.config.ts')

    # tsconfig.json
    tsconfig = {
        "compilerOptions": {
            "target": "ES2020",
            "useDefineForClassFields": True,
            "lib": ["ES2020", "DOM", "DOM.Iterable"],
            "module": "ESNext",
            "skipLibCheck": True,
            "moduleResolution": "bundler",
            "allowImportingTsExtensions": True,
            "resolveJsonModule": True,
            "isolatedModules": True,
            "noEmit": True,
            "jsx": "react-jsx",
            "strict": True,
            "noUnusedLocals": True,
            "noUnusedParameters": True,
            "noFallthroughCasesInSwitch": True,
            "baseUrl": ".",
            "paths": {"@/*": ["./src/*"]}
        },
        "include": ["src"],
        "references": [{"path": "./tsconfig.node.json"}]
    }
    write_json(output_dir / 'tsconfig.json', tsconfig)
    created_files.append('tsconfig.json')

    # tsconfig.node.json
    tsconfig_node = {
        "compilerOptions": {
            "composite": True,
            "skipLibCheck": True,
            "module": "ESNext",
            "moduleResolution": "bundler",
            "allowSyntheticDefaultImports": True,
            "strict": True
        },
        "include": ["vite.config.ts"]
    }
    write_json(output_dir / 'tsconfig.node.json', tsconfig_node)
    created_files.append('tsconfig.node.json')

    # index.html
    index_html = f'''<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="description" content="{config.description}" />
    <title>{config.title}</title>
    <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
  </head>
  <body>
    <div id="root"></div>
    <script type="module" src="/src/main.tsx"></script>
  </body>
</html>
'''
    write_file(output_dir / 'index.html', index_html)
    created_files.append('index.html')

    # src/main.tsx
    main_tsx = '''import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import { ThemeProvider } from '@/context/theme-provider'
import App from './App'

// CRITICAL: Import tokens FIRST
import './styles/tokens.css'
import './styles/globals.css'

createRoot(document.getElementById('root')!).render(
  <StrictMode>
    <ThemeProvider>
      <App />
    </ThemeProvider>
  </StrictMode>,
)
'''
    write_file(output_dir / 'src/main.tsx', main_tsx)
    created_files.append('src/main.tsx')

    # src/App.tsx
    app_tsx = '''function App() {
  return (
    <div className="app">
      <h1>Welcome to {PROJECT_TITLE}</h1>
      <p>Edit src/App.tsx to get started.</p>
    </div>
  )
}

export default App
'''.replace('{PROJECT_TITLE}', config.title)
    write_file(output_dir / 'src/App.tsx', app_tsx)
    created_files.append('src/App.tsx')

    # Create placeholder files
    placeholder_files = [
        'src/styles/tokens.css',
        'src/styles/globals.css',
        'src/context/theme-provider.tsx',
        'src/components/ui/index.ts',
        'src/components/layout/index.ts',
        'src/lib/utils.ts',
    ]

    for pf in placeholder_files:
        write_file(output_dir / pf, f'// TODO: Implement {Path(pf).name}\n')
        created_files.append(pf)

    return created_files


# ============================================================================
# NEXT.JS SCAFFOLDING
# ============================================================================

def create_nextjs_scaffold(output_dir: Path, config: ProjectConfig) -> List[str]:
    """Generate Next.js project scaffolding."""
    created_files = []

    # Directory structure
    dirs = [
        'src/app',
        'src/app/api/health',
        'src/app/dashboard',
        'src/components/ui',
        'src/components/layout',
        'src/components/features/dashboard',
        'src/context',
        'src/hooks',
        'src/lib',
        'src/styles',
        'src/types',
        'public',
    ]

    for d in dirs:
        (output_dir / d).mkdir(parents=True, exist_ok=True)

    # package.json
    package_json = {
        "name": config.name,
        "version": config.version,
        "private": True,
        "scripts": {
            "dev": "next dev",
            "build": "next build",
            "start": "next start",
            "lint": "next lint",
            "validate:tokens": "python scripts/validate_tokens.py src"
        },
        "dependencies": {
            "next": "^14.2.0",
            "react": "^18.3.1",
            "react-dom": "^18.3.1"
        },
        "devDependencies": {
            "@types/node": "^20.0.0",
            "@types/react": "^18.3.0",
            "@types/react-dom": "^18.3.0",
            "typescript": "^5.4.0"
        }
    }
    write_json(output_dir / 'package.json', package_json)
    created_files.append('package.json')

    # next.config.mjs
    next_config = '''/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: true,
}

export default nextConfig
'''
    write_file(output_dir / 'next.config.mjs', next_config)
    created_files.append('next.config.mjs')

    # tsconfig.json
    tsconfig = {
        "compilerOptions": {
            "target": "ES2020",
            "lib": ["dom", "dom.iterable", "esnext"],
            "allowJs": True,
            "skipLibCheck": True,
            "strict": True,
            "noEmit": True,
            "esModuleInterop": True,
            "module": "esnext",
            "moduleResolution": "bundler",
            "resolveJsonModule": True,
            "isolatedModules": True,
            "jsx": "preserve",
            "incremental": True,
            "plugins": [{"name": "next"}],
            "paths": {"@/*": ["./src/*"]}
        },
        "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
        "exclude": ["node_modules"]
    }
    write_json(output_dir / 'tsconfig.json', tsconfig)
    created_files.append('tsconfig.json')

    # src/app/layout.tsx
    layout_tsx = f'''import type {{ Metadata }} from 'next'
import {{ ThemeProvider }} from '@/context/theme-provider'

import '@/styles/tokens.css'
import './globals.css'

export const metadata: Metadata = {{
  title: '{config.title}',
  description: '{config.description}',
}}

export default function RootLayout({{
  children,
}}: {{
  children: React.ReactNode
}}) {{
  return (
    <html lang="en" suppressHydrationWarning>
      <body>
        <ThemeProvider>
          {{children}}
        </ThemeProvider>
      </body>
    </html>
  )
}}
'''
    write_file(output_dir / 'src/app/layout.tsx', layout_tsx)
    created_files.append('src/app/layout.tsx')

    # src/app/page.tsx
    page_tsx = f'''export default function Home() {{
  return (
    <main>
      <h1>Welcome to {config.title}</h1>
      <p>Edit src/app/page.tsx to get started.</p>
    </main>
  )
}}
'''
    write_file(output_dir / 'src/app/page.tsx', page_tsx)
    created_files.append('src/app/page.tsx')

    # src/app/globals.css
    globals_css = '''/* Global styles - tokens.css imported in layout.tsx */

*,
*::before,
*::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  font-family: var(--font-sans);
  color: var(--color-text-primary);
  background: var(--color-bg-primary);
}
'''
    write_file(output_dir / 'src/app/globals.css', globals_css)
    created_files.append('src/app/globals.css')

    # Placeholder files
    placeholder_files = [
        'src/styles/tokens.css',
        'src/context/theme-provider.tsx',
        'src/components/ui/index.ts',
        'src/lib/utils.ts',
    ]

    for pf in placeholder_files:
        write_file(output_dir / pf, f'// TODO: Implement {Path(pf).name}\n')
        created_files.append(pf)

    return created_files


# ============================================================================
# PYTHON FASTAPI SCAFFOLDING
# ============================================================================

def create_python_fastapi_scaffold(output_dir: Path, config: ProjectConfig) -> List[str]:
    """Generate Python FastAPI project scaffolding."""
    created_files = []

    package_name = config.name.replace('-', '_')

    # Directory structure
    dirs = [
        f'src/{package_name}',
        f'src/{package_name}/api',
        f'src/{package_name}/api/routes',
        f'src/{package_name}/core',
        f'src/{package_name}/models',
        f'src/{package_name}/services',
        f'src/{package_name}/static/css',
        f'src/{package_name}/static/js',
        f'src/{package_name}/templates',
        'tests',
        'scripts',
    ]

    for d in dirs:
        (output_dir / d).mkdir(parents=True, exist_ok=True)

    # pyproject.toml
    pyproject = f'''[project]
name = "{config.name}"
version = "{config.version}"
description = "{config.description}"
requires-python = ">=3.11"
dependencies = [
    "fastapi>=0.109.0",
    "uvicorn[standard]>=0.27.0",
    "pydantic>=2.5.0",
    "pydantic-settings>=2.1.0",
    "python-dotenv>=1.0.0",
    "jinja2>=3.1.0",
]

[project.optional-dependencies]
dev = [
    "pytest>=7.4.0",
    "pytest-asyncio>=0.23.0",
    "httpx>=0.26.0",
    "ruff>=0.1.0",
]

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[tool.hatch.build.targets.wheel]
packages = ["src/{package_name}"]
'''
    write_file(output_dir / 'pyproject.toml', pyproject)
    created_files.append('pyproject.toml')

    # requirements.txt
    requirements = '''fastapi>=0.109.0
uvicorn[standard]>=0.27.0
pydantic>=2.5.0
pydantic-settings>=2.1.0
python-dotenv>=1.0.0
jinja2>=3.1.0
'''
    write_file(output_dir / 'requirements.txt', requirements)
    created_files.append('requirements.txt')

    # src/package_name/__init__.py
    write_file(output_dir / f'src/{package_name}/__init__.py', f'"""{{package_name}} package."""\n')
    created_files.append(f'src/{package_name}/__init__.py')

    # src/package_name/main.py
    main_py = f'''"""FastAPI application entry point."""

from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles

from .api.routes import health
from .config import settings


def create_app() -> FastAPI:
    """Create and configure the FastAPI application."""
    app = FastAPI(
        title=settings.app_name,
        version=settings.version,
    )

    app.mount("/static", StaticFiles(directory="src/{package_name}/static"), name="static")
    app.include_router(health.router, prefix="/api", tags=["health"])

    return app


app = create_app()


if __name__ == "__main__":
    import uvicorn
    uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)
'''
    write_file(output_dir / f'src/{package_name}/main.py', main_py)
    created_files.append(f'src/{package_name}/main.py')

    # src/package_name/config.py
    config_py = f'''"""Application configuration."""

from pydantic_settings import BaseSettings


class Settings(BaseSettings):
    """Application settings."""

    app_name: str = "{config.title}"
    version: str = "{config.version}"
    debug: bool = False
    host: str = "0.0.0.0"
    port: int = 8000

    class Config:
        env_file = ".env"


settings = Settings()
'''
    write_file(output_dir / f'src/{package_name}/config.py', config_py)
    created_files.append(f'src/{package_name}/config.py')

    # API routes
    write_file(output_dir / f'src/{package_name}/api/__init__.py', '')
    write_file(output_dir / f'src/{package_name}/api/routes/__init__.py', '')

    health_py = '''"""Health check routes."""

from datetime import datetime
from fastapi import APIRouter
from pydantic import BaseModel


router = APIRouter()


class HealthResponse(BaseModel):
    status: str
    timestamp: datetime


@router.get("/health", response_model=HealthResponse)
async def health_check() -> HealthResponse:
    return HealthResponse(status="ok", timestamp=datetime.now())
'''
    write_file(output_dir / f'src/{package_name}/api/routes/health.py', health_py)
    created_files.append(f'src/{package_name}/api/routes/health.py')

    # .env.example
    env_example = '''DEBUG=false
HOST=0.0.0.0
PORT=8000
'''
    write_file(output_dir / '.env.example', env_example)
    created_files.append('.env.example')

    return created_files


# ============================================================================
# RUST AXUM SCAFFOLDING
# ============================================================================

def create_rust_axum_scaffold(output_dir: Path, config: ProjectConfig) -> List[str]:
    """Generate Rust Axum project scaffolding."""
    created_files = []

    # Directory structure
    dirs = [
        'src/routes',
        'src/handlers',
        'src/models',
        'src/services',
        'static/css',
        'static/js',
        'templates',
        'tests',
    ]

    for d in dirs:
        (output_dir / d).mkdir(parents=True, exist_ok=True)

    # Cargo.toml
    cargo_toml = f'''[package]
name = "{config.name}"
version = "{config.version}"
edition = "2021"
description = "{config.description}"

[dependencies]
axum = "0.7"
tokio = {{ version = "1.35", features = ["full"] }}
tower = "0.4"
tower-http = {{ version = "0.5", features = ["fs", "trace"] }}
serde = {{ version = "1.0", features = ["derive"] }}
serde_json = "1.0"
dotenvy = "0.15"
tracing = "0.1"
tracing-subscriber = {{ version = "0.3", features = ["env-filter"] }}
thiserror = "1.0"
anyhow = "1.0"

[dev-dependencies]
axum-test = "14.0"
'''
    write_file(output_dir / 'Cargo.toml', cargo_toml)
    created_files.append('Cargo.toml')

    # src/main.rs
    main_rs = '''mod config;
mod routes;

use axum::Router;
use std::net::SocketAddr;
use tower_http::services::ServeDir;
use tower_http::trace::TraceLayer;
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    tracing_subscriber::registry()
        .with(tracing_subscriber::EnvFilter::try_from_default_env()
            .unwrap_or_else(|_| "info".into()))
        .with(tracing_subscriber::fmt::layer())
        .init();

    let app = Router::new()
        .merge(routes::create_router())
        .nest_service("/static", ServeDir::new("static"))
        .layer(TraceLayer::new_for_http());

    let addr = SocketAddr::from(([0, 0, 0, 0], 3000));
    tracing::info!("Listening on {}", addr);

    let listener = tokio::net::TcpListener::bind(addr).await?;
    axum::serve(listener, app).await?;

    Ok(())
}
'''
    write_file(output_dir / 'src/main.rs', main_rs)
    created_files.append('src/main.rs')

    # src/config.rs
    config_rs = '''use serde::Deserialize;

#[derive(Debug, Deserialize)]
pub struct Config {
    #[serde(default = "default_port")]
    pub port: u16,
}

fn default_port() -> u16 {
    3000
}
'''
    write_file(output_dir / 'src/config.rs', config_rs)
    created_files.append('src/config.rs')

    # src/routes/mod.rs
    routes_mod = '''pub mod health;

use axum::{routing::get, Router};

pub fn create_router() -> Router {
    Router::new()
        .route("/api/health", get(health::health_check))
}
'''
    write_file(output_dir / 'src/routes/mod.rs', routes_mod)
    created_files.append('src/routes/mod.rs')

    # src/routes/health.rs
    health_rs = '''use axum::Json;
use serde::Serialize;

#[derive(Serialize)]
pub struct HealthResponse {
    status: String,
    version: String,
}

pub async fn health_check() -> Json<HealthResponse> {
    Json(HealthResponse {
        status: "ok".into(),
        version: env!("CARGO_PKG_VERSION").into(),
    })
}
'''
    write_file(output_dir / 'src/routes/health.rs', health_rs)
    created_files.append('src/routes/health.rs')

    # .env
    env_file = '''RUST_LOG=info
PORT=3000
'''
    write_file(output_dir / '.env', env_file)
    created_files.append('.env')

    return created_files


# ============================================================================
# UTILITIES
# ============================================================================

def write_file(path: Path, content: str) -> None:
    """Write content to a file."""
    path.parent.mkdir(parents=True, exist_ok=True)
    path.write_text(content, encoding='utf-8')


def write_json(path: Path, data: dict) -> None:
    """Write JSON data to a file."""
    path.parent.mkdir(parents=True, exist_ok=True)
    path.write_text(json.dumps(data, indent=2) + '\n', encoding='utf-8')


def to_title(name: str) -> str:
    """Convert kebab-case to Title Case."""
    return ' '.join(word.capitalize() for word in name.replace('-', ' ').replace('_', ' ').split())


# ============================================================================
# MAIN
# ============================================================================

def main():
    parser = argparse.ArgumentParser(
        description='Generate project scaffolding for various frameworks',
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="""
Frameworks:
  react-vite      React + Vite (SPA)
  nextjs          Next.js 14/15 (SSR/SSG)
  python-fastapi  Python FastAPI
  rust-axum       Rust Axum

Examples:
  %(prog)s my-dashboard react-vite ./output
  %(prog)s my-app nextjs ./projects
  %(prog)s my-api python-fastapi ./services
        """
    )
    parser.add_argument('project_name', help='Project name (kebab-case)')
    parser.add_argument('framework', choices=FRAMEWORKS.keys(), help='Target framework')
    parser.add_argument('output_dir', nargs='?', default='.', help='Output directory')
    parser.add_argument('--description', '-d', default='', help='Project description')
    parser.add_argument('--author', '-a', default='', help='Author name')

    args = parser.parse_args()

    output_dir = Path(args.output_dir) / args.project_name
    if output_dir.exists():
        print(f"Error: Directory already exists: {output_dir}", file=sys.stderr)
        sys.exit(1)

    config = ProjectConfig(
        name=args.project_name,
        title=to_title(args.project_name),
        description=args.description or f'A {FRAMEWORKS[args.framework]} project',
        author=args.author or os.environ.get('USER', 'developer'),
    )

    print(f"\n{'=' * 60}")
    print(f"  GENERATING {FRAMEWORKS[args.framework].upper()} PROJECT")
    print(f"{'=' * 60}\n")
    print(f"  Name: {config.name}")
    print(f"  Title: {config.title}")
    print(f"  Output: {output_dir}\n")

    # Create scaffold based on framework
    if args.framework == 'react-vite':
        created_files = create_react_vite_scaffold(output_dir, config)
    elif args.framework == 'nextjs':
        created_files = create_nextjs_scaffold(output_dir, config)
    elif args.framework == 'python-fastapi':
        created_files = create_python_fastapi_scaffold(output_dir, config)
    elif args.framework == 'rust-axum':
        created_files = create_rust_axum_scaffold(output_dir, config)
    else:
        print(f"Error: Unknown framework: {args.framework}", file=sys.stderr)
        sys.exit(1)

    print(f"  Created {len(created_files)} files:\n")
    for f in created_files[:10]:
        print(f"    - {f}")
    if len(created_files) > 10:
        print(f"    ... and {len(created_files) - 10} more")

    print(f"\n{'=' * 60}")
    print(f"  NEXT STEPS")
    print(f"{'=' * 60}\n")

    if args.framework == 'react-vite':
        print(f"  cd {output_dir}")
        print("  npm install")
        print("  npm run dev")
    elif args.framework == 'nextjs':
        print(f"  cd {output_dir}")
        print("  npm install")
        print("  npm run dev")
    elif args.framework == 'python-fastapi':
        print(f"  cd {output_dir}")
        print("  pip install -e '.[dev]'")
        print("  uvicorn src.<package>.main:app --reload")
    elif args.framework == 'rust-axum':
        print(f"  cd {output_dir}")
        print("  cargo run")

    print()


if __name__ == "__main__":
    main()

```

### scripts/check_imports.py

```python
#!/usr/bin/env python3
"""
check_imports.py - Import Chain Validator

Validates that import chains are correct in React/TypeScript projects:
- tokens.css is imported before other styles
- ThemeProvider wraps the app
- Barrel exports exist for component directories
- No circular imports

ZERO CONTEXT TOKEN COST - Executed without loading into Claude's context.

Usage:
    python check_imports.py <directory>

Examples:
    python check_imports.py src
    python check_imports.py demo/examples/my-project/src
"""

import sys
import re
import argparse
from pathlib import Path
from dataclasses import dataclass, field
from typing import List, Dict, Set, Optional
from collections import defaultdict


@dataclass
class ImportInfo:
    """Information about an import statement."""
    source: str
    specifiers: List[str]
    is_css: bool
    is_relative: bool
    line_number: int


@dataclass
class ValidationResult:
    """Result of validation checks."""
    file: str
    issues: List[str] = field(default_factory=list)
    warnings: List[str] = field(default_factory=list)


@dataclass
class ProjectValidation:
    """Overall project validation results."""
    total_files: int = 0
    files_with_issues: int = 0
    total_issues: int = 0
    total_warnings: int = 0
    results: List[ValidationResult] = field(default_factory=list)
    missing_barrel_exports: List[str] = field(default_factory=list)
    token_import_issues: List[str] = field(default_factory=list)


def parse_imports(file_path: Path) -> List[ImportInfo]:
    """Parse all import statements from a file."""
    imports = []
    content = file_path.read_text(encoding='utf-8')
    lines = content.split('\n')

    # Match various import patterns
    patterns = [
        # import X from 'path'
        r"import\s+(\w+)\s+from\s+['\"]([^'\"]+)['\"]",
        # import { X, Y } from 'path'
        r"import\s+\{([^}]+)\}\s+from\s+['\"]([^'\"]+)['\"]",
        # import 'path' (side-effect import, like CSS)
        r"import\s+['\"]([^'\"]+)['\"]",
        # import * as X from 'path'
        r"import\s+\*\s+as\s+(\w+)\s+from\s+['\"]([^'\"]+)['\"]",
    ]

    for line_num, line in enumerate(lines, 1):
        line = line.strip()
        if not line.startswith('import'):
            continue

        # Side-effect import (CSS, etc.)
        side_effect_match = re.match(r"import\s+['\"]([^'\"]+)['\"]", line)
        if side_effect_match:
            source = side_effect_match.group(1)
            imports.append(ImportInfo(
                source=source,
                specifiers=[],
                is_css=source.endswith('.css'),
                is_relative=source.startswith('.') or source.startswith('@/'),
                line_number=line_num
            ))
            continue

        # Named or default import
        for pattern in patterns[:-1]:  # Exclude side-effect pattern
            match = re.match(pattern, line)
            if match:
                if len(match.groups()) == 2:
                    specifiers_str, source = match.groups()
                    specifiers = [s.strip() for s in specifiers_str.split(',')]
                else:
                    source = match.group(1)
                    specifiers = []

                imports.append(ImportInfo(
                    source=source,
                    specifiers=specifiers,
                    is_css=source.endswith('.css'),
                    is_relative=source.startswith('.') or source.startswith('@/'),
                    line_number=line_num
                ))
                break

    return imports


def check_token_import_order(file_path: Path, imports: List[ImportInfo]) -> List[str]:
    """Check that tokens.css is imported before other CSS files."""
    issues = []

    css_imports = [i for i in imports if i.is_css]
    if not css_imports:
        return issues

    token_import_idx = None
    for idx, imp in enumerate(css_imports):
        if 'tokens' in imp.source.lower():
            token_import_idx = idx
            break

    if token_import_idx is None:
        # No token import found - might be okay if it's not an entry file
        if file_path.name in ('main.tsx', 'index.tsx', 'App.tsx', 'layout.tsx'):
            issues.append(f"Entry file should import tokens.css")
    elif token_import_idx > 0:
        issues.append(f"tokens.css should be imported BEFORE other CSS files (line {css_imports[token_import_idx].line_number})")

    return issues


def check_theme_provider(file_path: Path) -> List[str]:
    """Check that entry files use ThemeProvider."""
    issues = []

    if file_path.name not in ('main.tsx', 'index.tsx', 'App.tsx', 'layout.tsx', '_app.tsx'):
        return issues

    content = file_path.read_text(encoding='utf-8')

    # Check for ThemeProvider import
    has_theme_import = re.search(r"import.*ThemeProvider", content) is not None

    # Check for ThemeProvider usage
    has_theme_usage = re.search(r"<ThemeProvider", content) is not None

    if file_path.name in ('main.tsx', 'layout.tsx', '_app.tsx'):
        if not has_theme_import:
            issues.append("Entry file should import ThemeProvider")
        if not has_theme_usage:
            issues.append("Entry file should wrap app with ThemeProvider")

    return issues


def check_barrel_exports(directory: Path) -> List[str]:
    """Check that component directories have barrel exports."""
    missing = []

    # Find directories with .tsx files but no index.ts
    for dir_path in directory.rglob('*'):
        if not dir_path.is_dir():
            continue

        # Skip certain directories
        if any(skip in dir_path.parts for skip in ('node_modules', '.next', 'dist', 'build')):
            continue

        tsx_files = list(dir_path.glob('*.tsx'))
        has_index = (dir_path / 'index.ts').exists() or (dir_path / 'index.tsx').exists()

        # If there are multiple .tsx files, there should be a barrel export
        if len(tsx_files) > 1 and not has_index:
            relative = dir_path.relative_to(directory)
            missing.append(str(relative))

    return missing


def find_circular_imports(directory: Path) -> List[str]:
    """Detect circular imports in the project."""
    # Build import graph
    import_graph: Dict[str, Set[str]] = defaultdict(set)

    for ts_file in directory.rglob('*.ts'):
        if 'node_modules' in str(ts_file):
            continue
        imports = parse_imports(ts_file)
        file_key = str(ts_file.relative_to(directory))

        for imp in imports:
            if imp.is_relative:
                # Resolve relative import
                if imp.source.startswith('./'):
                    resolved = ts_file.parent / imp.source[2:]
                elif imp.source.startswith('../'):
                    resolved = (ts_file.parent / imp.source).resolve()
                elif imp.source.startswith('@/'):
                    resolved = directory / imp.source[2:]
                else:
                    continue

                # Add .ts or .tsx extension if needed
                if not resolved.suffix:
                    for ext in ['.ts', '.tsx', '/index.ts', '/index.tsx']:
                        if (resolved.parent / (resolved.name + ext)).exists():
                            resolved = resolved.parent / (resolved.name + ext)
                            break

                if resolved.exists():
                    target_key = str(resolved.relative_to(directory))
                    import_graph[file_key].add(target_key)

    # Same for .tsx files
    for tsx_file in directory.rglob('*.tsx'):
        if 'node_modules' in str(tsx_file):
            continue
        imports = parse_imports(tsx_file)
        file_key = str(tsx_file.relative_to(directory))

        for imp in imports:
            if imp.is_relative:
                if imp.source.startswith('./'):
                    resolved = tsx_file.parent / imp.source[2:]
                elif imp.source.startswith('../'):
                    resolved = (tsx_file.parent / imp.source).resolve()
                elif imp.source.startswith('@/'):
                    resolved = directory / imp.source[2:]
                else:
                    continue

                if not resolved.suffix:
                    for ext in ['.ts', '.tsx', '/index.ts', '/index.tsx']:
                        test_path = resolved.parent / (resolved.name + ext)
                        if test_path.exists():
                            resolved = test_path
                            break

                if resolved.exists():
                    target_key = str(resolved.relative_to(directory))
                    import_graph[file_key].add(target_key)

    # Detect cycles using DFS
    cycles = []
    visited = set()
    rec_stack = set()
    path = []

    def dfs(node: str) -> bool:
        visited.add(node)
        rec_stack.add(node)
        path.append(node)

        for neighbor in import_graph.get(node, []):
            if neighbor not in visited:
                if dfs(neighbor):
                    return True
            elif neighbor in rec_stack:
                cycle_start = path.index(neighbor)
                cycle = path[cycle_start:] + [neighbor]
                cycles.append(' -> '.join(cycle))
                return True

        path.pop()
        rec_stack.remove(node)
        return False

    for node in import_graph:
        if node not in visited:
            dfs(node)

    return cycles


def validate_file(file_path: Path) -> ValidationResult:
    """Validate a single file."""
    result = ValidationResult(file=str(file_path))

    try:
        imports = parse_imports(file_path)

        # Check token import order
        result.issues.extend(check_token_import_order(file_path, imports))

        # Check ThemeProvider usage
        result.issues.extend(check_theme_provider(file_path))

    except Exception as e:
        result.warnings.append(f"Could not parse file: {e}")

    return result


def validate_project(directory: Path) -> ProjectValidation:
    """Validate the entire project."""
    validation = ProjectValidation()

    # Find all TypeScript/TSX files
    ts_files = list(directory.rglob('*.ts')) + list(directory.rglob('*.tsx'))
    ts_files = [f for f in ts_files if 'node_modules' not in str(f)]

    validation.total_files = len(ts_files)

    # Validate each file
    for ts_file in ts_files:
        result = validate_file(ts_file)
        if result.issues or result.warnings:
            validation.results.append(result)
            validation.files_with_issues += 1
            validation.total_issues += len(result.issues)
            validation.total_warnings += len(result.warnings)

    # Check barrel exports
    validation.missing_barrel_exports = check_barrel_exports(directory)

    # Check for circular imports
    # (Disabled by default as it can be slow on large projects)
    # validation.circular_imports = find_circular_imports(directory)

    return validation


def format_report(validation: ProjectValidation) -> str:
    """Format the validation report."""
    lines = []

    lines.append("")
    lines.append("=" * 60)
    lines.append("  IMPORT CHAIN VALIDATION REPORT")
    lines.append("=" * 60)
    lines.append("")

    if not validation.results and not validation.missing_barrel_exports:
        lines.append("  All import chains are valid!")
        lines.append("")
        lines.append(f"  Scanned: {validation.total_files} files")
        lines.append("")
        return '\n'.join(lines)

    # File-specific issues
    for result in validation.results:
        lines.append(f"  {result.file}")
        lines.append("  " + "-" * 50)

        for issue in result.issues:
            lines.append(f"    Issue: {issue}")

        for warning in result.warnings:
            lines.append(f"    Warning: {warning}")

        lines.append("")

    # Missing barrel exports
    if validation.missing_barrel_exports:
        lines.append("  Missing Barrel Exports (index.ts)")
        lines.append("  " + "-" * 50)
        for dir_path in validation.missing_barrel_exports:
            lines.append(f"    - {dir_path}/")
        lines.append("")
        lines.append("  Run: python scripts/generate_exports.py src/components")
        lines.append("")

    # Summary
    lines.append("-" * 60)
    lines.append("  SUMMARY")
    lines.append("-" * 60)
    lines.append(f"  Files scanned:       {validation.total_files}")
    lines.append(f"  Files with issues:   {validation.files_with_issues}")
    lines.append(f"  Total issues:        {validation.total_issues}")
    lines.append(f"  Total warnings:      {validation.total_warnings}")
    lines.append(f"  Missing exports:     {len(validation.missing_barrel_exports)}")
    lines.append("")

    return '\n'.join(lines)


def main():
    parser = argparse.ArgumentParser(
        description='Validate import chains in React/TypeScript projects',
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="""
Checks performed:
  - tokens.css imported before other CSS files
  - ThemeProvider wraps the app in entry files
  - Barrel exports exist for component directories
  - No circular imports (optional)

Examples:
  %(prog)s src
  %(prog)s demo/examples/my-project/src
        """
    )
    parser.add_argument('directory', type=Path, help='Directory to validate')
    parser.add_argument('--json', action='store_true', help='Output as JSON')
    parser.add_argument('--check-circular', action='store_true', help='Check for circular imports (slow)')

    args = parser.parse_args()

    if not args.directory.exists():
        print(f"Error: Directory not found: {args.directory}", file=sys.stderr)
        sys.exit(1)

    validation = validate_project(args.directory)

    if args.json:
        import json
        print(json.dumps({
            'total_files': validation.total_files,
            'files_with_issues': validation.files_with_issues,
            'total_issues': validation.total_issues,
            'total_warnings': validation.total_warnings,
            'missing_barrel_exports': validation.missing_barrel_exports,
            'results': [
                {
                    'file': r.file,
                    'issues': r.issues,
                    'warnings': r.warnings
                }
                for r in validation.results
            ]
        }, indent=2))
    else:
        print(format_report(validation))

    # Exit with error if issues found
    if validation.total_issues > 0:
        sys.exit(1)
    sys.exit(0)


if __name__ == "__main__":
    main()

```

### scripts/generate_exports.py

```python
#!/usr/bin/env python3
"""
generate_exports.py - Barrel Export Generator

Generates index.ts barrel export files for React/TypeScript component directories.
Scans for .tsx files and creates proper exports.

ZERO CONTEXT TOKEN COST - Executed without loading into Claude's context.

Usage:
    python generate_exports.py <directory>

Examples:
    python generate_exports.py src/components
    python generate_exports.py src/components/ui
"""

import sys
import re
import argparse
from pathlib import Path
from dataclasses import dataclass
from typing import List, Optional, Set


@dataclass
class ExportInfo:
    """Information about an export."""
    name: str
    file_path: str
    is_default: bool


def find_exports(file_path: Path) -> List[ExportInfo]:
    """Find all exports in a TypeScript/TSX file."""
    exports = []
    content = file_path.read_text(encoding='utf-8')
    file_stem = file_path.stem

    # Check for default export
    # Patterns: export default function X, export default X, export default class X
    default_patterns = [
        r'export\s+default\s+function\s+(\w+)',
        r'export\s+default\s+class\s+(\w+)',
        r'export\s+default\s+(\w+)',
    ]

    for pattern in default_patterns:
        match = re.search(pattern, content)
        if match:
            name = match.group(1)
            # Use PascalCase version of filename if export name is generic
            if name in ('default', 'component', 'Component'):
                name = to_pascal_case(file_stem)
            exports.append(ExportInfo(
                name=name,
                file_path=f'./{file_stem}',
                is_default=True
            ))
            break

    # Check for named exports
    # Patterns: export function X, export const X, export class X, export type X, export interface X
    named_patterns = [
        r'export\s+(?:async\s+)?function\s+(\w+)',
        r'export\s+const\s+(\w+)',
        r'export\s+let\s+(\w+)',
        r'export\s+class\s+(\w+)',
        r'export\s+type\s+(\w+)',
        r'export\s+interface\s+(\w+)',
        r'export\s+enum\s+(\w+)',
    ]

    for pattern in named_patterns:
        for match in re.finditer(pattern, content):
            name = match.group(1)
            # Skip if it's a default export we already captured
            if any(e.name == name and e.is_default for e in exports):
                continue
            exports.append(ExportInfo(
                name=name,
                file_path=f'./{file_stem}',
                is_default=False
            ))

    return exports


def to_pascal_case(name: str) -> str:
    """Convert kebab-case or snake_case to PascalCase."""
    parts = re.split(r'[-_]', name)
    return ''.join(part.capitalize() for part in parts)


def generate_index_content(exports: List[ExportInfo]) -> str:
    """Generate the content for an index.ts barrel export file."""
    lines = []

    # Group exports by file
    files: dict[str, List[ExportInfo]] = {}
    for export in exports:
        if export.file_path not in files:
            files[export.file_path] = []
        files[export.file_path].append(export)

    # Generate export statements
    for file_path, file_exports in sorted(files.items()):
        default_exports = [e for e in file_exports if e.is_default]
        named_exports = [e for e in file_exports if not e.is_default]

        if default_exports and named_exports:
            # Both default and named exports
            names = ', '.join(e.name for e in named_exports)
            lines.append(f"export {{ default as {default_exports[0].name}, {names} }} from '{file_path}'")
        elif default_exports:
            # Only default export - re-export as named
            lines.append(f"export {{ {default_exports[0].name} }} from '{file_path}'")
        elif named_exports:
            # Only named exports
            names = ', '.join(e.name for e in named_exports)
            lines.append(f"export {{ {names} }} from '{file_path}'")

    return '\n'.join(sorted(lines)) + '\n'


def process_directory(directory: Path, recursive: bool = True) -> dict[Path, str]:
    """Process a directory and generate barrel exports."""
    results = {}

    # Find all directories with .tsx files
    if recursive:
        dirs_to_process = set()
        for tsx_file in directory.rglob('*.tsx'):
            if tsx_file.name != 'index.tsx':
                dirs_to_process.add(tsx_file.parent)
    else:
        dirs_to_process = {directory}

    for dir_path in dirs_to_process:
        exports = []

        # Find all .tsx files (excluding index.tsx)
        tsx_files = [f for f in dir_path.glob('*.tsx') if f.name != 'index.tsx']

        if not tsx_files:
            continue

        for tsx_file in tsx_files:
            file_exports = find_exports(tsx_file)
            if not file_exports:
                # If no exports found, assume default export with PascalCase name
                exports.append(ExportInfo(
                    name=to_pascal_case(tsx_file.stem),
                    file_path=f'./{tsx_file.stem}',
                    is_default=True
                ))
            else:
                exports.extend(file_exports)

        if exports:
            content = generate_index_content(exports)
            results[dir_path / 'index.ts'] = content

    return results


def main():
    parser = argparse.ArgumentParser(
        description='Generate barrel export files for React/TypeScript components',
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="""
Examples:
  %(prog)s src/components
  %(prog)s src/components/ui --no-recursive
  %(prog)s src/components --dry-run
        """
    )
    parser.add_argument('directory', type=Path, help='Directory to process')
    parser.add_argument('--no-recursive', action='store_true', help='Only process the specified directory')
    parser.add_argument('--dry-run', action='store_true', help='Show what would be generated without writing')
    parser.add_argument('--overwrite', action='store_true', help='Overwrite existing index.ts files')

    args = parser.parse_args()

    if not args.directory.exists():
        print(f"Error: Directory not found: {args.directory}", file=sys.stderr)
        sys.exit(1)

    results = process_directory(args.directory, recursive=not args.no_recursive)

    if not results:
        print("No components found to generate exports for.")
        sys.exit(0)

    print(f"\n{'=' * 60}")
    print(f"  BARREL EXPORT GENERATOR")
    print(f"{'=' * 60}\n")

    created = 0
    skipped = 0

    for index_path, content in sorted(results.items()):
        relative_path = index_path.relative_to(args.directory.parent) if args.directory.parent != index_path.parent else index_path.name

        if args.dry_run:
            print(f"  Would create: {relative_path}")
            print(f"  {'-' * 40}")
            for line in content.split('\n'):
                if line:
                    print(f"    {line}")
            print()
        else:
            if index_path.exists() and not args.overwrite:
                print(f"  Skipped (exists): {relative_path}")
                skipped += 1
            else:
                index_path.write_text(content, encoding='utf-8')
                print(f"  Created: {relative_path}")
                created += 1

    print(f"\n{'-' * 60}")
    if args.dry_run:
        print(f"  Dry run: {len(results)} files would be created")
    else:
        print(f"  Created: {created} files")
        if skipped:
            print(f"  Skipped: {skipped} files (use --overwrite to replace)")
    print()


if __name__ == "__main__":
    main()

```

### references/library-context.md

```markdown
# AI Design Components Library Context

> **Critical Reference**: This document provides the assembling-components skill with deep awareness of the AI Design Components library structure, enabling intelligent assembly that generic LLM knowledge cannot provide.


## Table of Contents

- [Why This Context Matters](#why-this-context-matters)
- [Skill Chain Architecture](#skill-chain-architecture)
  - [Standard Skill Chain Flow](#standard-skill-chain-flow)
  - [Skill Outputs Reference](#skill-outputs-reference)
- [Token System Reference](#token-system-reference)
  - [Token Naming Conventions](#token-naming-conventions)
- [Component Integration Patterns](#component-integration-patterns)
  - [Import Chain (Critical Order)](#import-chain-critical-order)
  - [Component Directory Structure](#component-directory-structure)
  - [State Integration Patterns](#state-integration-patterns)
- [Skill-Specific Assembly Rules](#skill-specific-assembly-rules)
  - [After theming-components Skill](#after-theming-components-skill)
  - [After designing-layouts Skill](#after-designing-layouts-skill)
  - [After creating-dashboards Skill](#after-creating-dashboards-skill)
  - [After visualizing-data Skill](#after-visualizing-data-skill)
  - [After providing-feedback Skill](#after-providing-feedback-skill)
- [Validation Checklist (Library-Specific)](#validation-checklist-library-specific)
  - [Token Compliance](#token-compliance)
  - [Theme System](#theme-system)
  - [Component Integration](#component-integration)
  - [Accessibility](#accessibility)
- [Common Integration Patterns](#common-integration-patterns)
  - [Theme Toggle Button](#theme-toggle-button)
  - [KPI Card with Severity](#kpi-card-with-severity)
  - [Toast Notifications](#toast-notifications)
- [Version Compatibility](#version-compatibility)
- [Summary](#summary)

## Why This Context Matters

LLMs are already proficient at general application assembly. This skill's unique value comes from:

1. **Library-Specific Knowledge** - Understanding our exact component outputs
2. **Token System Mastery** - Knowing our precise naming conventions
3. **Skill Chain Awareness** - Understanding what each skill produces
4. **Integration Intelligence** - Knowing how our components connect

---

## Skill Chain Architecture

### Standard Skill Chain Flow

```
┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│  theming-   │────▶│  designing- │────▶│  creating-  │
│  components │     │  layouts    │     │  dashboards │
└─────────────┘     └─────────────┘     └─────────────┘
       │                   │                   │
       ▼                   ▼                   ▼
   tokens.css         Layout.tsx         Dashboard.tsx
   globals.css        Header.tsx         KPICard.tsx
                      Sidebar.tsx
       │                   │                   │
       └───────────────────┴───────────────────┘
                           │
                           ▼
               ┌───────────────────────┐
               │  visualizing-data     │
               │  (data-viz skill)     │
               └───────────────────────┘
                           │
                           ▼
                   DonutChart.tsx
                   BarChart.tsx
                   LineChart.tsx
                           │
                           ▼
               ┌───────────────────────┐
               │  providing-feedback   │
               └───────────────────────┘
                           │
                           ▼
                    Toast.tsx
                    Spinner.tsx
                    EmptyState.tsx
                           │
                           ▼
               ┌───────────────────────┐
               │ ASSEMBLING-COMPONENTS │
               │    (THIS SKILL)       │
               └───────────────────────┘
                           │
                           ▼
                 WORKING COMPONENT SYSTEM
```

### Skill Outputs Reference

| Skill | Primary Outputs | Token Dependencies |
|-------|-----------------|-------------------|
| `theming-components` | tokens.css, theme-provider.tsx | Foundation - no deps |
| `designing-layouts` | Layout.tsx, Header.tsx, grid CSS | Spacing, borders |
| `creating-dashboards` | Dashboard.tsx, grid structures | All layout tokens |
| `visualizing-data` | Chart components, legends | Colors, typography |
| `building-forms` | Form inputs, validation | Spacing, borders |
| `building-tables` | Table components, pagination | Colors, spacing |
| `providing-feedback` | Toast, Spinner, EmptyState | Colors, shadows |

---

## Token System Reference

### Token Naming Conventions

Our library uses a **semantic token architecture** with these categories:

#### Color Tokens
```css
/* Brand colors (source of truth) */
--color-cyber-orange: #FA582D;
--color-prisma-blue: #00C0E8;
--color-cortex-green: #00CC66;
--color-strata-yellow: #FFCB06;
--color-unit42-red: #C84727;

/* Semantic mappings */
--color-primary: var(--color-cyber-orange);
--color-success: var(--color-cortex-green);
--color-warning: var(--color-strata-yellow);
--color-error: var(--color-unit42-red);
--color-info: var(--color-prisma-blue);

/* Surface colors */
--color-bg-primary: #FFFFFF;      /* Main background */
--color-bg-secondary: #F8FAFC;    /* Elevated surfaces */
--color-bg-tertiary: #F1F5F9;     /* Subtle backgrounds */
--color-bg-elevated: #FFFFFF;     /* Cards, modals */

/* Text colors */
--color-text-primary: #1E293B;    /* Headings, body */
--color-text-secondary: #64748B;  /* Descriptions */
--color-text-tertiary: #94A3B8;   /* Muted text */
--color-text-inverse: #FFFFFF;    /* On dark backgrounds */
```

#### Spacing Tokens
```css
/* Base scale (4px unit) */
--space-1: 0.25rem;   /* 4px - xs */
--space-2: 0.5rem;    /* 8px - sm */
--space-3: 0.75rem;   /* 12px */
--space-4: 1rem;      /* 16px - md */
--space-6: 1.5rem;    /* 24px - lg */
--space-8: 2rem;      /* 32px - xl */
--space-12: 3rem;     /* 48px - 2xl */

/* Semantic aliases */
--spacing-xs: var(--space-1);
--spacing-sm: var(--space-2);
--spacing-md: var(--space-4);
--spacing-lg: var(--space-6);
--spacing-xl: var(--space-8);
--spacing-2xl: var(--space-12);
```

#### Component Size Tokens
```css
/* Icons */
--icon-size-sm: 1rem;      /* 16px */
--icon-size-md: 1.5rem;    /* 24px */
--icon-size-lg: 2rem;      /* 32px */
--icon-size-xl: 3rem;      /* 48px */

/* Buttons */
--button-height-sm: 2rem;
--button-height-md: 2.5rem;
--button-height-lg: 3rem;

/* Cards/Charts */
--min-height-card: 140px;
--min-height-chart: 200px;
```

---

## Component Integration Patterns

### Import Chain (Critical Order)

```typescript
// src/main.tsx - CORRECT ORDER
import './styles/tokens.css'      // 1. Tokens first!
import './styles/globals.css'     // 2. Global resets
import './styles/components.css'  // 3. Component styles

import { ThemeProvider } from '@/context/theme-provider'
import App from './App'
```

### Component Directory Structure

```
src/components/
├── ui/                     # From theming-components, forms skills
│   ├── button.tsx
│   ├── input.tsx
│   ├── card.tsx
│   └── index.ts           # Barrel export
├── layout/                 # From designing-layouts skill
│   ├── header.tsx
│   ├── sidebar.tsx
│   ├── footer.tsx
│   └── index.ts
├── charts/                 # From visualizing-data skill
│   ├── donut-chart.tsx
│   ├── bar-chart.tsx
│   ├── line-chart.tsx
│   └── index.ts
├── feedback/               # From providing-feedback skill
│   ├── toast.tsx
│   ├── spinner.tsx
│   ├── empty-state.tsx
│   └── index.ts
└── features/               # Domain-specific compositions
    └── dashboard/
        ├── kpi-card.tsx
        ├── dashboard.tsx
        └── index.ts
```

### State Integration Patterns

```typescript
// Theme context - always at root
<ThemeProvider>
  <App />
</ThemeProvider>

// Toast context - for notifications
<ToastProvider>
  <ThemeProvider>
    <App />
  </ThemeProvider>
</ToastProvider>
```

---

## Skill-Specific Assembly Rules

### After theming-components Skill

**Expected outputs:**
- `tokens.css` with complete token definitions
- Dark theme via `[data-theme="dark"]` selector
- Reduced motion support via `@media (prefers-reduced-motion)`

**Assembly actions:**
1. Verify tokens.css has all 7 categories (colors, spacing, typography, borders, shadows, motion, z-index)
2. Create theme-provider.tsx if not present
3. Ensure index.html has no `data-theme` attribute (let JS handle it)

### After designing-layouts Skill

**Expected outputs:**
- Layout components (Header, Sidebar, Footer)
- CSS Grid/Flexbox patterns
- Responsive breakpoints

**Assembly actions:**
1. Wire layout components into App.tsx
2. Verify layout CSS uses spacing tokens (not px values)
3. Check responsive classes use correct breakpoints

### After creating-dashboards Skill

**Expected outputs:**
- Dashboard.tsx with grid layout
- KPI cards with trend indicators
- Section organization

**Assembly actions:**
1. Import chart components from visualizing-data
2. Wire data fetching/state management
3. Ensure loading states use Spinner from feedback

### After visualizing-data Skill

**Expected outputs:**
- Chart components (Donut, Bar, Line, etc.)
- Legend components
- Accessible chart markup

**Assembly actions:**
1. Verify chart colors use `--chart-color-*` tokens
2. Check legends use correct typography tokens
3. Ensure empty states are handled

### After providing-feedback Skill

**Expected outputs:**
- Toast/notification system
- Loading spinners
- Empty states
- Error boundaries

**Assembly actions:**
1. Create ToastProvider context
2. Wire toast system to API error handlers
3. Add loading spinners to async operations

---

## Validation Checklist (Library-Specific)

### Token Compliance
- [ ] All colors use `--color-*` tokens (not hex/rgb)
- [ ] All spacing uses `--spacing-*` or `--space-*` tokens
- [ ] All typography uses `--font-size-*`, `--font-weight-*` tokens
- [ ] All radii use `--radius-*` tokens
- [ ] All shadows use `--shadow-*` tokens
- [ ] All transitions use `--transition-*` or `--duration-*` tokens
- [ ] All z-indices use `--z-*` tokens

### Theme System
- [ ] Theme toggle updates `data-theme` attribute on `<html>`
- [ ] Dark theme has all required color overrides
- [ ] System preference detection works
- [ ] Theme persists in localStorage

### Component Integration
- [ ] All component CSS imports tokens.css (or inherits)
- [ ] Barrel exports exist for each component directory
- [ ] No circular imports
- [ ] TypeScript types are exported

### Accessibility
- [ ] `prefers-reduced-motion` disables animations
- [ ] Focus states use `--color-border-focus` or `--shadow-focus`
- [ ] Color contrast meets WCAG 2.1 AA
- [ ] Interactive elements have focus-visible styles

---

## Common Integration Patterns

### Theme Toggle Button
```typescript
// Uses our token system
function ThemeToggle() {
  const { theme, setTheme } = useTheme()

  return (
    <button
      className="theme-toggle"
      onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')}
      aria-label={`Switch to ${theme === 'dark' ? 'light' : 'dark'} mode`}
    >
      {theme === 'dark' ? '☀️' : '🌙'}
    </button>
  )
}
```

```css
.theme-toggle {
  width: var(--button-height-md);
  height: var(--button-height-md);
  background: var(--color-bg-tertiary);
  border: var(--border-width-thin) solid var(--color-border-primary);
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: var(--transition-fast);
}

.theme-toggle:hover {
  background: var(--color-bg-secondary);
}
```

### KPI Card with Severity
```typescript
interface KPICardProps {
  severity: 'critical' | 'high' | 'medium' | 'low' | 'info'
  // ...
}

function KPICard({ severity, ...props }: KPICardProps) {
  return (
    <div className={`kpi-card kpi-card--${severity}`}>
      {/* Uses severity-specific tokens */}
    </div>
  )
}
```

### Toast Notifications
```typescript
// Toast types map to our semantic colors
type ToastType = 'success' | 'error' | 'warning' | 'info'

function Toast({ type, message }: { type: ToastType; message: string }) {
  return (
    <div className={`toast toast--${type}`}>
      <div className="toast__icon">{icons[type]}</div>
      <div className="toast__content">{message}</div>
    </div>
  )
}
```

---

## Version Compatibility

| AI Design Components | React | Next.js | Python | Rust |
|---------------------|-------|---------|--------|------|
| v0.2.x | 18.x | 14.x, 15.x | 3.11+ | 1.75+ |

---

## Summary

This skill is **not** about generic app assembly - it's about understanding our specific design library's:

1. **14 component skills** and what each produces
2. **Token system** with precise naming conventions
3. **Skill chain workflow** and expected outputs at each step
4. **Integration patterns** unique to our library

The validation scripts and assembly rules encode this library-specific knowledge, ensuring consistent, token-compliant applications regardless of the target ecosystem.

```

### references/react-vite-template.md

```markdown
# React + Vite Template

> Complete scaffolding template for single-page applications using Vite and React with TypeScript.


## Table of Contents

- [Project Structure](#project-structure)
- [Core Files](#core-files)
  - [index.html](#indexhtml)
  - [package.json](#packagejson)
  - [vite.config.ts](#viteconfigts)
  - [tsconfig.json](#tsconfigjson)
  - [tsconfig.node.json](#tsconfignodejson)
  - [src/main.tsx](#srcmaintsx)
  - [src/App.tsx](#srcapptsx)
  - [src/context/theme-provider.tsx](#srccontexttheme-providertsx)
  - [src/lib/utils.ts](#srclibutilsts)
- [Barrel Export Pattern](#barrel-export-pattern)
- [Commands](#commands)
- [Integration Checklist](#integration-checklist)

## Project Structure

```
project-name/
├── index.html                 # Entry point
├── package.json               # Dependencies and scripts
├── tsconfig.json              # TypeScript configuration
├── tsconfig.node.json         # Node-specific TypeScript config
├── vite.config.ts             # Vite configuration
├── public/
│   └── favicon.svg
└── src/
    ├── main.tsx               # React bootstrap
    ├── App.tsx                # Root component
    ├── styles/
    │   ├── tokens.css         # Design tokens (FIRST import)
    │   └── globals.css        # Global resets
    ├── context/
    │   └── theme-provider.tsx # Theme context
    ├── components/
    │   ├── ui/                # Shared UI components
    │   │   ├── button.tsx
    │   │   ├── card.tsx
    │   │   └── index.ts       # Barrel export
    │   ├── layout/            # Layout components
    │   │   ├── header.tsx
    │   │   ├── sidebar.tsx
    │   │   └── index.ts
    │   ├── charts/            # Data visualization
    │   │   ├── donut-chart.tsx
    │   │   └── index.ts
    │   ├── feedback/          # Feedback components
    │   │   ├── toast.tsx
    │   │   ├── spinner.tsx
    │   │   └── index.ts
    │   └── features/          # Feature components
    │       └── dashboard/
    │           ├── kpi-card.tsx
    │           ├── dashboard.tsx
    │           └── index.ts
    ├── hooks/
    │   └── use-theme.ts
    ├── lib/
    │   └── utils.ts
    └── types/
        └── index.ts
```

## Core Files

### index.html

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="description" content="{{PROJECT_DESCRIPTION}}" />
    <title>{{PROJECT_TITLE}}</title>
    <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
  </head>
  <body>
    <div id="root"></div>
    <script type="module" src="/src/main.tsx"></script>
  </body>
</html>
```

### package.json

```json
{
  "name": "{{PROJECT_NAME}}",
  "private": true,
  "version": "1.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "tsc && vite build",
    "preview": "vite preview",
    "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
    "validate:tokens": "python scripts/validate_tokens.py src"
  },
  "dependencies": {
    "react": "^18.3.1",
    "react-dom": "^18.3.1"
  },
  "devDependencies": {
    "@types/react": "^18.3.0",
    "@types/react-dom": "^18.3.0",
    "@vitejs/plugin-react": "^4.3.0",
    "typescript": "^5.4.0",
    "vite": "^5.4.0"
  }
}
```

### vite.config.ts

```typescript
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import path from 'path'

export default defineConfig({
  plugins: [react()],
  resolve: {
    alias: {
      '@': path.resolve(__dirname, './src'),
    },
  },
  css: {
    devSourcemap: true,
  },
  build: {
    sourcemap: true,
  },
})
```

### tsconfig.json

```json
{
  "compilerOptions": {
    "target": "ES2020",
    "useDefineForClassFields": true,
    "lib": ["ES2020", "DOM", "DOM.Iterable"],
    "module": "ESNext",
    "skipLibCheck": true,
    "moduleResolution": "bundler",
    "allowImportingTsExtensions": true,
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx",
    "strict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noFallthroughCasesInSwitch": true,
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"]
    }
  },
  "include": ["src"],
  "references": [{ "path": "./tsconfig.node.json" }]
}
```

### tsconfig.node.json

```json
{
  "compilerOptions": {
    "composite": true,
    "skipLibCheck": true,
    "module": "ESNext",
    "moduleResolution": "bundler",
    "allowSyntheticDefaultImports": true,
    "strict": true
  },
  "include": ["vite.config.ts"]
}
```

### src/main.tsx

```tsx
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import { ThemeProvider } from '@/context/theme-provider'
import App from './App'

// CRITICAL: Import order matters!
import './styles/tokens.css'   // 1. Design tokens FIRST
import './styles/globals.css'  // 2. Global resets

createRoot(document.getElementById('root')!).render(
  <StrictMode>
    <ThemeProvider>
      <App />
    </ThemeProvider>
  </StrictMode>,
)
```

### src/App.tsx

```tsx
import { Header, Sidebar } from '@/components/layout'
import { Dashboard } from '@/components/features/dashboard'
import './App.css'

function App() {
  return (
    <div className="app">
      <Header />
      <div className="app__body">
        <Sidebar />
        <main className="app__main">
          <Dashboard />
        </main>
      </div>
    </div>
  )
}

export default App
```

### src/context/theme-provider.tsx

```tsx
import { createContext, useContext, useEffect, useState, ReactNode } from 'react'

type Theme = 'light' | 'dark' | 'system'

interface ThemeContextType {
  theme: Theme
  setTheme: (theme: Theme) => void
}

const ThemeContext = createContext<ThemeContextType | undefined>(undefined)

export function ThemeProvider({ children }: { children: ReactNode }) {
  const [theme, setTheme] = useState<Theme>(() => {
    if (typeof window !== 'undefined') {
      return (localStorage.getItem('theme') as Theme) || 'system'
    }
    return 'system'
  })

  useEffect(() => {
    const root = window.document.documentElement
    root.removeAttribute('data-theme')

    if (theme === 'system') {
      const systemTheme = window.matchMedia('(prefers-color-scheme: dark)').matches
        ? 'dark'
        : 'light'
      root.setAttribute('data-theme', systemTheme)
    } else {
      root.setAttribute('data-theme', theme)
    }

    localStorage.setItem('theme', theme)
  }, [theme])

  // Listen for system theme changes
  useEffect(() => {
    if (theme !== 'system') return

    const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)')
    const handleChange = () => {
      const root = window.document.documentElement
      root.setAttribute('data-theme', mediaQuery.matches ? 'dark' : 'light')
    }

    mediaQuery.addEventListener('change', handleChange)
    return () => mediaQuery.removeEventListener('change', handleChange)
  }, [theme])

  return (
    <ThemeContext.Provider value={{ theme, setTheme }}>
      {children}
    </ThemeContext.Provider>
  )
}

export function useTheme() {
  const context = useContext(ThemeContext)
  if (!context) {
    throw new Error('useTheme must be used within ThemeProvider')
  }
  return context
}
```

### src/lib/utils.ts

```typescript
import { type ClassValue, clsx } from 'clsx'

/**
 * Utility for conditionally joining classNames together
 */
export function cn(...inputs: ClassValue[]) {
  return clsx(inputs)
}
```

## Barrel Export Pattern

Each component directory should have an index.ts file:

```typescript
// src/components/ui/index.ts
export { Button } from './button'
export { Card } from './card'
export { Input } from './input'

// src/components/layout/index.ts
export { Header } from './header'
export { Sidebar } from './sidebar'
export { Footer } from './footer'

// src/components/features/dashboard/index.ts
export { Dashboard } from './dashboard'
export { KPICard } from './kpi-card'
export { DonutChart } from './donut-chart'
```

## Commands

```bash
# Install dependencies
npm install

# Start development server
npm run dev

# Validate CSS tokens
npm run validate:tokens

# Production build
npm run build

# Preview production build
npm run preview
```

## Integration Checklist

- [ ] `tokens.css` imported before all other styles
- [ ] ThemeProvider wraps entire app
- [ ] All CSS uses token variables (no hardcoded values)
- [ ] Barrel exports exist for each component directory
- [ ] Path aliases configured (@/)
- [ ] TypeScript strict mode enabled
- [ ] Build completes without errors

```

### references/nextjs-template.md

```markdown
# Next.js 14/15 Template

> Complete scaffolding template for full-stack applications using Next.js App Router with TypeScript.


## Table of Contents

- [Project Structure](#project-structure)
- [Core Files](#core-files)
  - [package.json](#packagejson)
  - [next.config.mjs](#nextconfigmjs)
  - [tsconfig.json](#tsconfigjson)
  - [src/app/layout.tsx](#srcapplayouttsx)
  - [src/app/globals.css](#srcappglobalscss)
  - [src/app/page.tsx](#srcapppagetsx)
  - [src/context/theme-provider.tsx](#srccontexttheme-providertsx)
  - [src/app/api/health/route.ts](#srcappapihealthroutets)
- [Server Components vs Client Components](#server-components-vs-client-components)
  - [When to use Server Components (default)](#when-to-use-server-components-default)
  - [When to use Client Components](#when-to-use-client-components)
- [Commands](#commands)
- [Integration Checklist](#integration-checklist)

## Project Structure

```
project-name/
├── package.json
├── next.config.mjs
├── tsconfig.json
├── tailwind.config.ts         # Optional: if using Tailwind
├── postcss.config.mjs
├── .env.local
├── public/
│   ├── favicon.ico
│   └── images/
└── src/
    ├── app/
    │   ├── layout.tsx         # Root layout with providers
    │   ├── page.tsx           # Home page
    │   ├── globals.css        # Global styles + token imports
    │   ├── dashboard/
    │   │   └── page.tsx
    │   └── api/
    │       └── health/
    │           └── route.ts
    ├── components/
    │   ├── ui/
    │   │   ├── button.tsx
    │   │   ├── card.tsx
    │   │   └── index.ts
    │   ├── layout/
    │   │   ├── header.tsx
    │   │   ├── sidebar.tsx
    │   │   └── index.ts
    │   ├── charts/
    │   │   ├── donut-chart.tsx
    │   │   └── index.ts
    │   ├── feedback/
    │   │   ├── toast.tsx
    │   │   ├── spinner.tsx
    │   │   └── index.ts
    │   └── features/
    │       └── dashboard/
    │           ├── kpi-card.tsx
    │           ├── dashboard.tsx
    │           └── index.ts
    ├── lib/
    │   └── utils.ts
    ├── hooks/
    │   └── use-theme.ts
    ├── context/
    │   └── theme-provider.tsx
    ├── styles/
    │   └── tokens.css         # Design tokens
    └── types/
        └── index.ts
```

## Core Files

### package.json

```json
{
  "name": "{{PROJECT_NAME}}",
  "version": "1.0.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint",
    "validate:tokens": "python scripts/validate_tokens.py src"
  },
  "dependencies": {
    "next": "^14.2.0",
    "react": "^18.3.1",
    "react-dom": "^18.3.1"
  },
  "devDependencies": {
    "@types/node": "^20.0.0",
    "@types/react": "^18.3.0",
    "@types/react-dom": "^18.3.0",
    "typescript": "^5.4.0"
  }
}
```

### next.config.mjs

```javascript
/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: true,
  // Enable experimental features if needed
  // experimental: {
  //   serverActions: true,
  // },
}

export default nextConfig
```

### tsconfig.json

```json
{
  "compilerOptions": {
    "target": "ES2020",
    "lib": ["dom", "dom.iterable", "esnext"],
    "allowJs": true,
    "skipLibCheck": true,
    "strict": true,
    "noEmit": true,
    "esModuleInterop": true,
    "module": "esnext",
    "moduleResolution": "bundler",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "preserve",
    "incremental": true,
    "plugins": [
      {
        "name": "next"
      }
    ],
    "paths": {
      "@/*": ["./src/*"]
    }
  },
  "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
  "exclude": ["node_modules"]
}
```

### src/app/layout.tsx

```tsx
import type { Metadata } from 'next'
import { ThemeProvider } from '@/context/theme-provider'

// CRITICAL: Import tokens first
import '@/styles/tokens.css'
import './globals.css'

export const metadata: Metadata = {
  title: '{{PROJECT_TITLE}}',
  description: '{{PROJECT_DESCRIPTION}}',
}

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en" suppressHydrationWarning>
      <body>
        <ThemeProvider
          attribute="data-theme"
          defaultTheme="system"
          enableSystem
        >
          {children}
        </ThemeProvider>
      </body>
    </html>
  )
}
```

### src/app/globals.css

```css
/*
 * Global styles - tokens.css is imported in layout.tsx before this
 * All styles here should use CSS variables from tokens.css
 */

*,
*::before,
*::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  font-family: var(--font-sans);
  font-size: var(--font-size-base);
  line-height: var(--line-height-normal);
  color: var(--color-text-primary);
  background: var(--color-bg-primary);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

body {
  min-height: 100vh;
}

/* Focus states for accessibility */
:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}

/* Reduced motion support */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}
```

### src/app/page.tsx

```tsx
import { Header, Sidebar } from '@/components/layout'
import { Dashboard } from '@/components/features/dashboard'

export default function Home() {
  return (
    <div className="app">
      <Header />
      <div className="app__body">
        <Sidebar />
        <main className="app__main">
          <Dashboard />
        </main>
      </div>
    </div>
  )
}
```

### src/context/theme-provider.tsx

```tsx
'use client'

import { createContext, useContext, useEffect, useState, ReactNode } from 'react'

type Theme = 'light' | 'dark' | 'system'

interface ThemeContextType {
  theme: Theme
  setTheme: (theme: Theme) => void
}

const ThemeContext = createContext<ThemeContextType | undefined>(undefined)

interface ThemeProviderProps {
  children: ReactNode
  attribute?: string
  defaultTheme?: Theme
  enableSystem?: boolean
}

export function ThemeProvider({
  children,
  attribute = 'data-theme',
  defaultTheme = 'system',
  enableSystem = true,
}: ThemeProviderProps) {
  const [theme, setTheme] = useState<Theme>(defaultTheme)
  const [mounted, setMounted] = useState(false)

  useEffect(() => {
    setMounted(true)
    const stored = localStorage.getItem('theme') as Theme | null
    if (stored) {
      setTheme(stored)
    }
  }, [])

  useEffect(() => {
    if (!mounted) return

    const root = window.document.documentElement

    if (theme === 'system' && enableSystem) {
      const systemTheme = window.matchMedia('(prefers-color-scheme: dark)').matches
        ? 'dark'
        : 'light'
      root.setAttribute(attribute, systemTheme)
    } else {
      root.setAttribute(attribute, theme)
    }

    localStorage.setItem('theme', theme)
  }, [theme, mounted, attribute, enableSystem])

  // Prevent flash of incorrect theme
  if (!mounted) {
    return null
  }

  return (
    <ThemeContext.Provider value={{ theme, setTheme }}>
      {children}
    </ThemeContext.Provider>
  )
}

export function useTheme() {
  const context = useContext(ThemeContext)
  if (!context) {
    throw new Error('useTheme must be used within ThemeProvider')
  }
  return context
}
```

### src/app/api/health/route.ts

```typescript
import { NextResponse } from 'next/server'

export async function GET() {
  return NextResponse.json({
    status: 'ok',
    timestamp: new Date().toISOString(),
  })
}
```

## Server Components vs Client Components

### When to use Server Components (default)

- Fetching data from APIs
- Accessing backend resources directly
- Keeping sensitive information on server
- Large dependencies that should stay on server

```tsx
// app/dashboard/page.tsx (Server Component)
async function getData() {
  const res = await fetch('https://api.example.com/data')
  return res.json()
}

export default async function DashboardPage() {
  const data = await getData()
  return <Dashboard data={data} />
}
```

### When to use Client Components

- Interactivity (onClick, onChange, etc.)
- Browser APIs (localStorage, window, etc.)
- React hooks (useState, useEffect, useContext)
- Custom hooks that use state

```tsx
'use client'

// components/ui/button.tsx
import { useState } from 'react'

export function Button({ children, onClick }) {
  const [isLoading, setIsLoading] = useState(false)
  // ...
}
```

## Commands

```bash
# Install dependencies
npm install

# Start development server
npm run dev

# Validate CSS tokens
npm run validate:tokens

# Production build
npm run build

# Start production server
npm run start
```

## Integration Checklist

- [ ] `tokens.css` imported in layout.tsx before globals.css
- [ ] ThemeProvider wraps entire app with `'use client'`
- [ ] `suppressHydrationWarning` on html tag
- [ ] All CSS uses token variables
- [ ] Barrel exports exist for component directories
- [ ] Path aliases configured (@/)
- [ ] Server vs Client components properly separated
- [ ] Build completes without errors

```

### references/python-fastapi-template.md

```markdown
# Python FastAPI Template

> Complete scaffolding template for modern async APIs using FastAPI with Pydantic validation.


## Table of Contents

- [Project Structure](#project-structure)
- [Core Files](#core-files)
  - [pyproject.toml](#pyprojecttoml)
  - [requirements.txt](#requirementstxt)
  - [src/project_name/main.py](#srcproject_namemainpy)
  - [src/project_name/config.py](#srcproject_nameconfigpy)
  - [src/project_name/api/routes/health.py](#srcproject_nameapirouteshealthpy)
  - [src/project_name/api/routes/dashboard.py](#srcproject_nameapiroutesdashboardpy)
  - [src/project_name/templates/base.html](#srcproject_nametemplatesbasehtml)
  - [src/project_name/templates/dashboard.html](#srcproject_nametemplatesdashboardhtml)
  - [Dockerfile](#dockerfile)
  - [docker-compose.yml](#docker-composeyml)
- [Commands](#commands)
- [Integration Checklist](#integration-checklist)

## Project Structure

```
project-name/
├── pyproject.toml             # Modern Python packaging
├── requirements.txt           # Production dependencies
├── requirements-dev.txt       # Development dependencies
├── .env                       # Environment variables
├── .env.example              # Example environment file
├── Dockerfile
├── docker-compose.yml
├── src/
│   └── project_name/          # Main package
│       ├── __init__.py
│       ├── main.py            # Application entry point
│       ├── config.py          # Configuration management
│       ├── api/               # API routes
│       │   ├── __init__.py
│       │   ├── dependencies.py
│       │   └── routes/
│       │       ├── __init__.py
│       │       ├── dashboard.py
│       │       └── health.py
│       ├── core/              # Core business logic
│       │   ├── __init__.py
│       │   └── security.py
│       ├── models/            # Data models
│       │   ├── __init__.py
│       │   ├── schemas.py     # Pydantic schemas
│       │   └── database.py    # SQLAlchemy models
│       ├── services/          # Business logic services
│       │   ├── __init__.py
│       │   └── dashboard_service.py
│       ├── static/            # Static files (CSS, JS)
│       │   ├── css/
│       │   │   └── tokens.css
│       │   └── js/
│       └── templates/         # Jinja2 templates
│           ├── base.html
│           └── dashboard.html
├── tests/
│   ├── __init__.py
│   ├── conftest.py
│   └── test_dashboard.py
└── scripts/
    └── validate_tokens.py
```

## Core Files

### pyproject.toml

```toml
[project]
name = "{{PROJECT_NAME}}"
version = "1.0.0"
description = "{{PROJECT_DESCRIPTION}}"
readme = "README.md"
requires-python = ">=3.11"
dependencies = [
    "fastapi>=0.109.0",
    "uvicorn[standard]>=0.27.0",
    "pydantic>=2.5.0",
    "pydantic-settings>=2.1.0",
    "python-dotenv>=1.0.0",
    "jinja2>=3.1.0",
]

[project.optional-dependencies]
dev = [
    "pytest>=7.4.0",
    "pytest-asyncio>=0.23.0",
    "httpx>=0.26.0",
    "ruff>=0.1.0",
    "mypy>=1.8.0",
]

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[tool.hatch.build.targets.wheel]
packages = ["src/project_name"]

[tool.ruff]
line-length = 88
target-version = "py311"

[tool.mypy]
python_version = "3.11"
strict = true
```

### requirements.txt

```
fastapi>=0.109.0
uvicorn[standard]>=0.27.0
pydantic>=2.5.0
pydantic-settings>=2.1.0
python-dotenv>=1.0.0
jinja2>=3.1.0
```

### src/project_name/main.py

```python
"""FastAPI application entry point."""

from contextlib import asynccontextmanager
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates

from .api.routes import dashboard, health
from .config import settings


@asynccontextmanager
async def lifespan(app: FastAPI):
    """Application lifespan events."""
    # Startup
    print(f"Starting {settings.app_name}...")
    yield
    # Shutdown
    print("Shutting down...")


def create_app() -> FastAPI:
    """Create and configure the FastAPI application."""
    app = FastAPI(
        title=settings.app_name,
        version=settings.version,
        lifespan=lifespan,
    )

    # Mount static files
    app.mount("/static", StaticFiles(directory="src/project_name/static"), name="static")

    # Include routers
    app.include_router(health.router, prefix="/api", tags=["health"])
    app.include_router(dashboard.router, prefix="/api", tags=["dashboard"])

    return app


app = create_app()


if __name__ == "__main__":
    import uvicorn
    uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)
```

### src/project_name/config.py

```python
"""Application configuration using Pydantic Settings."""

from pydantic_settings import BaseSettings, SettingsConfigDict


class Settings(BaseSettings):
    """Application settings."""

    model_config = SettingsConfigDict(
        env_file=".env",
        env_file_encoding="utf-8",
        case_sensitive=False,
    )

    # Application
    app_name: str = "{{PROJECT_NAME}}"
    version: str = "1.0.0"
    debug: bool = False

    # Server
    host: str = "0.0.0.0"
    port: int = 8000

    # Database (if needed)
    # database_url: str = "sqlite:///./app.db"


settings = Settings()
```

### src/project_name/api/routes/health.py

```python
"""Health check routes."""

from datetime import datetime
from fastapi import APIRouter
from pydantic import BaseModel


router = APIRouter()


class HealthResponse(BaseModel):
    """Health check response model."""

    status: str
    timestamp: datetime
    version: str


@router.get("/health", response_model=HealthResponse)
async def health_check() -> HealthResponse:
    """Check API health status."""
    from ...config import settings

    return HealthResponse(
        status="ok",
        timestamp=datetime.now(),
        version=settings.version,
    )
```

### src/project_name/api/routes/dashboard.py

```python
"""Dashboard routes."""

from fastapi import APIRouter, Request
from fastapi.templating import Jinja2Templates
from pydantic import BaseModel


router = APIRouter()
templates = Jinja2Templates(directory="src/project_name/templates")


class KPIData(BaseModel):
    """KPI data model."""

    label: str
    value: int
    trend: float
    trend_direction: str


class DashboardData(BaseModel):
    """Dashboard data model."""

    kpis: list[KPIData]


@router.get("/dashboard")
async def get_dashboard(request: Request):
    """Render dashboard page."""
    return templates.TemplateResponse(
        "dashboard.html",
        {
            "request": request,
            "theme": "light",
            "title": "Dashboard",
        }
    )


@router.get("/dashboard/data", response_model=DashboardData)
async def get_dashboard_data() -> DashboardData:
    """Get dashboard data as JSON."""
    return DashboardData(
        kpis=[
            KPIData(label="Total Threats", value=1234, trend=15.3, trend_direction="up"),
            KPIData(label="Blocked Attacks", value=892, trend=8.2, trend_direction="up"),
            KPIData(label="Active Alerts", value=23, trend=-5.1, trend_direction="down"),
        ]
    )
```

### src/project_name/templates/base.html

```html
<!DOCTYPE html>
<html lang="en" data-theme="{{ theme | default('light') }}">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>{{ title }} - {{PROJECT_NAME}}</title>

  <!-- Design tokens FIRST -->
  <link rel="stylesheet" href="{{ url_for('static', path='css/tokens.css') }}">
  <!-- Component styles -->
  <link rel="stylesheet" href="{{ url_for('static', path='css/dashboard.css') }}">

  <script>
    // Theme toggle
    (function() {
      const theme = localStorage.getItem('theme') || 'light';
      document.documentElement.setAttribute('data-theme', theme);
    })();
  </script>
</head>
<body>
  {% block content %}{% endblock %}

  <script>
    // Theme toggle button
    function toggleTheme() {
      const html = document.documentElement;
      const current = html.getAttribute('data-theme');
      const next = current === 'dark' ? 'light' : 'dark';
      html.setAttribute('data-theme', next);
      localStorage.setItem('theme', next);
    }
  </script>
</body>
</html>
```

### src/project_name/templates/dashboard.html

```html
{% extends "base.html" %}

{% block content %}
<div class="dashboard">
  <header class="dashboard__header">
    <h1>Dashboard</h1>
    <button onclick="toggleTheme()" class="theme-toggle">
      Toggle Theme
    </button>
  </header>

  <main class="dashboard__content">
    <section class="kpi-grid" id="kpi-container">
      <!-- KPI cards loaded via JavaScript -->
    </section>
  </main>
</div>

<script>
  // Fetch and render KPI data
  async function loadDashboard() {
    const response = await fetch('/api/dashboard/data');
    const data = await response.json();

    const container = document.getElementById('kpi-container');
    container.innerHTML = data.kpis.map(kpi => `
      <div class="kpi-card">
        <h3 class="kpi-card__label">${kpi.label}</h3>
        <div class="kpi-card__value">${kpi.value.toLocaleString()}</div>
        <div class="kpi-card__trend trend--${kpi.trend_direction === 'up' ? 'positive' : 'negative'}">
          ${kpi.trend_direction === 'up' ? '↑' : '↓'} ${Math.abs(kpi.trend)}%
        </div>
      </div>
    `).join('');
  }

  loadDashboard();
</script>
{% endblock %}
```

### Dockerfile

```dockerfile
FROM python:3.11-slim

WORKDIR /app

# Install dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Copy application
COPY src/ ./src/

# Run application
CMD ["uvicorn", "src.project_name.main:app", "--host", "0.0.0.0", "--port", "8000"]
```

### docker-compose.yml

```yaml
version: '3.8'

services:
  app:
    build: .
    ports:
      - "8000:8000"
    volumes:
      - ./src:/app/src
    environment:
      - DEBUG=true
    command: uvicorn src.project_name.main:app --host 0.0.0.0 --port 8000 --reload
```

## Commands

```bash
# Create virtual environment
python -m venv venv
source venv/bin/activate  # Linux/Mac
# venv\Scripts\activate   # Windows

# Install dependencies
pip install -e ".[dev]"

# Start development server
uvicorn src.project_name.main:app --reload

# Validate CSS tokens
python scripts/validate_tokens.py src/project_name/static

# Run tests
pytest

# Type checking
mypy src/

# Linting
ruff check src/
```

## Integration Checklist

- [ ] `tokens.css` exists in static/css/
- [ ] Templates load tokens.css before other styles
- [ ] Theme toggle updates `data-theme` attribute
- [ ] Pydantic models validate all API data
- [ ] Configuration uses pydantic-settings
- [ ] Tests cover critical endpoints
- [ ] Dockerfile builds successfully

```

### references/rust-axum-template.md

```markdown
# Rust Axum Template

> Complete scaffolding template for high-performance web applications using Axum with tower middleware.


## Table of Contents

- [Project Structure](#project-structure)
- [Core Files](#core-files)
  - [Cargo.toml](#cargotoml)
  - [src/main.rs](#srcmainrs)
  - [src/config.rs](#srcconfigrs)
  - [src/error.rs](#srcerrorrs)
  - [src/routes/mod.rs](#srcroutesmodrs)
  - [src/routes/health.rs](#srcrouteshealthrs)
  - [src/routes/dashboard.rs](#srcroutesdashboardrs)
  - [src/models/mod.rs](#srcmodelsmodrs)
  - [src/models/dashboard.rs](#srcmodelsdashboardrs)
  - [templates/base.html (Tera)](#templatesbasehtml-tera)
  - [Dockerfile](#dockerfile)
  - [docker-compose.yml](#docker-composeyml)
- [Commands](#commands)
- [Integration Checklist](#integration-checklist)

## Project Structure

```
project-name/
├── Cargo.toml                 # Dependencies and metadata
├── Cargo.lock
├── .env                       # Environment variables
├── Dockerfile
├── docker-compose.yml
├── src/
│   ├── main.rs                # Application entry point
│   ├── lib.rs                 # Library crate (optional)
│   ├── config.rs              # Configuration
│   ├── error.rs               # Error handling
│   ├── routes/                # HTTP routes
│   │   ├── mod.rs
│   │   ├── dashboard.rs
│   │   └── health.rs
│   ├── handlers/              # Request handlers
│   │   ├── mod.rs
│   │   └── dashboard_handler.rs
│   ├── models/                # Data structures
│   │   ├── mod.rs
│   │   └── dashboard.rs
│   ├── services/              # Business logic
│   │   ├── mod.rs
│   │   └── dashboard_service.rs
│   └── middleware/            # Custom middleware
│       └── mod.rs
├── static/                    # Static assets
│   ├── css/
│   │   └── tokens.css
│   └── js/
├── templates/                 # Tera templates
│   ├── base.html
│   └── dashboard.html
└── tests/
    └── integration_tests.rs
```

## Core Files

### Cargo.toml

```toml
[package]
name = "{{PROJECT_NAME}}"
version = "1.0.0"
edition = "2021"
authors = ["{{AUTHOR}}"]
description = "{{PROJECT_DESCRIPTION}}"

[dependencies]
# Web framework
axum = "0.7"
tokio = { version = "1.35", features = ["full"] }
tower = "0.4"
tower-http = { version = "0.5", features = ["fs", "trace", "cors"] }

# Serialization
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"

# Configuration
dotenvy = "0.15"
config = "0.14"

# Templating
tera = "1.19"

# Tracing
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }

# Error handling
thiserror = "1.0"
anyhow = "1.0"

[dev-dependencies]
axum-test = "14.0"
```

### src/main.rs

```rust
//! Application entry point.

mod config;
mod error;
mod handlers;
mod models;
mod routes;
mod services;

use axum::Router;
use std::net::SocketAddr;
use tower_http::services::ServeDir;
use tower_http::trace::TraceLayer;
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};

use crate::config::Config;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // Initialize tracing
    tracing_subscriber::registry()
        .with(tracing_subscriber::EnvFilter::try_from_default_env()
            .unwrap_or_else(|_| "info".into()))
        .with(tracing_subscriber::fmt::layer())
        .init();

    // Load configuration
    let config = Config::from_env()?;
    tracing::info!("Starting {} v{}", config.app_name, config.version);

    // Build application
    let app = Router::new()
        .merge(routes::create_router())
        .nest_service("/static", ServeDir::new("static"))
        .layer(TraceLayer::new_for_http());

    // Run server
    let addr = SocketAddr::from(([0, 0, 0, 0], config.port));
    tracing::info!("Listening on {}", addr);

    let listener = tokio::net::TcpListener::bind(addr).await?;
    axum::serve(listener, app).await?;

    Ok(())
}
```

### src/config.rs

```rust
//! Application configuration.

use serde::Deserialize;

#[derive(Debug, Deserialize)]
pub struct Config {
    #[serde(default = "default_app_name")]
    pub app_name: String,

    #[serde(default = "default_version")]
    pub version: String,

    #[serde(default = "default_port")]
    pub port: u16,

    #[serde(default)]
    pub debug: bool,
}

fn default_app_name() -> String {
    "{{PROJECT_NAME}}".into()
}

fn default_version() -> String {
    "1.0.0".into()
}

fn default_port() -> u16 {
    3000
}

impl Config {
    pub fn from_env() -> anyhow::Result<Self> {
        dotenvy::dotenv().ok();

        let config = config::Config::builder()
            .add_source(config::Environment::default())
            .build()?;

        Ok(config.try_deserialize()?)
    }
}
```

### src/error.rs

```rust
//! Application error types.

use axum::{
    http::StatusCode,
    response::{IntoResponse, Response},
    Json,
};
use serde_json::json;
use thiserror::Error;

#[derive(Debug, Error)]
pub enum AppError {
    #[error("Not found: {0}")]
    NotFound(String),

    #[error("Bad request: {0}")]
    BadRequest(String),

    #[error("Internal server error")]
    InternalError(#[from] anyhow::Error),
}

impl IntoResponse for AppError {
    fn into_response(self) -> Response {
        let (status, message) = match &self {
            AppError::NotFound(msg) => (StatusCode::NOT_FOUND, msg.clone()),
            AppError::BadRequest(msg) => (StatusCode::BAD_REQUEST, msg.clone()),
            AppError::InternalError(_) => {
                tracing::error!("Internal error: {:?}", self);
                (StatusCode::INTERNAL_SERVER_ERROR, "Internal server error".into())
            }
        };

        let body = Json(json!({
            "error": message,
            "status": status.as_u16(),
        }));

        (status, body).into_response()
    }
}
```

### src/routes/mod.rs

```rust
//! Route definitions.

pub mod dashboard;
pub mod health;

use axum::{routing::get, Router};

pub fn create_router() -> Router {
    Router::new()
        .route("/api/health", get(health::health_check))
        .route("/api/dashboard", get(dashboard::get_dashboard))
        .route("/api/dashboard/data", get(dashboard::get_dashboard_data))
}
```

### src/routes/health.rs

```rust
//! Health check routes.

use axum::Json;
use serde::Serialize;

#[derive(Serialize)]
pub struct HealthResponse {
    status: String,
    version: String,
}

pub async fn health_check() -> Json<HealthResponse> {
    Json(HealthResponse {
        status: "ok".into(),
        version: env!("CARGO_PKG_VERSION").into(),
    })
}
```

### src/routes/dashboard.rs

```rust
//! Dashboard routes.

use axum::Json;

use crate::models::dashboard::{DashboardData, KpiData};

pub async fn get_dashboard() -> &'static str {
    // In production, render a template here
    "Dashboard"
}

pub async fn get_dashboard_data() -> Json<DashboardData> {
    Json(DashboardData {
        kpis: vec![
            KpiData {
                label: "Total Threats".into(),
                value: 1234,
                trend: 15.3,
                trend_direction: "up".into(),
            },
            KpiData {
                label: "Blocked Attacks".into(),
                value: 892,
                trend: 8.2,
                trend_direction: "up".into(),
            },
            KpiData {
                label: "Active Alerts".into(),
                value: 23,
                trend: -5.1,
                trend_direction: "down".into(),
            },
        ],
    })
}
```

### src/models/mod.rs

```rust
//! Data models.

pub mod dashboard;
```

### src/models/dashboard.rs

```rust
//! Dashboard data models.

use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct KpiData {
    pub label: String,
    pub value: i64,
    pub trend: f64,
    pub trend_direction: String,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DashboardData {
    pub kpis: Vec<KpiData>,
}
```

### templates/base.html (Tera)

```html
<!DOCTYPE html>
<html lang="en" data-theme="{{ theme | default(value='light') }}">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>{{ title }} - {{PROJECT_NAME}}</title>

  <!-- Design tokens FIRST -->
  <link rel="stylesheet" href="/static/css/tokens.css">
  <link rel="stylesheet" href="/static/css/dashboard.css">

  <script>
    (function() {
      const theme = localStorage.getItem('theme') || 'light';
      document.documentElement.setAttribute('data-theme', theme);
    })();
  </script>
</head>
<body>
  {% block content %}{% endblock %}

  <script>
    function toggleTheme() {
      const html = document.documentElement;
      const current = html.getAttribute('data-theme');
      const next = current === 'dark' ? 'light' : 'dark';
      html.setAttribute('data-theme', next);
      localStorage.setItem('theme', next);
    }
  </script>
</body>
</html>
```

### Dockerfile

```dockerfile
# Build stage
FROM rust:1.75-slim as builder

WORKDIR /app
COPY . .
RUN cargo build --release

# Runtime stage
FROM debian:bookworm-slim

WORKDIR /app

# Copy binary
COPY --from=builder /app/target/release/{{PROJECT_NAME}} .

# Copy static files and templates
COPY static/ ./static/
COPY templates/ ./templates/

# Run
EXPOSE 3000
CMD ["./{{PROJECT_NAME}}"]
```

### docker-compose.yml

```yaml
version: '3.8'

services:
  app:
    build: .
    ports:
      - "3000:3000"
    volumes:
      - ./static:/app/static
      - ./templates:/app/templates
    environment:
      - RUST_LOG=info
      - PORT=3000
```

## Commands

```bash
# Build
cargo build

# Run development server (with auto-reload using cargo-watch)
cargo watch -x run

# Validate CSS tokens
python scripts/validate_tokens.py static

# Run tests
cargo test

# Production build
cargo build --release

# Format code
cargo fmt

# Lint
cargo clippy
```

## Integration Checklist

- [ ] `tokens.css` exists in static/css/
- [ ] Templates load tokens.css before other styles
- [ ] Tower-http serves static files correctly
- [ ] Error types implement IntoResponse
- [ ] Tracing configured for observability
- [ ] Configuration loads from environment
- [ ] Dockerfile builds successfully
- [ ] Tests cover critical routes

```

### references/token-validation-rules.md

```markdown
# Token Validation Rules

> Complete reference for CSS design token validation rules used by `validate_tokens.py`.


## Table of Contents

- [Overview](#overview)
- [Severity Levels](#severity-levels)
- [Validation Rules](#validation-rules)
  - [1. Colors (Error)](#1-colors-error)
  - [2. Spacing (Error)](#2-spacing-error)
  - [3. Font Sizes (Error)](#3-font-sizes-error)
  - [4. Border Radius (Warning)](#4-border-radius-warning)
  - [5. Box Shadows (Warning)](#5-box-shadows-warning)
  - [6. Transitions (Info - Strict Mode Only)](#6-transitions-info-strict-mode-only)
  - [7. Z-Index (Warning)](#7-z-index-warning)
- [Exceptions (Always Allowed)](#exceptions-always-allowed)
  - [CSS Keywords](#css-keywords)
  - [Small Values](#small-values)
  - [Layout Values](#layout-values)
  - [Context-Specific](#context-specific)
  - [Exception Properties](#exception-properties)
- [Script Usage](#script-usage)
- [CI/CD Integration](#cicd-integration)
  - [GitHub Actions](#github-actions)
  - [Pre-commit Hook](#pre-commit-hook)
- [Output Example](#output-example)

## Overview

The token validation script scans CSS files for hardcoded values that should use design tokens. This ensures consistent theming and makes dark mode, brand customization, and accessibility features work correctly.

## Severity Levels

| Level | Meaning | CI/CD Impact |
|-------|---------|--------------|
| **Error** | Must fix before deployment | Build fails |
| **Warning** | Should fix but not blocking | Build succeeds |
| **Info** | Nice to have (strict mode only) | No impact |

## Validation Rules

### 1. Colors (Error)

**Pattern:** Hardcoded hex, rgb, rgba, hsl values

**Bad:**
```css
.button {
  background: #FA582D;
  color: rgb(30, 41, 59);
  border-color: rgba(0, 0, 0, 0.1);
}
```

**Good:**
```css
.button {
  background: var(--color-primary);
  color: var(--color-text-primary);
  border-color: var(--color-border-primary);
}
```

**Common Token Mappings:**

| Hardcoded | Token |
|-----------|-------|
| `#FA582D` | `--color-cyber-orange` / `--color-primary` |
| `#00C0E8` | `--color-prisma-blue` / `--color-info` |
| `#00CC66` | `--color-cortex-green` / `--color-success` |
| `#FFCB06` | `--color-strata-yellow` / `--color-warning` |
| `#C84727` | `--color-unit42-red` / `--color-error` |
| `#FFFFFF` | `--color-bg-primary` |
| `#F8FAFC` | `--color-bg-secondary` |
| `#1E293B` | `--color-text-primary` |
| `#64748B` | `--color-text-secondary` |

**Exceptions:**
- `currentColor` - CSS keyword
- `transparent` - CSS keyword
- `inherit` - CSS keyword

### 2. Spacing (Error)

**Pattern:** Hardcoded pixel values ≥ 4px on spacing properties

**Properties:** `padding`, `margin`, `gap`, `top`, `right`, `bottom`, `left`

**Bad:**
```css
.card {
  padding: 16px;
  margin-bottom: 24px;
  gap: 8px;
}
```

**Good:**
```css
.card {
  padding: var(--spacing-md);
  margin-bottom: var(--spacing-lg);
  gap: var(--spacing-sm);
}
```

**Token Scale:**

| Hardcoded | Token | Base Unit |
|-----------|-------|-----------|
| `4px` | `--spacing-xs` / `--space-1` | 1× |
| `8px` | `--spacing-sm` / `--space-2` | 2× |
| `12px` | `--space-3` | 3× |
| `16px` | `--spacing-md` / `--space-4` | 4× |
| `20px` | `--space-5` | 5× |
| `24px` | `--spacing-lg` / `--space-6` | 6× |
| `32px` | `--spacing-xl` / `--space-8` | 8× |
| `40px` | `--space-10` | 10× |
| `48px` | `--spacing-2xl` / `--space-12` | 12× |

**Exceptions:**
- `0`, `0px` - Zero values
- `1px` - Hairline borders
- `2px` - Focus outlines

### 3. Font Sizes (Error)

**Pattern:** Hardcoded font-size values

**Bad:**
```css
.title {
  font-size: 24px;
}
.body {
  font-size: 14px;
}
```

**Good:**
```css
.title {
  font-size: var(--font-size-2xl);
}
.body {
  font-size: var(--font-size-sm);
}
```

**Token Scale:**

| Hardcoded | Token | rem |
|-----------|-------|-----|
| `12px` | `--font-size-xs` | 0.75rem |
| `14px` | `--font-size-sm` | 0.875rem |
| `16px` | `--font-size-base` | 1rem |
| `18px` | `--font-size-lg` | 1.125rem |
| `20px` | `--font-size-xl` | 1.25rem |
| `24px` | `--font-size-2xl` | 1.5rem |
| `30px` | `--font-size-3xl` | 1.875rem |
| `36px` | `--font-size-4xl` | 2.25rem |

### 4. Border Radius (Warning)

**Pattern:** Hardcoded border-radius values

**Bad:**
```css
.button {
  border-radius: 8px;
}
.avatar {
  border-radius: 9999px;
}
```

**Good:**
```css
.button {
  border-radius: var(--radius-md);
}
.avatar {
  border-radius: var(--radius-full);
}
```

**Token Scale:**

| Hardcoded | Token |
|-----------|-------|
| `4px` | `--radius-sm` |
| `8px` | `--radius-md` |
| `12px` | `--radius-lg` |
| `16px` | `--radius-xl` |
| `9999px` | `--radius-full` |

### 5. Box Shadows (Warning)

**Pattern:** Hardcoded box-shadow values

**Bad:**
```css
.card {
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
}
.modal {
  box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
}
```

**Good:**
```css
.card {
  box-shadow: var(--shadow-sm);
}
.modal {
  box-shadow: var(--shadow-2xl);
}
```

**Token Scale:**

| Token | Description |
|-------|-------------|
| `--shadow-sm` | Subtle elevation |
| `--shadow-md` | Cards, dropdowns |
| `--shadow-lg` | Popovers |
| `--shadow-xl` | Modals, dialogs |
| `--shadow-2xl` | Overlays |

### 6. Transitions (Info - Strict Mode Only)

**Pattern:** Hardcoded transition timing

**Bad:**
```css
.button {
  transition: all 150ms ease;
}
```

**Good:**
```css
.button {
  transition: var(--transition-fast);
}
```

**Token Scale:**

| Token | Duration |
|-------|----------|
| `--duration-fast` | 150ms |
| `--duration-normal` | 200ms |
| `--duration-slow` | 300ms |
| `--transition-fast` | all 150ms ease-out |
| `--transition-normal` | all 200ms ease-out |

### 7. Z-Index (Warning)

**Pattern:** Hardcoded z-index values ≥ 100

**Bad:**
```css
.dropdown {
  z-index: 1000;
}
.modal {
  z-index: 1050;
}
```

**Good:**
```css
.dropdown {
  z-index: var(--z-dropdown);
}
.modal {
  z-index: var(--z-modal);
}
```

**Token Scale:**

| Token | Value |
|-------|-------|
| `--z-dropdown` | 1000 |
| `--z-sticky` | 1020 |
| `--z-fixed` | 1030 |
| `--z-modal-backdrop` | 1040 |
| `--z-modal` | 1050 |
| `--z-popover` | 1060 |
| `--z-tooltip` | 1070 |
| `--z-toast` | 1080 |

## Exceptions (Always Allowed)

### CSS Keywords
- `currentColor`
- `transparent`
- `inherit`
- `initial`
- `unset`
- `none`
- `auto`

### Small Values
- `0`, `0px` - Zero
- `1px` - Hairline borders
- `2px` - Focus outlines
- `100%`, `50%` - Percentages

### Layout Values
These are skipped because they're structural, not themeable:
- Container max-widths (`1400px`, `1200px`, `1024px`)
- Media query breakpoints (`768px`, `640px`, `480px`)
- Grid functions (`minmax()`, `repeat()`)
- Grid templates

### Context-Specific
- Lines starting with `--` (token definitions)
- Comments (`/*`, `*`, `*/`)
- `@media` query lines
- `@keyframes` definitions
- Animation percentages (`0%`, `100%`)

### Exception Properties
Some properties accept hardcoded values:
- `outline` - Accessibility focus indicators
- `outline-offset` - Accessibility
- `transform` - Animation transforms
- `animation` - Animation definitions
- `content` - Pseudo-element content
- `clip-path` - Complex clipping
- `mask` - Complex masking

## Script Usage

```bash
# Basic validation
python scripts/validate_tokens.py src/styles

# Strict mode (includes info-level)
python scripts/validate_tokens.py src --strict

# JSON output for CI/CD
python scripts/validate_tokens.py src --json

# Show fix suggestions
python scripts/validate_tokens.py src --fix-suggestions
```

## CI/CD Integration

### GitHub Actions

```yaml
- name: Validate CSS Tokens
  run: python scripts/validate_tokens.py src --json > token-report.json

- name: Check for Errors
  run: |
    errors=$(jq '.errors' token-report.json)
    if [ "$errors" -gt 0 ]; then
      echo "Found $errors token violations"
      exit 1
    fi
```

### Pre-commit Hook

```bash
#!/bin/bash
# .git/hooks/pre-commit

python scripts/validate_tokens.py src --strict
if [ $? -ne 0 ]; then
  echo "CSS token validation failed. Fix violations before committing."
  exit 1
fi
```

## Output Example

```
======================================================================
  CSS DESIGN TOKEN VALIDATION REPORT
======================================================================

  src/components/Card.css
  ------------------------------------------------------------
    ❌ Line 5:12 [ERROR]
       Found: #FA582D
       Rule: colors
       Fix: Use semantic color token (e.g., --color-primary)
       Suggested: var(--color-cyber-orange)

    ⚠️ Line 12:3 [WARNING]
       Found: border-radius: 8px
       Rule: radii
       Fix: Use radius token (e.g., --radius-md)
       Suggested: var(--radius-md)

----------------------------------------------------------------------
  SUMMARY
----------------------------------------------------------------------
  Files scanned:     15
  Files with issues: 3
  Total violations:  7
    - Errors:   4
    - Warnings: 3
    - Info:     0

  By Category:
    - colors: 4
    - radii: 2
    - shadows: 1
```

```