#!/bin/bash # DSS Initialization Script - Complete Setup & Build Pipeline # # This is the single entry point for DSS setup. It handles: # - MCP configuration # - Dependencies (Python venv, Node modules) # - Directory structure (JSON storage) # - Figma sync and token resolution # - CSS generation with style-dictionary # - Storybook story generation # - Development servers (optional) # # Usage: scripts/dss-init.sh [--reset] [--skip-analysis] [--skip-servers] # # Flags: # --reset Clear all DSS data first (fresh start) # --skip-analysis Skip target project analysis # --skip-servers Don't start development servers # --servers-only Only start servers (skip init steps) set -e DSS_ROOT="$(cd "$(dirname "$0")/.." && pwd)" cd "$DSS_ROOT" # Parse arguments RESET=false SKIP_ANALYSIS=false SKIP_SERVERS=false SERVERS_ONLY=false for arg in "$@"; do case $arg in --reset) RESET=true ;; --skip-analysis) SKIP_ANALYSIS=true ;; --skip-servers) SKIP_SERVERS=true ;; --servers-only) SERVERS_ONLY=true ;; esac done # Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' CYAN='\033[0;36m' NC='\033[0m' log_step() { echo -e "${BLUE}[STEP]${NC} $1"; } log_ok() { echo -e "${GREEN}[OK]${NC} $1"; } log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; } log_error() { echo -e "${RED}[ERROR]${NC} $1"; } log_info() { echo -e "${CYAN}[INFO]${NC} $1"; } echo "╔══════════════════════════════════════════════════════════════╗" echo "║ DSS INITIALIZATION ║" echo "║ Complete Setup & Build Pipeline ║" echo "╚══════════════════════════════════════════════════════════════╝" echo "" # ============================================================================ # SERVERS ONLY MODE # ============================================================================ if [ "$SERVERS_ONLY" = true ]; then log_step "Starting development servers only..." # Kill existing processes pkill -f "vite.*admin-ui" 2>/dev/null || true pkill -f "storybook.*6006" 2>/dev/null || true sleep 1 cd "$DSS_ROOT/admin-ui" nohup npm run dev > /tmp/dss-admin-ui.log 2>&1 & log_info "admin-ui starting (PID: $!)..." nohup npm run storybook > /tmp/dss-storybook.log 2>&1 & log_info "Storybook starting (PID: $!)..." cd "$DSS_ROOT" sleep 5 if curl -s -o /dev/null -w "" http://localhost:6221 2>/dev/null; then log_ok "admin-ui: http://localhost:6221" else log_warn "admin-ui not responding yet (check /tmp/dss-admin-ui.log)" fi if curl -s -o /dev/null -w "" http://localhost:6226 2>/dev/null; then log_ok "Storybook: http://localhost:6226" else log_warn "Storybook not responding yet (check /tmp/dss-storybook.log)" fi exit 0 fi # ============================================================================ # STEP 1: Reset (if requested) # ============================================================================ if [ "$RESET" = true ]; then log_step "1. Resetting DSS to clean state..." # Clear data directories rm -rf .dss/data/projects/* .dss/data/teams/* .dss/data/_system/cache/* .dss/data/_system/activity/* 2>/dev/null || true rm -rf .dss/data/_system/tokens/* .dss/data/_system/themes/* .dss/data/_system/components/* 2>/dev/null || true # Clear admin-ui generated files rm -f admin-ui/css/dss-*.css 2>/dev/null || true rm -f admin-ui/src/components/*.stories.js admin-ui/src/components/ds-*.js 2>/dev/null || true # Reset core_tokens mkdir -p dss/core_tokens cat > dss/core_tokens/tokens.json << 'EOF' { "_meta": { "version": "1.0.0", "generated": null, "source": "awaiting Figma sync", "status": "empty" }, "tokens": {} } EOF # Reset skins (macOS bash 3 compatible) for skin in base classic workbench; do skin_cap="$(echo "$skin" | sed 's/./\U&/')" if [ "$skin" = "base" ]; then cat > "dss-claude-plugin/core/skins/${skin}.json" << EOF { "meta": { "id": "${skin}", "version": "1.0.0", "description": "${skin_cap} skin - awaiting Figma sync" }, "tokens": {} } EOF else cat > "dss-claude-plugin/core/skins/${skin}.json" << EOF { "meta": { "id": "${skin}", "version": "1.0.0", "description": "${skin_cap} skin - awaiting Figma sync", "extends": "base" }, "tokens": {} } EOF fi done # Clear logs rm -f .dss/logs/*.jsonl 2>/dev/null || true rm -rf .dss/logs/browser-logs/* 2>/dev/null || true log_ok "Reset complete" echo "" else log_step "1. Skipping reset (use --reset to clear first)" echo "" fi # ============================================================================ # STEP 2: Generate MCP Configuration # ============================================================================ log_step "2. Generating MCP configuration..." mkdir -p "$DSS_ROOT/.claude" cat > "$DSS_ROOT/.claude/mcp.json" << EOF { "\$schema": "https://raw.githubusercontent.com/anthropics/claude-code/main/schemas/mcp-servers.schema.json", "mcpServers": { "dss": { "command": "$DSS_ROOT/.venv/bin/python3", "args": ["-m", "dss.mcp.server"], "env": { "PYTHONPATH": "$DSS_ROOT", "DSS_HOME": "$DSS_ROOT/.dss", "DSS_CACHE": "$DSS_ROOT/.dss/cache", "DSS_BASE_PATH": "$DSS_ROOT", "DSS_ENABLE_DEV_COMMANDS": "1", "DSS_API_URL": "" }, "description": "Design System Server MCP - local development" } } } EOF log_ok "MCP config: .claude/mcp.json" echo "" # ============================================================================ # STEP 3: Check/Install Dependencies # ============================================================================ log_step "3. Checking dependencies..." # Check/create Python venv if [ ! -d "$DSS_ROOT/.venv" ]; then log_info "Creating Python virtual environment..." python3 -m venv "$DSS_ROOT/.venv" fi # Use venv Python PYTHON="$DSS_ROOT/.venv/bin/python3" # Activate venv and check packages source "$DSS_ROOT/.venv/bin/activate" if ! python3 -c "import mcp" 2>/dev/null; then log_info "Installing MCP package..." pip install mcp 2>/dev/null || log_warn "MCP package install failed" fi log_ok "Python venv ready" # Check root node_modules (includes style-dictionary) if [ ! -d "$DSS_ROOT/node_modules" ]; then log_info "Installing root dependencies (style-dictionary)..." cd "$DSS_ROOT" && npm install fi log_ok "Root dependencies ready" # Check admin-ui node_modules (verify storybook is installed) if [ ! -d "$DSS_ROOT/admin-ui/node_modules" ] || [ ! -f "$DSS_ROOT/admin-ui/node_modules/.bin/storybook" ]; then log_info "Installing admin-ui dependencies..." cd "$DSS_ROOT/admin-ui" && npm install --legacy-peer-deps cd "$DSS_ROOT" fi log_ok "admin-ui dependencies ready" # Build admin-ui log_info "Building admin-ui..." cd "$DSS_ROOT/admin-ui" npm run build 2>&1 | tail -5 cd "$DSS_ROOT" log_ok "admin-ui built (dist/)" # Check style-dictionary STYLE_DICT_AVAILABLE=false STYLE_DICT_CMD="" if [ -f "$DSS_ROOT/node_modules/.bin/style-dictionary" ]; then STYLE_DICT_AVAILABLE=true STYLE_DICT_CMD="$DSS_ROOT/node_modules/.bin/style-dictionary" log_ok "style-dictionary: local" elif [ -f "$HOME/node_modules/.bin/style-dictionary" ]; then STYLE_DICT_AVAILABLE=true STYLE_DICT_CMD="$HOME/node_modules/.bin/style-dictionary" log_ok "style-dictionary: global (~)" elif command -v style-dictionary &> /dev/null; then STYLE_DICT_AVAILABLE=true STYLE_DICT_CMD="style-dictionary" log_ok "style-dictionary: global" else log_warn "style-dictionary not installed (npm install style-dictionary)" fi echo "" # ============================================================================ # STEP 4: Validate Environment # ============================================================================ log_step "4. Validating environment..." log_ok "Python: $(python3 --version | cut -d' ' -f2)" log_ok "Node.js: $(node --version)" # Check Figma token FIGMA_AVAILABLE=false FIGMA_CONFIG=".dss/config/figma.json" if [ -z "$FIGMA_TOKEN" ] && [ -f "$FIGMA_CONFIG" ]; then FIGMA_TOKEN=$(python3 -c "import json; print(json.load(open('$FIGMA_CONFIG')).get('token',''))" 2>/dev/null) export FIGMA_TOKEN fi if [ -n "$FIGMA_TOKEN" ]; then FIGMA_AVAILABLE=true log_ok "FIGMA_TOKEN: configured" if [ -f "$FIGMA_CONFIG" ]; then UIKIT_NAME=$(python3 -c "import json; d=json.load(open('$FIGMA_CONFIG')); print(d.get('uikit_reference',{}).get('name',''))" 2>/dev/null) [ -n "$UIKIT_NAME" ] && log_ok "UIKit: $UIKIT_NAME" fi else log_warn "FIGMA_TOKEN not set" fi echo "" # ============================================================================ # STEP 5: Create Directory Structure # ============================================================================ log_step "5. Creating directory structure..." mkdir -p .dss/data/{_system/{tokens,themes,components,cache,activity},projects,teams} mkdir -p .dss/schema mkdir -p .dss/logs/browser-logs touch .dss/logs/dss-operations.jsonl touch .dss/logs/git-hooks.jsonl # Create ds.config.json if [ ! -f ".dss/data/_system/ds.config.json" ]; then cat > .dss/data/_system/ds.config.json << 'EOF' { "name": "dss-system", "version": "1.0.0", "description": "DSS internal design system", "skin": "base", "base_theme": "light", "targets": [ {"name": "admin-ui", "path": "./admin-ui", "type": "web-app"}, {"name": "storybook", "path": "./storybook", "type": "documentation"} ], "output": { "tokens_dir": "./.dss/data/_system/tokens", "themes_dir": "./.dss/data/_system/themes", "formats": ["css", "scss", "json"] } } EOF fi log_ok "Directory structure ready" echo "" # ============================================================================ # STEP 6: Storage (JSON) # ============================================================================ log_step "6. Storage (JSON) ready..." log_ok "Using JSON storage under .dss/data/" echo "" # ============================================================================ # STEP 7: Analyze Target Projects # ============================================================================ if [ "$SKIP_ANALYSIS" = false ]; then log_step "7. Analyzing targets..." if [ -d "admin-ui" ]; then JS_COUNT=$(find admin-ui -name "*.js" -not -path "*/node_modules/*" 2>/dev/null | wc -l) CSS_COUNT=$(find admin-ui -name "*.css" -not -path "*/node_modules/*" 2>/dev/null | wc -l) log_ok "admin-ui: $JS_COUNT js, $CSS_COUNT css" fi STORIES_COUNT=$(find . -name "*.stories.js" -o -name "*.stories.ts" 2>/dev/null | grep -v node_modules | wc -l) log_ok "storybook: $STORIES_COUNT stories" echo "" else log_step "7. Skipping analysis (--skip-analysis)" echo "" fi # ============================================================================ # STEP 8: Initialize Token Structure # ============================================================================ log_step "8. Checking tokens..." mkdir -p .dss/data/_system/tokens if [ ! -f ".dss/data/_system/tokens/base.json" ]; then cat > .dss/data/_system/tokens/base.json << 'EOF' { "_meta": {"version": "1.0.0", "status": "empty"}, "tokens": {} } EOF log_ok "Token structure created" else log_ok "Token structure exists" fi # Create style-dictionary config cat > .dss/data/_system/style-dictionary.config.json << 'EOF' { "source": ["tokens/tokens.json"], "platforms": { "css": { "transformGroup": "css", "buildPath": "themes/", "files": [{"destination": "tokens.css", "format": "css/variables"}] }, "scss": { "transformGroup": "scss", "buildPath": "themes/", "files": [{"destination": "_tokens.scss", "format": "scss/variables"}] }, "json": { "transformGroup": "js", "buildPath": "themes/", "files": [{"destination": "tokens.json", "format": "json/flat"}] } } } EOF echo "" # ============================================================================ # STEP 9: Validate 3-Layer Architecture # ============================================================================ log_step "9. Validating 3-layer architecture..." if [ -f ".dss/core/primitives.json" ]; then PRIM_COUNT=$(python3 -c "import json; d=json.load(open('.dss/core/primitives.json')); print(sum(len(v) if isinstance(v,dict) else 0 for k,v in d.items() if not k.startswith('_')))" 2>/dev/null || echo "0") log_ok "Core primitives: $PRIM_COUNT" fi SKIN_COUNT=$(find .dss/skins -name "tokens.json" 2>/dev/null | wc -l) [ "$SKIN_COUNT" -gt 0 ] && log_ok "Skins: $SKIN_COUNT" THEME_COUNT=$(find .dss/themes -name "*.json" 2>/dev/null | grep -v "_" | wc -l) [ "$THEME_COUNT" -gt 0 ] && log_ok "Themes: $THEME_COUNT" # Run validation if [ -f "scripts/validate-theme.py" ]; then log_info "Running validation..." if $PYTHON scripts/validate-theme.py --validate-skin --quiet 2>&1 | while read line; do echo " $line" done; then log_ok "Validation passed" fi fi echo "" # ============================================================================ # STEP 10: Figma Sync # ============================================================================ log_step "10. Figma sync..." TOKEN_STATUS=$(python3 -c "import json; d=json.load(open('.dss/data/_system/tokens/base.json')); print(d.get('_meta',{}).get('status','empty'))" 2>/dev/null || echo "empty") if [ "$FIGMA_AVAILABLE" = true ] && [ "$TOKEN_STATUS" = "empty" ]; then FIGMA_FILE_KEY=$(python3 -c "import json; print(json.load(open('$FIGMA_CONFIG')).get('uikit_reference',{}).get('file_key',''))" 2>/dev/null) if [ -n "$FIGMA_FILE_KEY" ]; then log_info "Syncing from Figma..." if $PYTHON "$DSS_ROOT/scripts/figma-sync.py" --file-key "$FIGMA_FILE_KEY" 2>&1 | while read line; do echo " $line" done; then log_ok "Figma sync complete" fi else log_warn "No UIKit file_key configured" fi elif [ "$TOKEN_STATUS" != "empty" ]; then log_ok "Tokens already synced" else log_warn "FIGMA_TOKEN not set" fi echo "" # ============================================================================ # STEP 11: Resolve Token Cascade # ============================================================================ log_step "11. Resolving token cascade..." if [ -f ".dss/core/primitives.json" ] && [ -d ".dss/skins/shadcn" ]; then log_info "Core → Skin → Theme" if $PYTHON scripts/resolve-tokens.py 2>&1 | while read line; do echo " $line" done; then log_ok "Tokens resolved" fi else log_warn "3-layer structure incomplete" fi echo "" # ============================================================================ # STEP 12: Build CSS # ============================================================================ log_step "12. Building CSS..." HAS_TOKENS=$(python3 -c " import json try: d = json.load(open('.dss/data/_system/tokens/tokens.json')) print('yes' if d else 'no') except: print('no') " 2>/dev/null || echo "no") if [ "$HAS_TOKENS" = "yes" ] && [ -n "$STYLE_DICT_CMD" ]; then cd .dss/data/_system if $STYLE_DICT_CMD build --config style-dictionary.config.json 2>&1 | grep -v "^$"; then log_ok "CSS generated" fi cd "$DSS_ROOT" if [ -f ".dss/data/_system/themes/tokens.css" ]; then CSS_VARS=$(grep -c "^ --" .dss/data/_system/themes/tokens.css 2>/dev/null || echo "0") log_ok "$CSS_VARS CSS variables" fi elif [ "$HAS_TOKENS" = "no" ]; then log_warn "No tokens - sync from Figma first" elif [ -z "$STYLE_DICT_CMD" ]; then log_warn "style-dictionary not installed" fi echo "" # ============================================================================ # STEP 13: Generate Storybook Stories # ============================================================================ log_step "13. Generating Storybook stories..." if [ "$HAS_TOKENS" = "yes" ] && [ -f "scripts/generate-storybook.py" ]; then if $PYTHON scripts/generate-storybook.py 2>&1 | while read line; do echo " $line" done; then STORY_COUNT=$(find admin-ui/src/stories -name "*.stories.js" 2>/dev/null | wc -l) log_ok "$STORY_COUNT stories generated" fi else log_warn "Skipping (no tokens or generator)" fi echo "" # ============================================================================ # STEP 14: Update Hash Manifest # ============================================================================ log_step "14. Updating hashes..." if [ -f "scripts/regenerate-core-hashes.sh" ]; then ./scripts/regenerate-core-hashes.sh 2>/dev/null log_ok "Hash manifest updated" fi echo "" # ============================================================================ # STEP 15: Start Development Servers # ============================================================================ if [ "$SKIP_SERVERS" = false ]; then log_step "15. Starting development servers..." pkill -f "vite.*admin-ui" 2>/dev/null || true pkill -f "storybook.*6006" 2>/dev/null || true sleep 1 cd "$DSS_ROOT/admin-ui" nohup npm run dev > /tmp/dss-admin-ui.log 2>&1 & log_info "admin-ui starting..." nohup npm run storybook > /tmp/dss-storybook.log 2>&1 & log_info "Storybook starting..." cd "$DSS_ROOT" sleep 5 if curl -s -o /dev/null -w "" http://localhost:6221 2>/dev/null; then log_ok "admin-ui: http://localhost:6221" else log_warn "admin-ui not responding yet" fi if curl -s -o /dev/null -w "" http://localhost:6226 2>/dev/null; then log_ok "Storybook: http://localhost:6226" else log_warn "Storybook not responding yet" fi echo "" else log_step "15. Skipping servers (--skip-servers)" echo "" fi # ============================================================================ # SUMMARY # ============================================================================ # Determine status if [ -f ".dss/data/_system/themes/tokens.css" ]; then STATUS="READY" STATUS_MSG="Import from .dss/data/_system/themes/" elif [ "$HAS_TOKENS" = "yes" ]; then STATUS="TOKENS READY" STATUS_MSG="Install style-dictionary to build CSS" else STATUS="AWAITING FIGMA SYNC" STATUS_MSG="Run: /dss-figma to populate tokens" fi echo "╔══════════════════════════════════════════════════════════════╗" echo "║ DSS INITIALIZATION COMPLETE ║" echo "╚══════════════════════════════════════════════════════════════╝" echo "" echo " Status: $STATUS" echo " → $STATUS_MSG" echo "" echo " Services:" echo " admin-ui: http://localhost:6221" echo " Storybook: http://localhost:6226" echo "" echo " Output:" echo " .dss/data/_system/themes/ ← CSS for admin-ui" echo " .dss/data/_system/tokens/ ← Token JSON" echo " admin-ui/src/stories/ ← Storybook stories" echo "" echo " Commands:" echo " /dss-init --reset Fresh start" echo " /dss-init Incremental update" echo " /dss-init --servers-only Start servers" echo ""