designlang 7.1.0 → 8.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/README.md +46 -4
  3. package/bin/design-extract.js +28 -2
  4. package/package.json +1 -1
  5. package/src/config.js +4 -1
  6. package/src/crawler.js +376 -6
  7. package/src/extractors/accessibility.js +44 -1
  8. package/src/extractors/colors.js +50 -12
  9. package/src/extractors/interaction-states.js +57 -0
  10. package/src/extractors/modern-css.js +100 -0
  11. package/src/extractors/scoring.js +49 -30
  12. package/src/extractors/token-sources.js +65 -0
  13. package/src/extractors/wide-gamut.js +47 -0
  14. package/src/formatters/routes-reconciliation.js +160 -0
  15. package/src/index.js +29 -0
  16. package/src/utils/color-gamut.js +82 -0
  17. package/.github/FUNDING.yml +0 -1
  18. package/.github/ISSUE_TEMPLATE/bug_report.yml +0 -62
  19. package/.github/ISSUE_TEMPLATE/config.yml +0 -8
  20. package/.github/ISSUE_TEMPLATE/feature_request.yml +0 -28
  21. package/chrome-extension/README.md +0 -41
  22. package/chrome-extension/icons/favicon.svg +0 -7
  23. package/chrome-extension/icons/icon-128.png +0 -0
  24. package/chrome-extension/icons/icon-16.png +0 -0
  25. package/chrome-extension/icons/icon-32.png +0 -0
  26. package/chrome-extension/icons/icon-48.png +0 -0
  27. package/chrome-extension/manifest.json +0 -26
  28. package/chrome-extension/popup.html +0 -167
  29. package/chrome-extension/popup.js +0 -59
  30. package/docs/superpowers/plans/2026-04-18-designlang-v7.md +0 -1121
  31. package/docs/superpowers/specs/2026-04-18-designlang-v7-design.md +0 -150
  32. package/docs/superpowers/specs/2026-04-18-website-redesign-design.md +0 -120
  33. package/docs/superpowers/specs/2026-04-19-designlang-v7-1-design.md +0 -111
  34. package/tests/cli.test.js +0 -84
  35. package/tests/cookies.test.js +0 -98
  36. package/tests/extractors.test.js +0 -792
  37. package/tests/formatters.test.js +0 -709
  38. package/tests/mcp.test.js +0 -68
  39. package/tests/utils.test.js +0 -413
  40. package/website/.claude/launch.json +0 -11
  41. package/website/AGENTS.md +0 -5
  42. package/website/CLAUDE.md +0 -1
  43. package/website/README.md +0 -36
  44. package/website/app/api/extract/route.js +0 -245
  45. package/website/app/components/A11ySlider.js +0 -369
  46. package/website/app/components/Comparison.js +0 -286
  47. package/website/app/components/CssHealth.js +0 -243
  48. package/website/app/components/Extractor.js +0 -184
  49. package/website/app/components/HeroExtractor.js +0 -455
  50. package/website/app/components/Marginalia.js +0 -3
  51. package/website/app/components/McpSection.js +0 -223
  52. package/website/app/components/PlatformTabs.js +0 -250
  53. package/website/app/components/RegionsComponents.js +0 -429
  54. package/website/app/components/Rule.js +0 -13
  55. package/website/app/components/Specimens.js +0 -237
  56. package/website/app/components/StructuredData.js +0 -144
  57. package/website/app/components/TokenBrowser.js +0 -344
  58. package/website/app/components/token-browser-sample.js +0 -65
  59. package/website/app/globals.css +0 -505
  60. package/website/app/icon.svg +0 -7
  61. package/website/app/layout.js +0 -126
  62. package/website/app/opengraph-image.js +0 -170
  63. package/website/app/page.js +0 -352
  64. package/website/app/robots.js +0 -15
  65. package/website/app/seo-config.js +0 -82
  66. package/website/app/sitemap.js +0 -18
  67. package/website/jsconfig.json +0 -7
  68. package/website/lib/cache.js +0 -73
  69. package/website/lib/rate-limit.js +0 -30
  70. package/website/lib/rate-limit.test.js +0 -55
  71. package/website/lib/specimens.json +0 -86
  72. package/website/lib/token-helpers.js +0 -70
  73. package/website/lib/url-safety.js +0 -103
  74. package/website/lib/url-safety.test.js +0 -116
  75. package/website/lib/zip-files.js +0 -15
  76. package/website/next.config.mjs +0 -15
  77. package/website/package-lock.json +0 -1353
  78. package/website/package.json +0 -19
  79. package/website/public/favicon.svg +0 -7
  80. package/website/public/logo-specimen.svg +0 -76
  81. package/website/public/mark.svg +0 -12
  82. package/website/public/site.webmanifest +0 -13
package/CHANGELOG.md CHANGED
@@ -1,5 +1,54 @@
1
1
  # Changelog
2
2
 
3
+ ## [8.0.0] — 2026-04-20
4
+
5
+ A credibility-and-distribution release. Three reliability bugs that hurt trust on real sites are fixed; three DX flags close the most-requested CLI gaps; five new surfaces (VS Code, Raycast, Figma, GitHub Actions, MCP registry) ship alongside.
6
+
7
+ ### Reliability
8
+
9
+ - **Brand / primary color detection rewritten** — the extractor now ranks chromatic clusters by `interactiveBg × 100 + saturation × 2 + log(usage)` and requires either HSL saturation > 25 or an interactive-bg hit to qualify as chromatic. Previously the extractor picked the most-counted color, which on neutral-heavy sites like Linear meant the "Primary" was a pale gray (`#d0d6e0`). v8 correctly picks Linear's lime CTA (`#e4f222`) and Stripe's purple (`#533afd`). `src/extractors/colors.js`.
10
+ - **Accessibility scoring defused** — the crawler now emits a `hasText` boolean per element (a direct text-node child with visible characters), and the WCAG extractor filters out decorative glyph wrappers, transparent/overlay pairs, and non-text containers. Linear's WCAG score moved from 25% (171 failing pairs) to 83% (1 failing pair). `src/extractors/accessibility.js`, `src/crawler.js`.
11
+ - **Design-system score recalibrated** — thresholds for color count, shadow count, border-radii count, typography weight, and type-scale size were re-fit against ground-truth sites (Stripe, Linear, Vercel, GitHub, Apple). `cssHealth` is now weighted in the overall (8/100). Linear 47→76, Stripe 81→88, Apple 83→86, Vercel 64→76. `src/extractors/scoring.js`.
12
+
13
+ ### Added
14
+
15
+ - **`--selector <css>`** — scopes extraction to a DOM subtree (e.g. `designlang https://stripe.com --selector "footer"`). Stripe full-page extraction drops from 2,409 elements to 112 when scoped to the footer. Falls back to the full document if the selector is invalid or empty.
16
+ - **`--system-chrome`** — forces Playwright to use the locally installed Chrome (`channel: 'chrome'`) instead of the ~150 MB bundled Chromium, for faster `npx` first-runs in environments that already have Chrome.
17
+ - **`--json` output mode** — full extraction payload written to stdout (suppresses progress UI) for piping into other tools. This was a partial implementation in v7; v8 makes it first-class and adds it to the CLI reference.
18
+ - **VS Code extension** (`vscode-extension/`) — `designlang: Extract design from URL` and `designlang: Extract and inject into workspace` commands.
19
+ - **Raycast extension** (`raycast-extension/`) — Extract, Score, and "Copy CLI command for URL" commands.
20
+ - **Figma plugin** (`figma-plugin/`) — URL or paste-JSON → Figma Variables collections (MV for Figma's `figma.variables` API, with multi-mode support).
21
+ - **GitHub Action** (`github-action/`) — "Design regression guard": runs `designlang` on a URL, diffs tokens vs a committed baseline, and comments the delta on the pull request. Optional `fail-on-change`.
22
+ - **Smithery + MCP registry** (`smithery.yaml`, `smithery.dockerfile`, `docs/MCP-REGISTRY.md`) — one-command install in Smithery; checklist for the official MCP registry, Cursor, and Claude Desktop.
23
+ - **Chrome Web Store + Firefox + Edge listing prep** (`chrome-extension/PRIVACY.md`, `chrome-extension/STORE_LISTING.md`) — privacy policy and store copy.
24
+ - **README hero demo tape** (`docs/demo.tape`) — VHS script that renders an animated terminal GIF into `website/public/demo.gif`.
25
+ - **Launch kit** (`docs/LAUNCH.md`) — Product Hunt / Show HN / Twitter copy + day-of checklist.
26
+
27
+ ### Changed
28
+
29
+ - README: hero image now references the animated demo (with static PNG fallback), adds an "Install everywhere" table covering all surfaces, documents `--selector`, `--system-chrome`, and `--json`.
30
+ - `.npmignore`: excludes all companion-surface directories (`vscode-extension/`, `raycast-extension/`, `figma-plugin/`, `github-action/`, `chrome-extension/`, `website/`) and test fixtures so the npm tarball stays small — each surface publishes to its own registry.
31
+ - `bin/design-extract.js`: reports `8.0.0` from `--version`.
32
+ - `src/config.js`: whitelists `selector` and `systemChrome` from CLI/config.
33
+
34
+ ### Thanks
35
+
36
+ - To everyone who flagged that Linear's primary was coming out as light gray — that single complaint drove the brand-color rewrite.
37
+
38
+ ## [7.2.0] — 2026-04-19
39
+
40
+ ### Added
41
+
42
+ - **Modern CSS surfacing (Tier 1a)** — crawler now captures pseudo-elements, variable-font axes (`font-variation-settings`), `@container` queries, and `env()` usage. Surfaced on `design.modernCss`. (#33)
43
+ - **Wide-gamut color + CSS source attribution (Tier 1b)** — `oklch()`, `oklab()`, `color-mix()`, `light-dark()`, Display P3, and Rec2020 references are collected on `design.wideGamut`. A new `design.tokenSources` maps each extracted token to the stylesheet URL it first appeared in. (#34)
44
+ - **Auto-interact pass (Tier 2)** — new `--deep-interact` flag (implied by `--full`) runs an interaction pass before extraction: full-page scroll in 4 steps, menu/dropdown opens, hover snapshots for the first batch of buttons/links with computed-style diffs, accordion clicks, and first-match modal trigger. Results populate `design.interactionStates` (hover deltas, menu/modal snapshots). Every step is wrapped in try/catch with per-step timeouts so interaction failures never kill the crawl.
45
+ - **Multi-page token reconciliation (Tier 2)** — when `--depth >= 1` the extractor now emits three new artifacts alongside the merged baseline: `*-tokens-shared.json` (tokens shared across every route), `*-tokens-routes/<slug>.json` (per-route `added` and `changed` deltas), and `*-routes-report.md` (readable summary). Slugs are derived from the route path (`/` → `index`) with automatic collision handling.
46
+
47
+ ### Changed
48
+
49
+ - `--full` now also enables `--deep-interact`.
50
+ - `--depth <n>` description updated to mention the new reconciliation outputs.
51
+
3
52
  ## [7.1.0] — 2026-04-19
4
53
 
5
54
  ### Added
package/README.md CHANGED
@@ -311,6 +311,26 @@ A dedicated audit pass surfaced on `design.cssHealth`:
311
311
 
312
312
  Also contributes a `cssHealth` dimension to the overall design score.
313
313
 
314
+ ### 22. Chrome Extension (NEW in v7.1)
315
+
316
+ A Manifest-v3 popup lives in [`chrome-extension/`](chrome-extension/). One click on any tab opens `designlang.manavaryasingh.com` with the URL prefilled — no copy-paste, no context switch. There is also a **Copy CLI** button that puts `npx designlang <url>` in your clipboard.
317
+
318
+ - **Permissions:** `activeTab` only, plus host access to the hosted extractor.
319
+ - **Install:** toggle developer mode at `chrome://extensions`, click *Load unpacked*, pick the `chrome-extension/` folder.
320
+ - **Firefox + Edge** work with the same MV3 manifest.
321
+
322
+ ### 23. Better Auth + Network Control (NEW in v7.1)
323
+
324
+ Extracting from authenticated, self-signed, or non-default environments now takes one flag:
325
+
326
+ - **`--cookie-file <path>`** — loads cookies from JSON array, Playwright `storageState.json`, or Netscape `cookies.txt` (browser extensions, curl exports). Merges cleanly with the existing `--cookie name=value` flag.
327
+ - **`--insecure`** — ignore HTTPS/SSL certificate errors for self-signed dev servers, corporate staging, or MITM tools.
328
+ - **`--user-agent <ua>`** — override the browser User-Agent string.
329
+
330
+ ```bash
331
+ designlang https://staging.internal --cookie-file ./session.json --insecure
332
+ ```
333
+
314
334
  ## All Features
315
335
 
316
336
  | Feature | Flag / Command | Description |
@@ -325,12 +345,16 @@ Also contributes a `cssHealth` dimension to the overall design score.
325
345
  | Font files | automatic | Source detection (Google/self-hosted/CDN/system), @font-face CSS |
326
346
  | Image styles | automatic | Aspect ratios, shapes, filters, pattern classification |
327
347
  | Dark mode | `--dark` | Extracts dark color scheme + light/dark diff |
328
- | Auth pages | `--cookie`, `--header` | Extract from authenticated/protected pages |
329
- | Multi-page | `--depth <n>` | Crawl N internal pages for site-wide tokens |
348
+ | Auth pages | `--cookie`, `--cookie-file`, `--header` | Extract from authenticated/protected pages; cookie files in JSON / Playwright storageState / Netscape formats |
349
+ | Self-signed / dev TLS | `--insecure` | Ignore HTTPS/SSL certificate errors |
350
+ | User-Agent override | `--user-agent <ua>` | Set a custom User-Agent string |
351
+ | Chrome extension | `chrome-extension/` | One-click handoff from any tab, MV3, `activeTab` only |
352
+ | Multi-page | `--depth <n>` | Crawl N internal pages; emits shared-vs-per-route token reconciliation (`*-tokens-shared.json`, `*-tokens-routes/<slug>.json`, `*-routes-report.md`) |
330
353
  | Screenshots | `--screenshots` | Capture buttons, cards, inputs, nav, hero, full page |
331
354
  | Responsive | `--responsive` | Crawl at 4 viewports, map breakpoint changes |
332
355
  | Interactions | `--interactions` | Capture hover/focus/active state transitions |
333
- | Everything | `--full` | Enable screenshots + responsive + interactions |
356
+ | Auto-interact | `--deep-interact` | Scroll, open menus/modals/accordions, hover CTAs before extraction |
357
+ | Everything | `--full` | Enable screenshots + responsive + interactions + deep-interact |
334
358
  | Apply | `designlang apply <url>` | Auto-detect framework and write tokens to your project |
335
359
  | Clone | `designlang clone <url>` | Generate a working Next.js starter with extracted design |
336
360
  | Score | `designlang score <url>` | Rate design quality with visual bar chart breakdown |
@@ -365,12 +389,16 @@ Options:
365
389
  --screenshots Capture component screenshots
366
390
  --responsive Capture at multiple breakpoints
367
391
  --interactions Capture hover/focus/active states
368
- --full Enable all captures
392
+ --deep-interact Auto-interact pass (scroll, menus, modals, accordions, hover CTAs)
393
+ --full Enable all captures (implies --deep-interact)
369
394
  --cookie <cookies...> Cookies for authenticated pages (name=value)
370
395
  --cookie-file <path> Load cookies from JSON / storageState / Netscape cookies.txt
371
396
  --header <headers...> Custom headers (name:value)
372
397
  --user-agent <ua> Override the browser User-Agent string
373
398
  --insecure Ignore HTTPS/SSL certificate errors (self-signed, dev, proxies)
399
+ --selector <css> Only extract from elements matching this CSS selector (e.g. ".pricing-card")
400
+ --system-chrome Use the system Chrome install instead of the bundled Chromium (skips 150MB download)
401
+ --json Print full extraction as JSON to stdout (for piping into other tools)
374
402
  --framework <type> Only generate specific theme (react, shadcn)
375
403
  --platforms <csv> Additional platforms: web,ios,android,flutter,wordpress,all (additive)
376
404
  --emit-agent-rules Emit Cursor / Claude Code / CLAUDE.md / agents.md rule files
@@ -443,6 +471,20 @@ Running `designlang https://vercel.com --full`:
443
471
  5. **Score** — Accessibility extractor calculates WCAG contrast ratios for all color pairs
444
472
  6. **Capture** — Optional: screenshots, responsive viewport crawling, interaction state recording
445
473
 
474
+ ## Install Everywhere
475
+
476
+ designlang ships surfaces beyond the CLI:
477
+
478
+ | Surface | Path | Description |
479
+ |---------|------|-------------|
480
+ | **CLI** | `npx designlang <url>` | Main entry point. |
481
+ | **VS Code extension** | [`vscode-extension/`](vscode-extension/) | "Extract design from URL" command + auto-inject into workspace. |
482
+ | **Raycast extension** | [`raycast-extension/`](raycast-extension/) | Extract, score, and "copy CLI command" from Raycast. |
483
+ | **Figma plugin** | [`figma-plugin/`](figma-plugin/) | Paste a URL inside Figma, get a full Variables collection. |
484
+ | **GitHub Action** | [`github-action/`](github-action/) | "Design regression guard" — diffs tokens on every PR and comments. |
485
+ | **Chrome extension** | [`chrome-extension/`](chrome-extension/) | One-click handoff from any tab (MV3, `activeTab` only). |
486
+ | **MCP server** | `npx designlang mcp` | Exposes the extracted design as MCP resources + tools for Cursor, Claude Code, Windsurf, etc. See [`docs/MCP-REGISTRY.md`](docs/MCP-REGISTRY.md). |
487
+
446
488
  ## Agent Skill
447
489
 
448
490
  Works with **Claude Code, Cursor, Codex, and 40+ AI coding agents** via the skills ecosystem:
@@ -21,6 +21,7 @@ import { formatFlutterDart } from '../src/formatters/flutter-dart.js';
21
21
  import { formatVueTheme } from '../src/formatters/vue-theme.js';
22
22
  import { formatSvelteTheme } from '../src/formatters/svelte-theme.js';
23
23
  import { formatAgentRules } from '../src/formatters/agent-rules.js';
24
+ import { reconcileRoutes, formatRoutesReport } from '../src/formatters/routes-reconciliation.js';
24
25
  import { loadConfig, mergeConfig } from '../src/config.js';
25
26
  import { diffDesigns, formatDiffMarkdown, formatDiffHtml } from '../src/diff.js';
26
27
  import { saveSnapshot, getHistory, formatHistoryMarkdown } from '../src/history.js';
@@ -47,7 +48,7 @@ const program = new Command();
47
48
  program
48
49
  .name('designlang')
49
50
  .description('Extract the complete design language from any website')
50
- .version('6.0.0');
51
+ .version('8.0.0');
51
52
 
52
53
  // ── Main command: extract ──────────────────────────────────────
53
54
  program
@@ -63,13 +64,16 @@ program
63
64
  .option('--framework <type>', 'generate framework theme (react, shadcn, vue, svelte)')
64
65
  .option('--responsive', 'capture design at multiple breakpoints')
65
66
  .option('--interactions', 'capture hover/focus/active states')
66
- .option('--full', 'enable all extra captures (screenshots, responsive, interactions)')
67
+ .option('--deep-interact', 'auto-interact pass: scroll, open menus/modals/accordions, hover CTAs (implies --interactions)')
68
+ .option('--full', 'enable all extra captures (screenshots, responsive, interactions, deep-interact)')
67
69
  .option('--cookie <cookies...>', 'cookies for authenticated pages (name=value)')
68
70
  .option('--cookie-file <path>', 'load cookies from JSON, Playwright storageState, or Netscape cookies.txt')
69
71
  .option('--header <headers...>', 'custom headers (name:value)')
70
72
  .option('--user-agent <ua>', 'override the browser User-Agent string')
71
73
  .option('--insecure', 'ignore HTTPS/SSL certificate errors (self-signed, dev, proxies)')
72
74
  .option('--ignore <selectors...>', 'CSS selectors to remove before extraction')
75
+ .option('--selector <css>', 'only extract design from elements matching this CSS selector (e.g. ".pricing-card")')
76
+ .option('--system-chrome', 'use the system Chrome install instead of the bundled Chromium (skips the 150MB Playwright download)')
73
77
  .option('--tokens-legacy', 'Emit pre-v7 flat token JSON (backward compat)')
74
78
  .option('--platforms <csv>', 'Additional platforms: web,ios,android,flutter,wordpress,all (web is always emitted)', 'web')
75
79
  .option('--emit-agent-rules', 'Emit Cursor/Claude Code/generic agent rules')
@@ -152,6 +156,9 @@ program
152
156
  headers: Object.keys(headers).length > 0 ? headers : undefined,
153
157
  insecure: merged.insecure || false,
154
158
  userAgent: merged.userAgent,
159
+ deepInteract: merged.deepInteract || merged.full,
160
+ selector: merged.selector,
161
+ channel: merged.systemChrome ? 'chrome' : undefined,
155
162
  });
156
163
 
157
164
  // Responsive capture
@@ -258,6 +265,25 @@ program
258
265
  }
259
266
  }
260
267
 
268
+ // Multi-route token reconciliation (Tier 2). Only when --depth >= 1 and
269
+ // the crawler actually returned per-route token data.
270
+ if (merged.depth >= 1 && Array.isArray(design.routes) && design.routes.length > 0) {
271
+ const reconciled = reconcileRoutes(design.routes);
272
+ const sharedPath = join(outDir, `${prefix}-tokens-shared.json`);
273
+ writeFileSync(sharedPath, JSON.stringify(reconciled.shared, null, 2), 'utf-8');
274
+ platformFiles.push({ path: sharedPath, label: 'Shared tokens (multi-route)' });
275
+ const routesDir = join(outDir, `${prefix}-tokens-routes`);
276
+ mkdirSync(routesDir, { recursive: true });
277
+ for (const [slug, entry] of Object.entries(reconciled.perRoute)) {
278
+ const rp = join(routesDir, `${slug}.json`);
279
+ writeFileSync(rp, JSON.stringify({ url: entry.url, path: entry.path, added: entry.added, changed: entry.changed }, null, 2), 'utf-8');
280
+ platformFiles.push({ path: rp, label: `Route tokens (${slug})` });
281
+ }
282
+ const reportPath = join(outDir, `${prefix}-routes-report.md`);
283
+ writeFileSync(reportPath, formatRoutesReport(reconciled), 'utf-8');
284
+ platformFiles.push({ path: reportPath, label: 'Routes report (markdown)' });
285
+ }
286
+
261
287
  // Agent rules (opt-in, also enabled by --full)
262
288
  if (merged.emitAgentRules || merged.full) {
263
289
  const agentFiles = formatAgentRules({ design, tokens: dtcgTokens, url });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "designlang",
3
- "version": "7.1.0",
3
+ "version": "8.0.0",
4
4
  "description": "Extract the complete design language from any website — colors, typography, spacing, shadows, and more. Outputs AI-optimized markdown, W3C design tokens, Tailwind config, and CSS variables.",
5
5
  "type": "module",
6
6
  "bin": {
package/src/config.js CHANGED
@@ -27,7 +27,8 @@ export function mergeConfig(cliOpts, config) {
27
27
  screenshots: cliOpts.screenshots || config.screenshots || false,
28
28
  framework: cliOpts.framework || config.framework,
29
29
  responsive: cliOpts.responsive || config.responsive || false,
30
- interactions: cliOpts.interactions || config.interactions || false,
30
+ interactions: cliOpts.interactions || cliOpts.deepInteract || config.interactions || false,
31
+ deepInteract: cliOpts.deepInteract || config.deepInteract || false,
31
32
  full: cliOpts.full || config.full || false,
32
33
  cookie: cliOpts.cookie || config.cookies,
33
34
  header: cliOpts.header || config.headers,
@@ -38,6 +39,8 @@ export function mergeConfig(cliOpts, config) {
38
39
  cookieFile: cliOpts.cookieFile || config.cookieFile,
39
40
  insecure: cliOpts.insecure || config.insecure || false,
40
41
  userAgent: cliOpts.userAgent || config.userAgent,
42
+ selector: cliOpts.selector || config.selector,
43
+ systemChrome: cliOpts.systemChrome || config.systemChrome || false,
41
44
  };
42
45
  }
43
46