{"id":45822753,"url":"https://github.com/maggieappleton/ektachrome","last_synced_at":"2026-02-26T21:01:15.476Z","repository":{"id":336830400,"uuid":"1151301610","full_name":"MaggieAppleton/ektachrome","owner":"MaggieAppleton","description":null,"archived":false,"fork":false,"pushed_at":"2026-02-06T10:58:27.000Z","size":11,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-02-06T18:02:10.535Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MaggieAppleton.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-06T09:47:28.000Z","updated_at":"2026-02-06T10:58:30.000Z","dependencies_parsed_at":"2026-02-06T18:02:14.615Z","dependency_job_id":null,"html_url":"https://github.com/MaggieAppleton/ektachrome","commit_stats":null,"previous_names":["maggieappleton/ektachrome"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/MaggieAppleton/ektachrome","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MaggieAppleton%2Fektachrome","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MaggieAppleton%2Fektachrome/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MaggieAppleton%2Fektachrome/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MaggieAppleton%2Fektachrome/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MaggieAppleton","download_url":"https://codeload.github.com/MaggieAppleton/ektachrome/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MaggieAppleton%2Fektachrome/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29872669,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-26T18:42:30.764Z","status":"ssl_error","status_checked_at":"2026-02-26T18:41:47.936Z","response_time":89,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-02-26T21:00:47.837Z","updated_at":"2026-02-26T21:01:15.459Z","avatar_url":"https://github.com/MaggieAppleton.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Ektachrome\n\nA design system refinement tool with live visual feedback. Select any element in a running app, see which design tokens control it, and adjust them with constrained controls that enforce design system consistency — all with instant, live updates across the entire app.\n\n## Vision\n\nMost design tools let you change any CSS property to any value. Ektachrome is different: it helps you **build, audit, and refine a design system** through direct manipulation. Every adjustment happens within structured constraints — spacing on a grid, colors mapped to tokens, typography on a scale — so the result is always a coherent system, not a collection of one-off overrides.\n\n## Installation\n\n```bash\nnpm install ektachrome\n```\n\n## Usage Modes\n\nEktachrome works in two modes:\n\n### Basic Mode\n\nWorks in any project (React, Vue, Svelte, plain HTML). Import and initialise:\n\n```js\nimport { Ektachrome } from 'ektachrome';\n\nconst ektachrome = new Ektachrome();\nektachrome.activate();\n```\n\n- Live editing works via CSS custom properties\n- Changes persist to localStorage across page reloads\n- Use \"Copy CSS\" to export changes manually\n\n### Enhanced Mode (Vite)\n\nIf your project uses Vite, add the plugin for automatic write-back to source CSS files:\n\n```js\n// vite.config.js\nimport { ektachromePlugin } from 'ektachrome/server/vite-plugin.js';\n\nexport default {\n  plugins: [\n    ektachromePlugin({\n      include: ['src/**/*.css'],\n      exclude: ['node_modules/**']\n    })\n  ]\n}\n```\n\nWith the plugin:\n- Changes are written directly to your CSS source files\n- Review diffs before committing\n- Full version control integration\n\n## How It Works\n\n### Two Phases\n\n#### Phase 1: Audit \u0026 Setup (Claude-assisted, run once per app)\n\nBefore live editing, Ektachrome scans the app's stylesheets and uses Claude to understand the current state of the design system:\n\n1. **Scan**: Collect all CSS custom properties, raw color values, spacing values, font sizes, and border radii from all stylesheets\n2. **Analyze**: Claude identifies which values map to tokens, which are hardcoded, and where inconsistencies exist\n3. **Report**: Generate a design system audit showing:\n   - How many color tokens exist vs. hardcoded colors\n   - Whether spacing follows a consistent grid (4px, 8px, etc.)\n   - How many typography scale stops are defined\n   - Border radius consistency\n4. **Propose**: Claude suggests a variable mapping to clean up inconsistencies (e.g., \"Map `#3b82f6` to `--color-primary`\")\n5. **Apply**: User approves, Claude Code applies the refactor to source files\n6. **Cache**: Build a `variableMap` that maps every computed style value back to its source token for instant lookups during refinement\n\n#### Phase 2: Live Refinement (zero latency, no model needed)\n\nOnce the design system is clean:\n\n1. **Select**: Click any element in the running app. An element picker highlights it and identifies it (tag, classes, React components, CSS path)\n2. **Inspect**: A toolbar popup shows which design tokens control the selected element's visual properties\n3. **Adjust**: Constrained controls let you tune each property — colors via OKLCH pickers (mapped to tokens), spacing via stepped grid controls, typography and radii via named scale pickers\n4. **Live update**: Every adjustment immediately calls `document.documentElement.style.setProperty()` on the CSS variable, so changes ripple across the entire app instantly\n5. **Commit**: When satisfied, serialize the adjusted token values and write them back to source files\n\n### Where Claude Sits\n\nClaude is needed at three specific moments, not continuously:\n\n| Moment | What Claude does | Latency |\n|--------|-----------------|---------|\n| **Audit** | Scan stylesheets, identify tokens, find inconsistencies | 10-30s (run once) |\n| **Variable resolution** | When the pure JS scanner can't resolve which token controls an element | 2-3s (rare, per element) |\n| **Commit** | Generate code changes to persist slider adjustments back to source | 5-10s (when done) |\n\nThe live slider interaction is **zero latency, zero model involvement**. It's pure CSS custom property manipulation.\n\n## Architecture\n\n```\n┌──────────────────────────────────────────────────────────┐\n│  Running App (any framework using CSS variables)         │\n│                                                          │\n│  1. User clicks element                                  │\n│     → Element picker identifies it                       │\n│     → Captures computed styles + CSS selectors            │\n│                                                          │\n│  2. Mini-toolbar appears: Color | Spacing | Type | ...   │\n│     → User picks \"Color\"                                 │\n│                                                          │\n│  3. Variable map lookup (instant, cached from audit)     │\n│     → Finds: --color-primary controls this element's bg  │\n│     → Knows it's used in 47 other places                 │\n│                                                          │\n│  4. Dynamically generate constrained controls            │\n│     → OKLCH picker bound to --color-primary              │\n│     → Shows usage count and token name                   │\n│                                                          │\n│  5. User adjusts sliders → LIVE updates via              │\n│     document.documentElement.style.setProperty(          │\n│       '--color-primary', 'oklch(0.6 0.2 250)'          │\n│     → Every element using this token updates instantly   │\n│                                                          │\n│  6. \"Commit\" → Write new values to source files          │\n└──────────────────────────────────────────────────────────┘\n```\n\n### File Structure\n\n```\nektachrome/\n├── src/\n│   ├── index.js                    # Entry point\n│   ├── controls/                   # Web Components (Shadow DOM)\n│   │   ├── oklch-picker.js         # L/C/H color sliders\n│   │   ├── color-token-control.js  # Token-aware color control\n│   │   ├── spacing-step-control.js # Stepped spacing (4px grid)\n│   │   ├── scale-picker.js         # Type/radius scale picker\n│   │   ├── toolbar-popup.js        # Main UI + persistence\n│   │   └── commit-panel.js         # Pending changes UI for write-back\n│   ├── picker/\n│   │   └── element-picker.js       # Click-to-select element picker\n│   ├── scanner/\n│   │   ├── detect-css-vars.js      # Find CSS vars used by an element\n│   │   ├── variable-map.js         # Computed→token mapping\n│   │   └── design-system-audit.js  # Full stylesheet audit\n│   ├── bridge/\n│   │   └── variable-discovery.js   # Claude API fallback for var resolution\n│   └── utils/\n│       ├── config.js               # .env loader\n│       ├── color-conversion.js     # RGB↔OKLCH\n│       ├── stylesheet-scanner.js   # Shared iteration\n│       ├── property-categories.js  # Category matchers\n│       ├── theme.js                # UI constants\n│       ├── claude-client.js        # API client\n│       └── state-persistence.js    # localStorage + change tracking\n│\n└── server/                         # Vite plugin for write-back (Node.js)\n    ├── vite-plugin.js              # HTTP middleware endpoints\n    └── css-parser.js               # Parse and modify CSS files\n```\n\n## Constrained Control Types\n\n### Colors: Token Picker, Not Freeform\n\nWhen you select an element and pick \"Color\", you see **which color token** this element uses and how many other elements share it. You adjust the token's OKLCH value, and it ripples everywhere.\n\n- Shows token name (e.g., `--color-primary`)\n- Shows usage count (e.g., \"used 47×\")\n- Warns when changing high-usage tokens\n- Uses OKLCH color space for perceptually uniform adjustments\n\n### Spacing: Stepped Grid, Not Arbitrary\n\nInstead of a continuous slider, spacing shows discrete steps on your grid:\n\n- Base unit configurable (default: 4px)\n- Scale: `0, 4, 8, 12, 16, 24, 32, 48, 64`\n- Visual bar chart showing the scale with active step highlighted\n- Maps to spacing tokens (e.g., `--space-4`, `--space-8`)\n\n### Typography: Named Scale Picker\n\nPick from named stops, not arbitrary pixel values:\n\n- `XS` (0.75rem) → `SM` (0.875rem) → `Base` (1rem) → `LG` (1.125rem) → `XL` (1.25rem) → `2XL` (1.5rem) → `3XL` (1.875rem)\n- Rendered as a horizontal segmented control\n- Maps to type tokens (e.g., `--text-sm`, `--text-lg`)\n\n### Border Radius: Named Scale Picker\n\nSame pattern as typography:\n\n- `none` (0) → `sm` (2px) → `md` (4px) → `lg` (8px) → `xl` (12px) → `2xl` (16px) → `full` (9999px)\n- Maps to radius tokens (e.g., `--radius-md`)\n\n## Key Design Decisions\n\n### Framework-Agnostic\n\nAll controls are Web Components using Shadow DOM. They work in any app — React, Svelte, plain HTML. The element picker is pure DOM manipulation. No framework dependency.\n\n### Design System First\n\nYou can't change \"this one button's color\". You change `--color-primary`, which changes every element that uses it. This is a feature, not a limitation. It forces coherent design.\n\n### No MCP Server Required\n\nThe Claude integration is a simple `fetch` to the Anthropic API. No server infrastructure, no MCP protocol. Just a single API call for audit and a single call for variable resolution when needed.\n\n### Builds on Kodachrome\n\nThe OKLCH picker and slider Web Components from [Kodachrome](https://github.com/MaggieAppleton/kodachrome) are the foundation. Ektachrome extends them with token awareness and constrained scales.\n\n### Borrows from Agentation\n\nThe element selection pattern (click-to-select, hover highlights, element identification via class names/IDs/text content, CSS path generation) is adapted from [Agentation](https://github.com/benjitaylor/agentation), ported to be framework-agnostic.\n\n## Claude Integration (Optional)\n\nSet `ANTHROPIC_API_KEY` in `.env` for:\n- **Audit** — Design system analysis\n- **Variable discovery** — Fallback when JS scanner fails\n\n## Write-Back Workflow (Enhanced Mode)\n\n1. Run your Vite dev server: `npm run dev`\n2. Activate Ektachrome in browser\n3. Click elements, adjust tokens\n4. Click the \"changes\" badge when ready\n5. Review diff, click \"Commit All\"\n6. Changes are written to your CSS files\n\n## Prior Art\n\n- **[Kodachrome](https://github.com/MaggieAppleton/kodachrome)** — Live control panel with OKLCH pickers and sliders. Ektachrome inherits the Web Component architecture and control-change event pattern.\n- **[Agentation](https://github.com/benjitaylor/agentation)** — Visual feedback tool for AI agents. Ektachrome borrows the element picker, identification, and CSS path generation patterns.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaggieappleton%2Fektachrome","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmaggieappleton%2Fektachrome","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaggieappleton%2Fektachrome/lists"}