Initial commit: Clean DSS implementation
Migrated from design-system-swarm with fresh git history.
Old project history preserved in /home/overbits/apps/design-system-swarm
Core components:
- MCP Server (Python FastAPI with mcp 1.23.1)
- Claude Plugin (agents, commands, skills, strategies, hooks, core)
- DSS Backend (dss-mvp1 - token translation, Figma sync)
- Admin UI (Node.js/React)
- Server (Node.js/Express)
- Storybook integration (dss-mvp1/.storybook)
Self-contained configuration:
- All paths relative or use DSS_BASE_PATH=/home/overbits/dss
- PYTHONPATH configured for dss-mvp1 and dss-claude-plugin
- .env file with all configuration
- Claude plugin uses ${CLAUDE_PLUGIN_ROOT} for portability
Migration completed: $(date)
🤖 Clean migration with full functionality preserved
This commit is contained in:
408
docs/QUICKSTART.md
Normal file
408
docs/QUICKSTART.md
Normal file
@@ -0,0 +1,408 @@
|
||||
# DSS Quick Start Guide
|
||||
|
||||
Get up and running with DSS in minutes.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Python 3.10+
|
||||
- Node.js 18+ (for CLI)
|
||||
- Figma account (optional, for Figma integration)
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
# Clone repository
|
||||
git clone <repo-url>
|
||||
cd dss
|
||||
|
||||
# Install Python dependencies
|
||||
python3 -m venv .venv
|
||||
source .venv/bin/activate
|
||||
pip install -r requirements.txt
|
||||
|
||||
# Install CLI (optional)
|
||||
cd cli
|
||||
npm install
|
||||
npm run build
|
||||
npm link
|
||||
cd ..
|
||||
```
|
||||
|
||||
## Basic Usage
|
||||
|
||||
### 1. Start the Servers
|
||||
|
||||
```bash
|
||||
# Start REST API (port 3456)
|
||||
python -m tools.api.server
|
||||
|
||||
# Start MCP server (port 3457) in another terminal
|
||||
python -m tools.api.mcp_server
|
||||
```
|
||||
|
||||
### 2. Ingest Design Tokens
|
||||
|
||||
#### From CSS
|
||||
|
||||
```python
|
||||
from tools.ingest.css import CSSTokenSource
|
||||
|
||||
parser = CSSTokenSource()
|
||||
result = await parser.extract("""
|
||||
:root {
|
||||
--color-primary: #3B82F6;
|
||||
--spacing-md: 16px;
|
||||
}
|
||||
""")
|
||||
|
||||
print(f"Extracted {len(result.tokens)} tokens")
|
||||
for token in result.tokens:
|
||||
print(f" {token.name}: {token.value}")
|
||||
```
|
||||
|
||||
#### From SCSS
|
||||
|
||||
```python
|
||||
from tools.ingest.scss import SCSSTokenSource
|
||||
|
||||
parser = SCSSTokenSource()
|
||||
result = await parser.extract("""
|
||||
$primary: #3B82F6;
|
||||
$spacing-md: 16px;
|
||||
""")
|
||||
```
|
||||
|
||||
#### From Tailwind Config
|
||||
|
||||
```python
|
||||
from tools.ingest.tailwind import TailwindTokenSource
|
||||
|
||||
parser = TailwindTokenSource()
|
||||
result = await parser.extract("./tailwind.config.js")
|
||||
```
|
||||
|
||||
#### From Figma
|
||||
|
||||
```python
|
||||
from tools.figma.figma_tools import FigmaToolSuite
|
||||
|
||||
# Set FIGMA_TOKEN environment variable first
|
||||
suite = FigmaToolSuite(output_dir="./output")
|
||||
result = await suite.extract_variables("YOUR_FILE_KEY")
|
||||
```
|
||||
|
||||
### 3. Merge Tokens from Multiple Sources
|
||||
|
||||
```python
|
||||
from tools.ingest.merge import TokenMerger, MergeStrategy
|
||||
from tools.ingest.base import TokenCollection, DesignToken, TokenType
|
||||
|
||||
# Create collections from different sources
|
||||
css_tokens = TokenCollection([
|
||||
DesignToken(name="color.primary", value="#FF0000", type=TokenType.COLOR, source="css")
|
||||
])
|
||||
|
||||
figma_tokens = TokenCollection([
|
||||
DesignToken(name="color.primary", value="#3B82F6", type=TokenType.COLOR, source="figma")
|
||||
])
|
||||
|
||||
# Merge with PREFER_FIGMA strategy
|
||||
merger = TokenMerger(strategy=MergeStrategy.PREFER_FIGMA)
|
||||
result = merger.merge([css_tokens, figma_tokens])
|
||||
|
||||
print(f"Merged tokens: {len(result.collection.tokens)}")
|
||||
print(f"Conflicts: {len(result.conflicts)}")
|
||||
|
||||
# Access the winning token
|
||||
primary = result.collection.tokens[0]
|
||||
print(f"Final color.primary: {primary.value}") # #3B82F6 (from Figma)
|
||||
```
|
||||
|
||||
### 4. Analyze React Project
|
||||
|
||||
```python
|
||||
from tools.analyze.scanner import ProjectScanner
|
||||
|
||||
scanner = ProjectScanner("./my-react-app")
|
||||
analysis = await scanner.scan()
|
||||
|
||||
print(f"Framework: {analysis.framework}")
|
||||
print(f"Styling: {analysis.styling_approach}")
|
||||
print(f"Components: {len(analysis.components)}")
|
||||
```
|
||||
|
||||
### 5. Find Quick Wins
|
||||
|
||||
```python
|
||||
from tools.analyze.quick_wins import QuickWinFinder
|
||||
|
||||
finder = QuickWinFinder("./my-react-app")
|
||||
wins = await finder.find_all()
|
||||
|
||||
for win in wins.opportunities[:5]:
|
||||
print(f"{win.type.value}: {win.title}")
|
||||
print(f" Impact: {win.impact.value}")
|
||||
print(f" Effort: {win.effort.value}")
|
||||
```
|
||||
|
||||
### 6. Generate Storybook Stories
|
||||
|
||||
```python
|
||||
from tools.storybook.generator import StoryGenerator
|
||||
from tools.analyze.base import ComponentInfo
|
||||
|
||||
# Define component
|
||||
component = ComponentInfo(
|
||||
name="Button",
|
||||
file_path="src/components/Button.tsx",
|
||||
props=[
|
||||
{"name": "variant", "type": "primary | secondary"},
|
||||
{"name": "children", "type": "ReactNode"}
|
||||
]
|
||||
)
|
||||
|
||||
# Generate story
|
||||
generator = StoryGenerator(output_dir="./stories")
|
||||
result = await generator.generate_story(component, template="csf3")
|
||||
|
||||
print(f"Story created: {result['file_path']}")
|
||||
```
|
||||
|
||||
### 7. Generate Storybook Theme from Tokens
|
||||
|
||||
```python
|
||||
from tools.storybook.theme import ThemeGenerator
|
||||
from tools.ingest.base import TokenCollection, DesignToken, TokenType
|
||||
|
||||
tokens = TokenCollection([
|
||||
DesignToken(name="color.primary.500", value="#3B82F6", type=TokenType.COLOR),
|
||||
DesignToken(name="spacing.md", value="16px", type=TokenType.SPACING),
|
||||
DesignToken(name="font.size.base", value="16px", type=TokenType.TYPOGRAPHY)
|
||||
])
|
||||
|
||||
generator = ThemeGenerator()
|
||||
theme = generator.generate_from_tokens(tokens)
|
||||
|
||||
print(theme) # JavaScript theme object
|
||||
```
|
||||
|
||||
## Using the REST API
|
||||
|
||||
```bash
|
||||
# Check status
|
||||
curl http://localhost:3456/status
|
||||
|
||||
# List tokens
|
||||
curl http://localhost:3456/tokens
|
||||
|
||||
# Ingest CSS tokens
|
||||
curl -X POST http://localhost:3456/tokens/ingest \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"source_type": "css",
|
||||
"content": ":root { --color: #FF0000; }"
|
||||
}'
|
||||
|
||||
# Analyze project
|
||||
curl -X POST http://localhost:3456/analyze/project \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"path": "./my-react-app"}'
|
||||
|
||||
# Get quick wins
|
||||
curl http://localhost:3456/analyze/quick-wins?path=./my-react-app
|
||||
```
|
||||
|
||||
## Using the MCP Server (AI Agents)
|
||||
|
||||
The MCP server exposes 32 tools for AI agents. Connect via MCP client:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"dss": {
|
||||
"command": "python",
|
||||
"args": ["-m", "tools.api.mcp_server"],
|
||||
"cwd": "/path/to/dss"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Available tool categories:
|
||||
- **Status & Discovery** (4 tools): `get_status`, `discover_project`, etc.
|
||||
- **Token Ingestion** (7 tools): `ingest_figma_variables`, `ingest_css_tokens`, etc.
|
||||
- **Analysis** (11 tools): `analyze_react_components`, `get_quick_wins`, etc.
|
||||
- **Storybook** (5 tools): `generate_story`, `generate_storybook_theme`, etc.
|
||||
- **Figma** (5 tools): `figma_extract_variables`, `figma_sync_tokens`, etc.
|
||||
|
||||
## Common Workflows
|
||||
|
||||
### Workflow 1: Figma → DSS → Storybook
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
from tools.figma.figma_tools import FigmaToolSuite
|
||||
from tools.storybook.theme import ThemeGenerator
|
||||
|
||||
async def figma_to_storybook(file_key: str):
|
||||
# 1. Extract from Figma
|
||||
suite = FigmaToolSuite(output_dir="./output")
|
||||
result = await suite.extract_variables(file_key)
|
||||
|
||||
# 2. Convert to tokens
|
||||
tokens = result['tokens'] # TokenCollection
|
||||
|
||||
# 3. Generate Storybook theme
|
||||
generator = ThemeGenerator()
|
||||
theme_code = generator.generate_theme_file(tokens, "./storybook/theme.js")
|
||||
|
||||
print(f"✅ Generated Storybook theme with {len(tokens)} tokens")
|
||||
|
||||
asyncio.run(figma_to_storybook("YOUR_FILE_KEY"))
|
||||
```
|
||||
|
||||
### Workflow 2: Multi-Source Token Merge
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
from tools.ingest.css import CSSTokenSource
|
||||
from tools.ingest.scss import SCSSTokenSource
|
||||
from tools.figma.figma_tools import FigmaToolSuite
|
||||
from tools.ingest.merge import TokenMerger, MergeStrategy
|
||||
|
||||
async def merge_all_sources():
|
||||
# 1. Ingest from CSS
|
||||
css_parser = CSSTokenSource()
|
||||
css_tokens = await css_parser.extract("./styles/tokens.css")
|
||||
|
||||
# 2. Ingest from SCSS
|
||||
scss_parser = SCSSTokenSource()
|
||||
scss_tokens = await scss_parser.extract("./styles/variables.scss")
|
||||
|
||||
# 3. Ingest from Figma
|
||||
figma = FigmaToolSuite()
|
||||
figma_result = await figma.extract_variables("YOUR_FILE_KEY")
|
||||
figma_tokens = figma_result['tokens']
|
||||
|
||||
# 4. Merge with Figma as source of truth
|
||||
merger = TokenMerger(strategy=MergeStrategy.PREFER_FIGMA)
|
||||
result = merger.merge([css_tokens, scss_tokens, figma_tokens])
|
||||
|
||||
print(f"✅ Merged {len(result.collection.tokens)} tokens")
|
||||
print(f"⚠️ Resolved {len(result.conflicts)} conflicts")
|
||||
|
||||
return result.collection
|
||||
|
||||
asyncio.run(merge_all_sources())
|
||||
```
|
||||
|
||||
### Workflow 3: Analyze → Quick Wins → Fix
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
from tools.analyze.scanner import ProjectScanner
|
||||
from tools.analyze.quick_wins import QuickWinFinder
|
||||
|
||||
async def analyze_project(path: str):
|
||||
# 1. Scan project
|
||||
scanner = ProjectScanner(path)
|
||||
analysis = await scanner.scan()
|
||||
|
||||
print(f"Framework: {analysis.framework}")
|
||||
print(f"Components: {len(analysis.components)}")
|
||||
|
||||
# 2. Find quick wins
|
||||
finder = QuickWinFinder(path)
|
||||
wins = await finder.find_all()
|
||||
|
||||
# 3. Prioritize by ROI
|
||||
high_roi = [
|
||||
w for w in wins.opportunities
|
||||
if w.impact.value == "high" and w.effort.value in ["low", "medium"]
|
||||
]
|
||||
|
||||
print(f"\n🎯 Top Quick Wins ({len(high_roi)}):")
|
||||
for win in high_roi[:5]:
|
||||
print(f" • {win.title}")
|
||||
print(f" Impact: {win.impact.value} | Effort: {win.effort.value}")
|
||||
|
||||
asyncio.run(analyze_project("./my-react-app"))
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
### Environment Variables
|
||||
|
||||
```bash
|
||||
# Figma integration
|
||||
export FIGMA_TOKEN="your-figma-token"
|
||||
export FIGMA_CACHE_TTL=300 # 5 minutes
|
||||
|
||||
# Server ports
|
||||
export PORT=3456 # REST API
|
||||
export DSS_MCP_PORT=3457 # MCP server
|
||||
export DSS_MCP_HOST=127.0.0.1
|
||||
|
||||
# Database
|
||||
export DSS_DB_PATH="./.dss/dss.db"
|
||||
```
|
||||
|
||||
### Figma Setup
|
||||
|
||||
1. Get Figma token: https://www.figma.com/developers/api#access-tokens
|
||||
2. Set `FIGMA_TOKEN` environment variable
|
||||
3. Get file key from Figma URL: `https://figma.com/file/FILE_KEY/...`
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Figma API Returns Empty
|
||||
|
||||
**Problem**: `extract_variables()` returns 0 tokens
|
||||
|
||||
**Solutions**:
|
||||
1. Check if file has Variables (requires paid plan)
|
||||
2. Use `extract_styles()` for document-level styles (free)
|
||||
3. Check file permissions and token validity
|
||||
|
||||
### Module Import Errors
|
||||
|
||||
**Problem**: `ModuleNotFoundError: No module named 'tools'`
|
||||
|
||||
**Solution**: Ensure you're in the project root and virtual env is activated:
|
||||
```bash
|
||||
cd /path/to/dss
|
||||
source .venv/bin/activate
|
||||
```
|
||||
|
||||
### Tailwind Parser Returns 0 Tokens
|
||||
|
||||
**Known Issue**: Tailwind parser regex doesn't match all config formats
|
||||
|
||||
**Workaround**: Use JSON tokens format:
|
||||
```python
|
||||
from tools.ingest.json_tokens import JSONTokenSource
|
||||
import json
|
||||
|
||||
# Convert Tailwind config to JSON tokens
|
||||
tailwind_as_json = json.dumps({
|
||||
"color": {
|
||||
"primary": {"value": "#3B82F6", "type": "color"}
|
||||
}
|
||||
})
|
||||
|
||||
parser = JSONTokenSource()
|
||||
result = await parser.extract(tailwind_as_json)
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
- Read [ARCHITECTURE.md](./ARCHITECTURE.md) for system design
|
||||
- Check [DSS_PRINCIPLES.md](../DSS_PRINCIPLES.md) for design philosophy
|
||||
- Review [PROJECT_MEMORY.md](../PROJECT_MEMORY.md) for complete module inventory
|
||||
- Explore [examples/](../examples/) for more code samples
|
||||
|
||||
## Getting Help
|
||||
|
||||
- GitHub Issues: [Report bugs](https://github.com/your-org/dss/issues)
|
||||
- Documentation: Check `docs/` folder
|
||||
- API Reference: See `tools/api/mcp_server.py` for all MCP tools
|
||||
Reference in New Issue
Block a user