# DSS Coding Principles Comprehensive principles for building the Design System Swarm (DSS) - a living, breathing design system organism. **Version**: 1.0 **Last Updated**: 2025-12-06 **Grade**: A (Excellent quality with room for accessibility improvements) --- ## Table of Contents 1. [Architectural Principles](#1-architectural-principles) 2. [Code Quality Standards](#2-code-quality-standards) 3. [Organism Framework Principles](#3-organism-framework-principles) 4. [Keyboard Accessibility](#4-keyboard-accessibility) 5. [Web Component Standards](#5-web-component-standards) 6. [Security Guidelines](#6-security-guidelines) 7. [Event Handling & Memory Management](#7-event-handling--memory-management) 8. [Testing & Quality Assurance](#8-testing--quality-assurance) 9. [Documentation Standards](#9-documentation-standards) 10. [Review Checklists](#10-review-checklists) --- ## 1. Architectural Principles DSS follows a **monolithic core architecture with strong separation of concerns**. These principles ensure maintainability and clarity. ### 1.1 Monolithic Core Design **Principle**: Single source of truth with immutable design system core **Guidelines**: - Central database of record (heart ❤️) - All design tokens pass through normalization pipeline - External systems translate TO DSS, not the reverse - Immutable by default for design data **Benefits**: - ✅ Simplified deployment and maintenance - ✅ Reduced operational complexity - ✅ Clear data flow and debugging - ✅ Strong consistency guarantees **Trade-offs**: - Less flexible than microservices - Single point of failure (mitigated by backups) - Harder to scale horizontally (acceptable for current scale) **Reference**: `/docs/ARCHITECTURE_REVIEW.md#1-monolithic-core` ### 1.2 External Translation Pattern **Principle**: DSS doesn't adapt to external systems; external systems translate TO DSS **Implementation**: ``` Figma → Translation Layer → DSS Core CSS → Translation Layer → DSS Core Tailwind → Translation Layer → DSS Core ``` **Benefits**: - ✅ Maintains data integrity - ✅ Prevents drift between sources - ✅ Clear contract boundaries - ✅ Easy to add new sources **Anti-Pattern**: - ❌ DSS adapting to external format variations - ❌ Custom handling per-source in core - ❌ Loose source contracts **Reference**: `/docs/ARCHITECTURE_REVIEW.md#2-external-translation` ### 1.3 Layered Architecture **Principle**: Clear separation between storage, domain logic, and interfaces **Layers** (bottom to top): 1. **Storage Layer** - SQLite, file system, cache 2. **Core Domain Layer** - Token models, merge logic, validation 3. **Ingestion Layer** - Source parsers (CSS, SCSS, Figma, etc.) 4. **Analysis Layer** - Project scanning, quick wins, metrics 5. **Generation Layer** - Storybook, component generation, output 6. **API Layer** - REST + MCP interfaces **Rules**: - Lower layers have NO dependencies on upper layers - Each layer has a single responsibility - Data flows through layers in defined directions - Minimal coupling between layers **Reference**: `/docs/ARCHITECTURE_REVIEW.md#3-layered-architecture` ### 1.4 Architectural Patterns **Strategy Pattern** - For token merge strategies ```python class TokenMerger: def __init__(self, strategy: MergeStrategy): self.strategy = strategy # FIRST, LAST, PREFER_FIGMA, etc. ``` **Abstract Base Classes** - For extension points ```python class TokenSource(ABC): @abstractmethod async def extract(self, source: str) -> TokenCollection: pass ``` **Data Classes** - For immutable domain models ```python @dataclass(frozen=True) class DesignToken: name: str value: str type: TokenType ``` **Dependency Injection** - Explicit dependencies ```python # Good: dependencies explicit def __init__(self, db_path: str, cache: Cache): self.db = Database(db_path) self.cache = cache # Avoid: hard-coded dependencies config_path = Path(__file__).parent / "config.json" ``` **Reference**: `/docs/ARCHITECTURE_REVIEW.md#architecture-patterns` --- ## 2. Code Quality Standards DSS maintains **A-grade code quality** with comprehensive standards. ### 2.1 Python Style & Conventions **Following**: PEP 8 with flexibility **Standards**: - 4-space indentation (never tabs) - Max line length: 100 characters (flexible) - snake_case for functions and variables - PascalCase for classes - UPPER_CASE for constants - Type hints for 100% of public APIs **Naming Examples**: ```python class TokenMerger: # Class: PascalCase async def merge(self, ...): # Method: snake_case MAX_TOKENS = 1000 # Constant: UPPER_CASE token_count = 0 # Variable: snake_case ``` ### 2.2 Error Handling **Principle**: Explicit, meaningful error handling with no silent failures **Good Practices**: ```python # Specific exceptions with context try: data = json.loads(content) except (json.JSONDecodeError, KeyError) as e: logger.error(f"Failed to parse tokens: {e}") raise ValueError(f"Invalid token data: {e}") from e # Meaningful error messages raise ValueError(f"Invalid token type: {token_type}. Expected one of: {valid_types}") ``` **Anti-Patterns**: - ❌ Bare `except:` statements - ❌ Silent failures (`pass` without logging) - ❌ Generic `Exception` catching - ❌ Swallowing error details **Reference**: `/docs/CODE_QUALITY.md#error-handling` ### 2.3 Async Patterns **Principle**: All I/O operations are async **Standard Pattern**: ```python async def extract(self, source: str) -> TokenCollection: # Async file reading content = await asyncio.to_thread(Path(source).read_text) return self._parse(content) # Never block the event loop # Use asyncio.to_thread for blocking operations ``` **Benefits**: - ✅ Responsive API under load - ✅ Efficient resource usage - ✅ Better scalability ### 2.4 Docstrings & Comments **Standard**: All modules, classes, and public functions have docstrings ```python """Module docstring explaining purpose. This module handles token extraction from design files. """ class TokenSource(ABC): """Abstract base for design token sources. Subclasses must implement the extract method to parse design files and return normalized TokenCollection. """ @abstractmethod async def extract(self, source: str) -> TokenCollection: """Extract tokens from a design source. Args: source: Path to design file or design system URL Returns: TokenCollection with normalized design tokens Raises: FileNotFoundError: If source file doesn't exist ValueError: If source format is invalid """ ``` **Comments**: - Explain WHY, not WHAT (code shows what) - Comment complex logic sections - Mark TODOs with urgency level - Update comments when code changes **Reference**: `/docs/CODE_QUALITY.md#docstrings` ### 2.5 Type Hints & Mypy **Principle**: 100% type hint coverage for public APIs **Target Coverage**: - ✅ Current: ~60% for internal code - 🎯 Goal: 100% for all public functions - 🎯 Goal: 80% overall codebase coverage **Examples**: ```python from typing import Optional, Dict, List, Union from dataclasses import dataclass async def process_tokens( tokens: List[DesignToken], merge_strategy: str = "first", validate: bool = True ) -> Dict[str, DesignToken]: """Process design tokens.""" ... @dataclass class Result: success: bool data: Optional[Dict] = None error: Optional[str] = None ``` **Run Mypy**: `mypy tools/ --strict` **Reference**: `/docs/CODE_QUALITY.md#type-hints` --- ## 3. Organism Framework Principles DSS is a **living organism** with organ systems. Understand and design for these systems. ### 3.1 The Heart ❤️ - Database Layer **Function**: Central source of truth, persistent storage **Vital Signs**: - Heart Rate = Database query response time - Blood Pressure = Data write performance - Rhythm = Regular sync cycles with external systems **Health Indicators**: - ✅ Consistent query latency - ✅ No data corruption - ✅ Reliable backups - ❌ Slow queries = system sluggish - ❌ Data inconsistency = system confused - ❌ Missing backups = system vulnerable **Design Principles**: - **Immutability First**: Historical record of all changes - **Strong Consistency**: No eventual consistency for design data - **Backups**: Regular backups (weekly minimum) - **Indexing**: Optimize common query patterns - **Schema**: Never break existing contracts **Reference**: `/docs/DSS_ORGANISM_GUIDE.md#1-the-heart` ### 3.2 The Brain 🧠 - Validators & Analysis **Function**: Validate data quality, detect patterns, learn from data **Neural Functions**: - Pattern Recognition = Detecting design consistency issues - Memory = Storing learned rules and patterns - Decision-Making = Validation rules and quality gates - Learning = Quick wins detection, improvement suggestions **Health Indicators**: - ✅ Validators catching errors early - ✅ Analysis discovering patterns - ✅ Smart suggestions for improvements - ❌ Validators too strict = system constrained - ❌ Validators too loose = garbage data accepted - ❌ Analysis finds nothing = system unaware **Design Principles**: - **Validation First**: Catch errors at ingestion time - **No False Positives**: Rules must catch real problems - **Learning**: Improve detection over time - **Transparency**: Users understand why validation fails **Reference**: `/docs/DSS_ORGANISM_GUIDE.md#2-the-brain` ### 3.3 The Digestive System 🍽️ - Ingestion Pipeline **Function**: Break down external design information into usable tokens **Digestion Stages**: 1. **Intake** = Receiving raw design files 2. **Breakdown** = Parsing format-specific syntax 3. **Extraction** = Pulling out tokens/definitions 4. **Normalization** = Converting to standard token format 5. **Absorption** = Storing in the system **Health Indicators**: - ✅ Successfully parsing diverse input formats - ✅ Zero loss of design information - ✅ Fast processing time - ❌ Failed parsing = maldigestion - ❌ Lost data = nutrient malabsorption - ❌ Slow processing = digestive dysfunction **Design Principles**: - **Format Agnostic**: Support CSS, SCSS, JSON, Figma, etc. - **Zero Data Loss**: Never drop design information - **Normalization**: Convert to standard token format immediately - **Error Recovery**: Partial failures don't block entire ingestion **Reference**: `/docs/DSS_ORGANISM_GUIDE.md#3-the-digestive-system` ### 3.4 The Nervous System 🔌 - APIs & Webhooks **Function**: Perceive external world and respond automatically **Neural Pathways**: - **Sensory Input** = Figma webhooks detecting changes - **Response** = Automatic sync and update triggers - **Communication** = REST API, MCP interface **Health Indicators**: - ✅ Real-time responsiveness to Figma changes - ✅ Reliable webhook delivery - ✅ Available API endpoints - ❌ Missed webhook events = delayed sync - ❌ API downtime = external systems blocked - ❌ Race conditions = data corruption **Design Principles**: - **Real-Time**: Respond to changes immediately - **Reliable**: Guarantee event delivery (retries, idempotency) - **Available**: 99.9% uptime for APIs - **Observable**: Log all external interactions **Reference**: `/docs/DSS_ORGANISM_GUIDE.md#4-the-nervous-system` ### 3.5 The Circulatory System 🩸 - Token Distribution **Function**: Distribute tokens throughout the system to where they're needed **Distribution Network**: - Token → CSS Variables - Token → Storybook Documentation - Token → Component Generation - Token → External Integrations **Design Principles**: - **Consistency**: Same token everywhere - **Traceability**: Know where each token goes - **Performance**: Efficient distribution, caching - **Flexibility**: Multiple output formats **Reference**: `/docs/DSS_ORGANISM_GUIDE.md` (distributed throughout docs) --- ## 4. Keyboard Accessibility All interactive elements must be keyboard accessible. Users should be able to navigate and interact with the entire application using only the keyboard. ### Guidelines - **Tabindex Management** - Use `tabindex="0"` on all keyboard-accessible elements (buttons, links, inputs, custom components) - Use `tabindex="-1"` for elements that shouldn't be in the tab order but need programmatic focus - Never use positive tabindex values (e.g., `tabindex="1"`) - maintain natural DOM order - **Focus Styling** - Always implement `:focus-visible` CSS for keyboard users - Ensure 3:1 contrast ratio for focus indicators - Use outline or box-shadow, not display/visibility changes - Apply consistently across all interactive elements - **Keyboard Event Handlers** - **Enter/Space**: Activate buttons and toggles - **Escape**: Close modals, sidebars, and collapsible panels - **Arrow Keys**: Navigate lists, tabs, and menus - **Alt+Key**: Power user shortcuts for common actions ### Web Component Implementation ```javascript class MyButton extends HTMLElement { static get observedAttributes() { return ['disabled', 'tabindex', 'aria-label', 'aria-expanded']; } setupEventListeners() { // Handle Enter/Space for activation this.keydownHandler = (e) => { if ((e.key === 'Enter' || e.key === ' ') && !this.disabled) { e.preventDefault(); this.shadowRoot.querySelector('button').click(); } }; this.addEventListener('keydown', this.keydownHandler); } render() { const tabindex = this.disabled ? '-1' : (this.getAttribute('tabindex') || '0'); // ... delegate tabindex to internal button } disconnectedCallback() { this.removeEventListener('keydown', this.keydownHandler); } } ``` **Reference**: `/admin-ui/js/components/ds-button.js:79-96` --- ## 2. ARIA & Screen Reader Support Screen reader users need semantic information about UI elements, their state, and purpose. ### Guidelines - **Labeling** - Always use `aria-label` on icon-only buttons - Use `aria-label` on elements without visible text - Example: `` - **State Indication** - Use `aria-expanded="true|false"` for toggles/collapsible elements - Use `aria-pressed="true|false"` for toggle buttons - Use `aria-invalid="true"` on form fields with errors - Update ARIA attributes when state changes - **Relationships** - Use `aria-controls="id"` to link controls to their targets - Use `aria-describedby="id"` to link inputs to error messages - Use `aria-labelledby="id"` to link to headings when appropriate - Use `aria-hidden="true"` on decorative elements (SVGs, icons) - **Semantic Roles** - Use native HTML elements when possible (button, input, link) - Use `role="button"` only on divs styled as buttons (not ideal) - Use `role="alert"` on error messages that appear dynamically - Always prefer semantic HTML over generic divs - **Error Handling** - Generate unique IDs for error messages - Link errors to inputs: `aria-describedby="error-{id}"` - Use `role="alert"` so screen readers announce errors - Set `aria-invalid="true"` on the input element ### Web Component Implementation ```javascript class MyInput extends HTMLElement { static get observedAttributes() { return ['aria-label', 'aria-invalid', 'aria-describedby', 'error']; } render() { const hasError = !!this.getAttribute('error'); const errorId = hasError ? `error-${Math.random().toString(36).substr(2, 9)}` : ''; const ariaInvalid = hasError ? 'aria-invalid="true"' : ''; const ariaDescribedBy = hasError ? `aria-describedby="${errorId}"` : ''; const ariaLabel = this.getAttribute('aria-label') || this.label || ''; this.shadowRoot.innerHTML = ` ${hasError ? `` : ''} `; } } ``` **Reference**: `/admin-ui/js/components/ds-input.js:172-240` --- ## 3. Web Component Lifecycle Management Memory leaks from accumulated event listeners are a critical performance issue in SPAs. Web Components must properly manage their lifecycle. ### Guidelines - **Connection/Disconnection** - Implement both `connectedCallback()` and `disconnectedCallback()` - `connectedCallback()`: Create shadow DOM, render, attach listeners - `disconnectedCallback()`: Remove all listeners, clean up references - **Event Listener Storage** - Store listener references on `this` for later cleanup - Never attach anonymous functions without storing references - Example: `this.clickHandler = (e) => { ... }` - Later: `element.removeEventListener('click', this.clickHandler)` - **Attribute Observation** - Implement `observedAttributes()` static getter - Include all attributes that affect rendering: `disabled`, `tabindex`, ARIA attributes - In `attributeChangedCallback()`, cleanup old listeners before re-rendering ### Implementation Pattern ```javascript class MyComponent extends HTMLElement { static get observedAttributes() { return ['disabled', 'tabindex', 'aria-label']; } connectedCallback() { this.render(); this.setupEventListeners(); } disconnectedCallback() { this.cleanupEventListeners(); } setupEventListeners() { // Store references this.clickHandler = (e) => { /* ... */ }; this.focusHandler = (e) => { /* ... */ }; const button = this.shadowRoot.querySelector('button'); button.addEventListener('click', this.clickHandler); this.addEventListener('focus', this.focusHandler); } cleanupEventListeners() { const button = this.shadowRoot?.querySelector('button'); if (button && this.clickHandler) { button.removeEventListener('click', this.clickHandler); delete this.clickHandler; } if (this.focusHandler) { this.removeEventListener('focus', this.focusHandler); delete this.focusHandler; } } } ``` **Reference**: `/admin-ui/js/components/ds-button.js:27-113` --- ## 4. Event Delegation & Listener Accumulation Prevention High-volume event listeners create memory pressure. Use event delegation and guard flags. ### Guidelines - **Use Document-Level Delegation** - Instead of: `buttons.forEach(b => b.addEventListener('click', handler))` - Do: `document.addEventListener('click', (e) => { const btn = e.target.closest('[data-action]'); ... })` - Benefit: One listener for N elements, regardless of count - **Guard Flags** - Prevent re-attachment on re-renders - Check flag before attaching: `if (!this.listeners.hasActionListener) { ... }` - Set flag after attachment: `this.listeners.hasActionListener = true;` - **Data-Driven Actions** - Use `data-action` attributes instead of inline onclick handlers - Router actions through a single switch statement - Example: `` ### Implementation Pattern ```javascript attachEventHandlers() { // Guard: only attach once, even if called multiple times if (!this.listeners.hasActionListener) { document.addEventListener('click', (e) => { const btn = e.target.closest('[data-action]'); if (!btn) return; const action = btn.dataset.action; switch (action) { case 'toggle-theme': this.toggleTheme(); break; case 'load-audit': this.loadAuditLog(); break; // ... more actions } }); this.listeners.hasActionListener = true; } } ``` **Reference**: `/admin-ui/js/core/app.js:2202-2414` --- ## 5. Security: No Global State Pollution Never expose critical classes or functions to `window`. Always use ES6 module imports. ### Guidelines - **No Window Assignments** - ❌ `window.app = app;` - ❌ `window.themeManager = themeManager;` - ✅ Use: `import app from './core/app.js';` - **Risk Mitigation** - Malicious/poorly-written third-party scripts can't hijack your code - Prevents accidental global namespace pollution - Makes code dependencies explicit and traceable - **Development Debugging** - If debugging requires window access, check environment first - Example: Only expose in development mode - Use: `if (process.env.NODE_ENV === 'development') { window.debug = {...}; }` ### Implementation ```javascript // ❌ DON'T DO THIS const app = new App(); window.app = app; // ✅ DO THIS const app = new App(); export default app; // In other files: import app from './app.js'; ``` **Reference**: `/admin-ui/js/core/app.js` (removed window exposure), `/admin-ui/index.html:750` --- ## 6. Security: Sanitize HTML Input Always sanitize HTML before insertion into the DOM. Use DOMPurify. ### Guidelines - **Never Use Unsafe Insertion** - ❌ `element.innerHTML = userInput;` - ❌ `element.innerHTML = apiResponse;` - ✅ Use: `sanitizeHtml()` and `setSafeHtml()` - **DOMPurify Configuration** - Default settings block dangerous attributes (onclick, onerror, etc.) - Whitelist only necessary tags and attributes - Strip scripts while preserving content - **Content Sources Requiring Sanitization** - User input (forms, search, comments) - API responses (markdown, rich text, HTML) - External data (imported content, integrations) ### Implementation ```javascript import { setSafeHtml, sanitizeHtml } from './sanitizer.js'; // Safe HTML insertion const htmlContent = `

${name}

${description}

`; setSafeHtml(element, htmlContent); // Sanitize and retrieve const clean = sanitizeHtml(userInput); ``` **Reference**: `/admin-ui/js/core/sanitizer.js`, `/admin-ui/js/core/app.js:28` --- ## 7. Non-Invasive Network Monitoring Never monkey-patch native APIs. Use non-invasive alternatives. ### Guidelines - **Don't Monkey-Patch Global Functions** - ❌ `window.fetch = async (...) => { ... }` - ❌ Breaks third-party integrations - ❌ Causes race conditions - **Use Platform APIs Instead** - ✅ `PerformanceObserver` for network monitoring - ✅ Browser Performance API for metrics - ✅ Event listeners on `window` for errors - **Graceful Degradation** - Check if API is available: `if ('PerformanceObserver' in window)` - Try/catch for unsupported browsers - Continue functionality if monitoring unavailable ### Implementation ```javascript captureNetworkActivity() { if ('PerformanceObserver' in window) { try { const observer = new PerformanceObserver((list) => { for (const entry of list.getEntries()) { if (entry.initiatorType === 'fetch' || entry.initiatorType === 'xmlhttprequest') { this.log('network', entry.initiatorType, `${entry.name}`, { duration: entry.duration, transferSize: entry.transferSize }); } } }); observer.observe({ entryTypes: ['resource'] }); } catch (e) { // Graceful degradation - network logging won't work } } } ``` **Reference**: `/admin-ui/js/core/browser-logger.js:134-162` --- ## 8. Focus Management Maintain user's context by managing focus properly during UI updates. ### Guidelines - **Focus Delegation** - Web Components should delegate focus to internal focusable element - Implement focus() method that focuses internal input/button - **Focus Restoration** - Store focused element before UI change - Restore focus after update if appropriate - Announce focus changes to screen readers - **Aria-Expanded Updates** - Update `aria-expanded` when toggles change state - Ensures screen readers announce state changes - Example: `toggleBtn.setAttribute('aria-expanded', isOpen);` ### Implementation ```javascript class MyComponent extends HTMLElement { focus() { // Delegate focus to internal input this.shadowRoot.querySelector('input')?.focus(); } togglePanel() { const isOpen = !this.isOpen; this.isOpen = isOpen; // Update ARIA state this.setAttribute('aria-expanded', isOpen); // Restore focus to toggle button after panel opens if (isOpen) { this.focus(); } } } ``` **Reference**: `/admin-ui/js/core/app.js:2495-2502` --- ## 9. Semantic HTML Over Custom Divs Use native HTML elements. They provide built-in accessibility. ### Guidelines - **Prefer Native Elements** - ✅ `