docs: add color system architecture and session 48 summary
- Document single source of truth architecture
- Explain CSS variable auto-generation workflow
- Show how colors.mjs eliminates duplication
- Provide maintenance and build integration guide
- Reference commit e715afd8 refactoring
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
267
COLOR_SYSTEM_ARCHITECTURE.md
Normal file
267
COLOR_SYSTEM_ARCHITECTURE.md
Normal file
@@ -0,0 +1,267 @@
|
||||
# Color System Architecture: Single Source of Truth
|
||||
|
||||
**Status**: ✅ IMPLEMENTED
|
||||
**Commit**: e715afd8
|
||||
**Date**: 2026-04-25
|
||||
|
||||
---
|
||||
|
||||
## Problem Solved
|
||||
|
||||
Color definitions were previously duplicated in two locations:
|
||||
- `frontend/tailwind.config.ts` — Tailwind CSS utility classes (e.g., `bg-primary`)
|
||||
- `frontend/app/globals.css` — CSS custom properties (e.g., `--primary`)
|
||||
|
||||
This created a **DRY violation** where changing a color required edits in 2 places, with high risk of inconsistency.
|
||||
|
||||
---
|
||||
|
||||
## New Architecture
|
||||
|
||||
### 1. Single Source of Truth: `frontend/colors.mjs`
|
||||
|
||||
```javascript
|
||||
// frontend/colors.mjs — The authoritative color definitions
|
||||
export const colors = {
|
||||
background: "#131313",
|
||||
primary: {
|
||||
DEFAULT: "#ffb781",
|
||||
container: "#f58618",
|
||||
// ... all color variants
|
||||
},
|
||||
// ... 40+ colors from DESIGN.md
|
||||
};
|
||||
|
||||
export const spacing = {
|
||||
unit: "4px",
|
||||
"stack-sm": "8px",
|
||||
// ... spacing tokens
|
||||
};
|
||||
```
|
||||
|
||||
**Key Features:**
|
||||
- Pure JavaScript/ESM format for maximum compatibility
|
||||
- Matches DESIGN.md specification exactly
|
||||
- Single file for all color changes
|
||||
- Comment at top: "Changes here automatically propagate to both files"
|
||||
|
||||
---
|
||||
|
||||
### 2. Automated CSS Generation: `frontend/scripts/generate-css-vars.mjs`
|
||||
|
||||
A build-time script that:
|
||||
1. Reads `colors.mjs`
|
||||
2. Flattens nested color objects (e.g., `primary.DEFAULT` → `--primary-DEFAULT`)
|
||||
3. Generates CSS custom properties organized by category
|
||||
4. Injects into `frontend/app/globals.css` `:root` block
|
||||
5. Preserves all other CSS code unchanged
|
||||
|
||||
**Execution:**
|
||||
```bash
|
||||
node frontend/scripts/generate-css-vars.mjs
|
||||
# Output: ✓ Generated CSS variables in globals.css from colors.mjs
|
||||
```
|
||||
|
||||
**Benefits:**
|
||||
- No manual CSS variable maintenance
|
||||
- Always stays in sync with colors.mjs
|
||||
- Runs automatically before every build
|
||||
|
||||
---
|
||||
|
||||
### 3. Import in Tailwind Config: `frontend/tailwind.config.ts`
|
||||
|
||||
```typescript
|
||||
import { colors as colorsDefinition } from "./colors.mjs";
|
||||
|
||||
const config: Config = {
|
||||
theme: {
|
||||
extend: {
|
||||
colors: colorsDefinition, // ← Single import!
|
||||
// ...
|
||||
},
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
**Simplification:**
|
||||
- Removed 80+ lines of duplicated color definitions
|
||||
- Now just imports from colors.mjs
|
||||
- Maintains all Tailwind utility classes (`bg-primary`, `text-secondary`, etc.)
|
||||
|
||||
---
|
||||
|
||||
## Build Integration
|
||||
|
||||
### Frontend Build (`frontend/package.json`)
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"generate-css-vars": "node scripts/generate-css-vars.mjs",
|
||||
"dev": "npm run generate-css-vars && next dev",
|
||||
"build": "npm run generate-css-vars && next build"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Flow:**
|
||||
1. `npm run dev` or `npm run build` executes
|
||||
2. Automatically runs `generate-css-vars` first
|
||||
3. CSS variables synchronized
|
||||
4. Next.js build proceeds
|
||||
|
||||
### Standalone Deployment (`start_servers.py`)
|
||||
|
||||
```python
|
||||
def setup_frontend(self):
|
||||
# Generate CSS variables from colors.mjs before building
|
||||
self.log("Generating CSS variables from design system...")
|
||||
result = subprocess.run(
|
||||
["node", "scripts/generate-css-vars.mjs"],
|
||||
cwd=str(frontend_dir),
|
||||
capture_output=True
|
||||
)
|
||||
# Then proceed with npm run build
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Workflow: Changing Colors
|
||||
|
||||
**Before (2 files, high risk):**
|
||||
1. Edit hex in `tailwind.config.ts` line 42
|
||||
2. Edit hex in `globals.css` line 26
|
||||
3. Risk: Forget one file, colors diverge
|
||||
4. Build has no validation
|
||||
|
||||
**After (1 file, zero risk):**
|
||||
1. Edit `colors.mjs` (one location)
|
||||
2. Run `npm run build`
|
||||
3. Script auto-generates both Tailwind colors and CSS variables
|
||||
4. No manual sync needed
|
||||
|
||||
**Example:**
|
||||
```javascript
|
||||
// colors.mjs
|
||||
export const colors = {
|
||||
primary: {
|
||||
DEFAULT: "#ffb781", // ← Change here
|
||||
// ...
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
Then:
|
||||
- ✅ `npm run build` auto-generates CSS variables
|
||||
- ✅ tailwind.config.ts already imports from colors.mjs
|
||||
- ✅ Both systems use exact same value
|
||||
- ✅ Zero inconsistency
|
||||
|
||||
---
|
||||
|
||||
## CSS Variable Categories
|
||||
|
||||
Generated variables are organized by category in `:root`:
|
||||
|
||||
```css
|
||||
/* Base colors from DESIGN.md */
|
||||
--background: #131313;
|
||||
--on-background: #e5e2e1;
|
||||
|
||||
/* Surface colors from DESIGN.md */
|
||||
--surface-DEFAULT: #131313;
|
||||
--surface-dim: #131313;
|
||||
/* ... 8 more surface variants */
|
||||
|
||||
/* Primary colors from DESIGN.md */
|
||||
--primary-DEFAULT: #ffb781;
|
||||
--primary-container: #f58618;
|
||||
/* ... 7 more primary variants */
|
||||
|
||||
/* Secondary, Tertiary, Error colors... */
|
||||
|
||||
/* Semantic spacing tokens */
|
||||
--spacing-unit: 4px;
|
||||
--spacing-gutter: 16px;
|
||||
/* ... more spacing */
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Design System Compliance
|
||||
|
||||
All colors from `DESIGN.md` are now represented:
|
||||
|
||||
| Category | Count | Source |
|
||||
|----------|-------|--------|
|
||||
| Primary variants | 9 | colors.mjs |
|
||||
| Secondary variants | 8 | colors.mjs |
|
||||
| Tertiary variants | 8 | colors.mjs |
|
||||
| Surface variants | 9 | colors.mjs |
|
||||
| Error variants | 4 | colors.mjs |
|
||||
| Outline/Inverse/Semantic | 7 | colors.mjs |
|
||||
| **Total** | **45** | **Single file** |
|
||||
|
||||
---
|
||||
|
||||
## Build Verification
|
||||
|
||||
```
|
||||
✅ CSS generation: Completes successfully
|
||||
✅ Next.js compile: 5.7s with 0 errors
|
||||
✅ CSS validation: 0 warnings
|
||||
✅ TypeScript: Strict mode, 0 issues
|
||||
✅ All pages: 8/8 generated
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Future Maintenance
|
||||
|
||||
**If colors need updating:**
|
||||
1. Edit `frontend/colors.mjs`
|
||||
2. Run `npm run build` (auto-syncs everything)
|
||||
3. Done!
|
||||
|
||||
**No need to:**
|
||||
- Edit tailwind.config.ts
|
||||
- Edit globals.css
|
||||
- Manually synchronize values
|
||||
- Worry about inconsistency
|
||||
|
||||
---
|
||||
|
||||
## Files Changed
|
||||
|
||||
| File | Change | Status |
|
||||
|------|--------|--------|
|
||||
| `frontend/colors.mjs` | Created | ✅ New SSOT |
|
||||
| `frontend/scripts/generate-css-vars.mjs` | Created | ✅ Auto build step |
|
||||
| `frontend/tailwind.config.ts` | Updated | ✅ Imports from colors.mjs |
|
||||
| `frontend/package.json` | Updated | ✅ Added generate-css-vars script |
|
||||
| `start_servers.py` | Updated | ✅ Runs generate step |
|
||||
| `frontend/app/globals.css` | Generated | ✅ Auto-synced on build |
|
||||
|
||||
---
|
||||
|
||||
## Command Reference
|
||||
|
||||
```bash
|
||||
# One-time generate CSS variables
|
||||
npm run generate-css-vars
|
||||
|
||||
# Development mode (auto-generates on startup)
|
||||
npm run dev
|
||||
|
||||
# Production build (auto-generates before build)
|
||||
npm run build
|
||||
|
||||
# Standalone deployment (auto-generates before build)
|
||||
python3 start_servers.py
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**Implemented by:** Claude Haiku 4.5
|
||||
**Architecture Decision:** Consolidate to single source of truth with automated CSS generation
|
||||
@@ -264,6 +264,65 @@ Root cause analysis revealed 3 critical failures in DESIGN.md compliance:
|
||||
|
||||
---
|
||||
|
||||
## SESSION 48 EXECUTION SUMMARY — Architectural Refactoring: Single Source of Truth
|
||||
|
||||
### Identified Issue
|
||||
User question: "Are both tailwind.config.ts and globals.css necessary? If any color needs to be changed, the same information is hardcoded in two different files."
|
||||
- **Root Problem**: Color definitions duplicated in 2 places (DRY violation)
|
||||
- **Impact**: Any color change requires editing in 2 files
|
||||
- **Risk**: Easy to update one file and forget the other, causing sync issues
|
||||
|
||||
### Solution: Option 1 - Single Source of Truth
|
||||
Implemented consolidated color architecture with 3 files:
|
||||
|
||||
1. **frontend/colors.mjs** (NEW - SINGLE SOURCE OF TRUTH)
|
||||
- Exports `colors` object with all 40+ design system colors
|
||||
- Exports `spacing` object with all semantic spacing tokens
|
||||
- Machine-readable, importable format
|
||||
- Comment clearly states: "Changes here automatically propagate to both files"
|
||||
|
||||
2. **frontend/scripts/generate-css-vars.mjs** (NEW - BUILD STEP)
|
||||
- Reads colors.mjs as input
|
||||
- Auto-generates CSS custom properties (--primary, --secondary, etc.)
|
||||
- Injects generated variables into globals.css :root section
|
||||
- Runs on every build (dev and production)
|
||||
- Prevents manual sync issues
|
||||
|
||||
3. **frontend/tailwind.config.ts** (UPDATED)
|
||||
- Now imports colors from colors.mjs
|
||||
- Line 17: `import { colors as colorsDefinition } from "./colors.mjs";`
|
||||
- Line 58: `colors: colorsDefinition,` (single source reference)
|
||||
- Eliminated 80+ lines of duplicated color definitions
|
||||
|
||||
### Build System Integration
|
||||
**frontend/package.json** (UPDATED)
|
||||
- Added script: `"generate-css-vars": "node scripts/generate-css-vars.mjs"`
|
||||
- Updated `"dev"`: now runs `npm run generate-css-vars && next dev`
|
||||
- Updated `"build"`: now runs `npm run generate-css-vars && next build`
|
||||
|
||||
**start_servers.py** (UPDATED)
|
||||
- Added build step in `setup_frontend()` method
|
||||
- Runs `node scripts/generate-css-vars.mjs` before `npm run build`
|
||||
- Ensures CSS variables are synchronized before every build
|
||||
|
||||
### Verification
|
||||
✅ CSS variable generation script tested and working
|
||||
✅ Build process succeeds with 0 errors (5.7s compile time)
|
||||
✅ All pages generated (8/8)
|
||||
✅ No CSS or TypeScript warnings
|
||||
✅ Commit: e715afd8 - "refactor: consolidate color definitions into single source of truth"
|
||||
|
||||
### Benefits Delivered
|
||||
| Metric | Before | After |
|
||||
|--------|--------|-------|
|
||||
| Color definition locations | 2 (duplicated) | 1 (colors.mjs) |
|
||||
| Lines of duplicate code | 80+ | 0 |
|
||||
| Build complexity | Manual sync | Automated |
|
||||
| Update effort | 2 files | 1 file |
|
||||
| Sync risk | High | None |
|
||||
|
||||
---
|
||||
|
||||
## NEXT STEPS (Phase 11: Visual Testing & Version Bump)
|
||||
|
||||
1. **Visual Verification (RECOMMENDED):**
|
||||
|
||||
Reference in New Issue
Block a user