designlang 12.4.0 → 12.7.1
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.
- package/.claude-plugin/marketplace.json +15 -7
- package/.claude-plugin/plugin.json +19 -8
- package/CHANGELOG.md +194 -0
- package/README.md +31 -4
- package/SUPPORT.md +22 -0
- package/bin/design-extract.js +181 -0
- package/commands/battle.md +27 -0
- package/commands/brand.md +59 -0
- package/commands/extract.md +41 -0
- package/commands/grade.md +29 -0
- package/commands/pack.md +37 -0
- package/commands/remix.md +29 -0
- package/commands/theme-swap.md +42 -0
- package/package.json +3 -3
- package/src/ci.js +36 -2
- package/src/formatters/brand-book.js +1052 -0
- package/src/formatters/theme-swap.js +272 -0
- package/src/recolor.js +199 -0
- package/src/utils/color-gamut.js +64 -0
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
|
-
"name": "
|
|
2
|
+
"name": "designlang",
|
|
3
3
|
"owner": {
|
|
4
4
|
"name": "Manavarya Singh",
|
|
5
5
|
"url": "https://github.com/Manavarya09"
|
|
6
6
|
},
|
|
7
7
|
"plugins": [
|
|
8
8
|
{
|
|
9
|
-
"name": "
|
|
9
|
+
"name": "designlang",
|
|
10
10
|
"source": "./",
|
|
11
|
-
"description": "
|
|
12
|
-
"version": "
|
|
11
|
+
"description": "Seven slash commands wrapping the designlang CLI: /extract (full design language \u2192 DTCG, Tailwind, Figma), /grade (shareable HTML report card + SVG badge), /battle (head-to-head graded comparison), /remix (restyle in 6 vocabularies \u2014 brutalist, swiss, art-deco, cyberpunk, soft-ui, editorial), /pack (one downloadable design-system bundle), /theme-swap (OKLCH-correct recolour around a new brand primary), /brand (full editorial brand-guidelines book \u2014 13 chapters, hand-off-ready).",
|
|
12
|
+
"version": "12.7.1",
|
|
13
13
|
"author": {
|
|
14
14
|
"name": "Manavarya Singh"
|
|
15
15
|
},
|
|
@@ -17,12 +17,20 @@
|
|
|
17
17
|
"tags": [
|
|
18
18
|
"design-system",
|
|
19
19
|
"design-tokens",
|
|
20
|
-
"
|
|
20
|
+
"dtcg",
|
|
21
21
|
"tailwind",
|
|
22
|
+
"shadcn",
|
|
23
|
+
"figma",
|
|
22
24
|
"typography",
|
|
23
25
|
"colors",
|
|
24
|
-
"
|
|
26
|
+
"motion",
|
|
27
|
+
"grade",
|
|
28
|
+
"battle",
|
|
29
|
+
"remix",
|
|
30
|
+
"pack",
|
|
31
|
+
"mcp",
|
|
32
|
+
"playwright"
|
|
25
33
|
]
|
|
26
34
|
}
|
|
27
35
|
]
|
|
28
|
-
}
|
|
36
|
+
}
|
|
@@ -1,24 +1,35 @@
|
|
|
1
1
|
{
|
|
2
|
-
"name": "
|
|
3
|
-
"description": "Extract
|
|
4
|
-
"version": "
|
|
2
|
+
"name": "designlang",
|
|
3
|
+
"description": "Extract any website's design language and ship it. Seven slash commands \u2014 /extract, /grade, /battle, /remix, /pack, /theme-swap, /brand \u2014 wrap the designlang CLI to pull DTCG tokens, Tailwind/shadcn/Figma vars, motion + voice, generate shareable graded report cards, head-to-head battle pages, six-vocabulary remixes, downloadable design-system bundles, OKLCH-correct theme recolouring, and full editorial brand-guidelines books.",
|
|
4
|
+
"version": "12.7.1",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Manavarya Singh",
|
|
7
7
|
"url": "https://github.com/Manavarya09"
|
|
8
8
|
},
|
|
9
|
-
"homepage": "https://
|
|
9
|
+
"homepage": "https://designlang.app",
|
|
10
10
|
"repository": "https://github.com/Manavarya09/design-extract",
|
|
11
11
|
"license": "MIT",
|
|
12
12
|
"keywords": [
|
|
13
13
|
"design-system",
|
|
14
14
|
"design-tokens",
|
|
15
15
|
"design-language",
|
|
16
|
-
"
|
|
16
|
+
"dtcg",
|
|
17
17
|
"tailwind",
|
|
18
|
+
"shadcn",
|
|
19
|
+
"figma-variables",
|
|
20
|
+
"css",
|
|
18
21
|
"playwright",
|
|
19
22
|
"extraction",
|
|
20
23
|
"colors",
|
|
21
|
-
"typography"
|
|
24
|
+
"typography",
|
|
25
|
+
"motion",
|
|
26
|
+
"grade",
|
|
27
|
+
"battle",
|
|
28
|
+
"remix",
|
|
29
|
+
"pack",
|
|
30
|
+
"claude-plugin",
|
|
31
|
+
"mcp"
|
|
22
32
|
],
|
|
23
|
-
"skills": "./skills/"
|
|
24
|
-
|
|
33
|
+
"skills": "./skills/",
|
|
34
|
+
"commands": "./commands/"
|
|
35
|
+
}
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,199 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [12.7.1] — 2026-05-09
|
|
4
|
+
|
|
5
|
+
**Brand book — visual polish pass.**
|
|
6
|
+
|
|
7
|
+
The v12.7.0 brand book had a real-data deficit: the cover used a generic
|
|
8
|
+
grade-coloured accent strip, every section opened with a philosophical
|
|
9
|
+
lede ("the felt pace of an interface", "form follows feeling"), and
|
|
10
|
+
components were a metadata table instead of a real mock. This pass
|
|
11
|
+
replaces all of that with the extracted values themselves.
|
|
12
|
+
|
|
13
|
+
Changes:
|
|
14
|
+
|
|
15
|
+
- **Cover** now leads with the brand's actual primary as a full-bleed
|
|
16
|
+
band (auto-detected, falls back through secondary/accent/most-used).
|
|
17
|
+
Asymmetric layout — band + label + hex above, host name in massive
|
|
18
|
+
serif below.
|
|
19
|
+
- **Lede paragraphs replaced with one-line data summaries.**
|
|
20
|
+
"1 primary · 1 secondary · 1 accent · 27 neutrals · 88 total" instead
|
|
21
|
+
of "Brand colours carry meaning. Neutrals carry structure."
|
|
22
|
+
- **Type specimen** now uses real headlines extracted from the site's
|
|
23
|
+
voice (`design.voice.sampleHeadings`). Falls back to a single neutral
|
|
24
|
+
pangram only when those are absent. The recycled aphorisms ("quiet
|
|
25
|
+
authority of restraint", "form follows feeling") are gone.
|
|
26
|
+
- **Colour chapter** — primary at full-width hero card, secondary +
|
|
27
|
+
accent at half-width below, neutrals as a flush horizontal strip,
|
|
28
|
+
full palette grid below. Hex labels render *inside* the swatch in
|
|
29
|
+
high-contrast text (auto black/white).
|
|
30
|
+
- **Components chapter** — renders an actual primary + secondary
|
|
31
|
+
button using the extracted brand colour and radius, plus a card
|
|
32
|
+
mockup using extracted surface + text colours. Metadata table moved
|
|
33
|
+
below the visual mock.
|
|
34
|
+
- **Accessibility chapter** — failing pairs render as actual stacked
|
|
35
|
+
colour blocks (foreground text on background with ratio inline),
|
|
36
|
+
not a pure table. Big score number on top.
|
|
37
|
+
- **Tokens chapter** — code blocks now have a header bar with the
|
|
38
|
+
language label and target filename.
|
|
39
|
+
- **"How to use"** trimmed from six rules of thumb to four punchy
|
|
40
|
+
ones, drops the "rule of thumb" framing.
|
|
41
|
+
- **Layout** — section padding moved into the wrap (no more gutter
|
|
42
|
+
around the hero band), TOC now sits on a tinted sub-paper background,
|
|
43
|
+
chapter headers are thinner with a bottom rule.
|
|
44
|
+
|
|
45
|
+
Same 13 chapters, same public API. No breaking changes.
|
|
46
|
+
|
|
47
|
+
378/378 tests pass (one assertion updated for the new lowercase
|
|
48
|
+
"Brand guidelines" cover label).
|
|
49
|
+
|
|
50
|
+
## [12.7.0] — 2026-05-09
|
|
51
|
+
|
|
52
|
+
**Brand book — full editorial design-guidelines document for any URL.**
|
|
53
|
+
|
|
54
|
+
\`designlang brand <url>\` produces a self-contained, print-ready HTML
|
|
55
|
+
"brand guidelines book" that documents every dimension of an extracted
|
|
56
|
+
design system. Cover, table of contents, 13 chapters: about, logo,
|
|
57
|
+
colour, typography, spacing, shape, iconography, motion, components,
|
|
58
|
+
voice, accessibility, tokens, how-to-use. Editorial layout, dark-mode
|
|
59
|
+
toggle, smooth-scroll TOC, drop-in code blocks per stack.
|
|
60
|
+
|
|
61
|
+
\`\`\`bash
|
|
62
|
+
npx designlang brand stripe.com
|
|
63
|
+
\`\`\`
|
|
64
|
+
|
|
65
|
+
\`\`\`
|
|
66
|
+
Brand book · 54 tokens · 3 fonts · grade B · https://stripe.com
|
|
67
|
+
✓ stripe-com.brand.html
|
|
68
|
+
✓ stripe-com.brand.md
|
|
69
|
+
✓ stripe-com.brand.json
|
|
70
|
+
\`\`\`
|
|
71
|
+
|
|
72
|
+
### Why this is different from \`pack\`, \`grade\`, and \`design-language.md\`
|
|
73
|
+
|
|
74
|
+
| Output | Audience | Format |
|
|
75
|
+
|---|---|---|
|
|
76
|
+
| \`pack\` (v12.4) | Devs picking up a design system | Directory of files (tokens, components, Storybook, starter) |
|
|
77
|
+
| \`grade\` (v12.1) | Audit / share | Single audit page with score + verdict |
|
|
78
|
+
| \`design-language.md\` | LLMs | AI-optimized markdown (data-dense) |
|
|
79
|
+
| **\`brand\` (v12.7)** | **Designers + handoff** | **Editorial brand-guidelines book — readable, print-ready, hand-off-ready** |
|
|
80
|
+
|
|
81
|
+
### Added
|
|
82
|
+
|
|
83
|
+
- New CLI command: \`designlang brand <url> [-o] [-n] [--format] [--open]\`.
|
|
84
|
+
- New formatter \`src/formatters/brand-book.js\` exporting \`formatBrandBook\`
|
|
85
|
+
(HTML book) and \`formatBrandBookMarkdown\` (terse markdown summary).
|
|
86
|
+
- 13 chapters with editorial typography (Instrument Serif display + Inter
|
|
87
|
+
body), generous whitespace, smooth-scroll anchors, dark-mode toggle,
|
|
88
|
+
print stylesheet with page breaks at chapter boundaries.
|
|
89
|
+
- Per-colour section: large swatch + HEX/RGB/HSL/usage grid for brand
|
|
90
|
+
colours, mini-grid for neutrals + full palette.
|
|
91
|
+
- Per-token section: drop-in code blocks for CSS variables, Tailwind
|
|
92
|
+
config, with cross-reference to \`pack\` for the full bundle.
|
|
93
|
+
- Closing "How to use" chapter with six rules of thumb (hierarchy of
|
|
94
|
+
brand colour, two-family discipline, snap-to-scale spacing, tight
|
|
95
|
+
radius set, motion as feedback, accessibility as hard constraint).
|
|
96
|
+
- 7 new tests covering chapter coverage, host/colour/font rendering,
|
|
97
|
+
XSS escaping, sparse-design fallback, and mixed-shape component
|
|
98
|
+
anatomy (the bug that broke the first integration — slots / variants
|
|
99
|
+
arrive as objects, strings, or arrays from the extractor).
|
|
100
|
+
|
|
101
|
+
### Plugin
|
|
102
|
+
|
|
103
|
+
\`/brand\` is the 7th slash command in the Claude Code plugin
|
|
104
|
+
(\`/extract\`, \`/grade\`, \`/battle\`, \`/remix\`, \`/pack\`, \`/theme-swap\`,
|
|
105
|
+
\`/brand\`). \`.claude-plugin/plugin.json\` and \`marketplace.json\`
|
|
106
|
+
bumped to 12.7.0.
|
|
107
|
+
|
|
108
|
+
## [12.6.0] — 2026-05-06
|
|
109
|
+
|
|
110
|
+
**Theme-swap — recolour any extracted design around your brand primary.**
|
|
111
|
+
|
|
112
|
+
\`designlang theme-swap <url> --primary <hex>\` takes the existing
|
|
113
|
+
extraction and rotates the brand palette around a new primary while
|
|
114
|
+
preserving everything else: type scale, spacing rhythm, neutrals, motion,
|
|
115
|
+
component anatomy. Closes
|
|
116
|
+
[#57](https://github.com/Manavarya09/design-extract/issues/57).
|
|
117
|
+
|
|
118
|
+
\`\`\`bash
|
|
119
|
+
npx designlang theme-swap stripe.com --primary "#ff4800"
|
|
120
|
+
\`\`\`
|
|
121
|
+
|
|
122
|
+
\`\`\`
|
|
123
|
+
#533afd → #ff4800 · 91 colours · https://stripe.com
|
|
124
|
+
Hue shift: 118.5° · neutrals preserved · type/spacing/motion untouched
|
|
125
|
+
|
|
126
|
+
✓ stripe-com-themeswap-ff4800.themeswap.html
|
|
127
|
+
✓ stripe-com-themeswap-ff4800.themeswap.md
|
|
128
|
+
✓ stripe-com-themeswap-ff4800.themeswap.json
|
|
129
|
+
✓ stripe-com-themeswap-ff4800.themeswap.tokens.json
|
|
130
|
+
\`\`\`
|
|
131
|
+
|
|
132
|
+
### Added
|
|
133
|
+
|
|
134
|
+
- New CLI command: \`designlang theme-swap <url> --primary <hex>\`
|
|
135
|
+
with \`--from\`, \`-o\`, \`-n\`, \`--format\`, \`--open\` flags.
|
|
136
|
+
- New module \`src/recolor.js\` exporting \`recolorDesign(design, opts)\`.
|
|
137
|
+
Operates in OKLCH so perceptual lightness stays constant — only hue
|
|
138
|
+
rotates. Auto-detects the source primary; pin it with \`--from\`.
|
|
139
|
+
Neutrals (chroma < 0.04 in OKLCH) are explicitly preserved so body
|
|
140
|
+
text, surfaces, and rule lines stay readable.
|
|
141
|
+
- New formatter \`src/formatters/theme-swap.js\` exporting
|
|
142
|
+
\`formatThemeSwap\` (HTML side-by-side preview) and
|
|
143
|
+
\`formatThemeSwapMarkdown\`.
|
|
144
|
+
- New OKLCH inverse helpers in \`src/utils/color-gamut.js\`:
|
|
145
|
+
\`srgbToOklab\`, \`srgbToOklch\`, \`hexToOklch\`, \`oklchToHex\` —
|
|
146
|
+
with chroma fallback for out-of-gamut colours.
|
|
147
|
+
- The recoloured design is fed through every existing emitter (DTCG,
|
|
148
|
+
Tailwind, shadcn, Figma vars, CSS vars), so the swap propagates
|
|
149
|
+
for free.
|
|
150
|
+
- 10 new tests covering primary-pinning, neutral preservation,
|
|
151
|
+
hue rotation, error paths, \`--from\` override, HTML/markdown shapes,
|
|
152
|
+
and XSS escaping.
|
|
153
|
+
|
|
154
|
+
### Why
|
|
155
|
+
|
|
156
|
+
People keep asking *"what would Stripe look like in our brand colors?"*.
|
|
157
|
+
\`theme-swap\` answers it in 30 seconds. Bridges \`remix\` (full-vocab
|
|
158
|
+
restyle) and \`apply\` (token write-through to a project).
|
|
159
|
+
|
|
160
|
+
## [12.5.0] — 2026-05-06
|
|
161
|
+
|
|
162
|
+
**Claude Code plugin — five slash commands wrapping the CLI.**
|
|
163
|
+
|
|
164
|
+
designlang is now a first-class Claude Code plugin. Drop it into any
|
|
165
|
+
session and every CLI verb becomes a slash command:
|
|
166
|
+
|
|
167
|
+
\`\`\`bash
|
|
168
|
+
/plugin install Manavarya09/design-extract
|
|
169
|
+
\`\`\`
|
|
170
|
+
|
|
171
|
+
| Command | What it does |
|
|
172
|
+
|---|---|
|
|
173
|
+
| \`/extract <url>\` | Full extraction → DTCG, Tailwind, Figma, motion, voice |
|
|
174
|
+
| \`/grade <url>\` | Shareable HTML Design Report Card (+ \`--badge\`) |
|
|
175
|
+
| \`/battle <urlA> <urlB>\` | Head-to-head graded battle card |
|
|
176
|
+
| \`/remix <url> --as <vocab>\` | Restyle in 6 vocabularies |
|
|
177
|
+
| \`/pack <url>\` | Bundle every output into one design-system directory |
|
|
178
|
+
|
|
179
|
+
### Added
|
|
180
|
+
|
|
181
|
+
- \`commands/extract.md\`, \`commands/grade.md\`, \`commands/battle.md\`,
|
|
182
|
+
\`commands/remix.md\`, \`commands/pack.md\` — five slash-command
|
|
183
|
+
manifests with \`description\` + \`argument-hint\` frontmatter and prompt
|
|
184
|
+
bodies that wrap the CLI and surface tight summaries.
|
|
185
|
+
- Refreshed \`.claude-plugin/plugin.json\` (was stale at v1.0.0) — name
|
|
186
|
+
bumped to \`designlang\`, description rewritten around all v12 surfaces,
|
|
187
|
+
added \`commands\` directory pointer + expanded keywords.
|
|
188
|
+
- Refreshed \`.claude-plugin/marketplace.json\` — same updates plus
|
|
189
|
+
marketplace tags.
|
|
190
|
+
- New README section "Claude Code plugin" documenting install + the
|
|
191
|
+
five slash commands. Existing skills-ecosystem section retained for
|
|
192
|
+
Cursor / Codex / 40+ other agents.
|
|
193
|
+
|
|
194
|
+
No CLI behavior change. The slash commands are pure wrappers — they
|
|
195
|
+
shell out to \`npx designlang …\` and read the same output files.
|
|
196
|
+
|
|
3
197
|
## [12.4.0] — 2026-05-05
|
|
4
198
|
|
|
5
199
|
**Pack — one command, one polished design-system bundle.**
|
package/README.md
CHANGED
|
@@ -26,6 +26,8 @@ It also goes where extractors don't: **layout patterns**, **responsive behavior
|
|
|
26
26
|
|
|
27
27
|
```bash
|
|
28
28
|
npx designlang https://stripe.com # extract everything
|
|
29
|
+
npx designlang brand stripe.com # full brand-guidelines book (13 chapters) ← v12.7
|
|
30
|
+
npx designlang theme-swap stripe.com --primary "#ff4800" # recolour around your brand ← v12.6
|
|
29
31
|
npx designlang pack stripe.com # one polished design-system directory ← v12.4
|
|
30
32
|
npx designlang remix stripe.com --as cyberpunk # restyle in another vocabulary ← v12.3
|
|
31
33
|
npx designlang remix stripe.com --all # emit all 6 vocabs at once ← v12.3
|
|
@@ -131,7 +133,9 @@ designlang mcp # stdio MCP server for Cursor / Clau
|
|
|
131
133
|
| Battle (v12.2) | `designlang battle <A> <B>` | Head-to-head graded battle card with verdict, dimension table, palette comparison |
|
|
132
134
|
| Badge (v12.2) | `designlang grade --badge` | Shields.io-style SVG badge — `design · B · 87` — drop into any README. Live endpoint: `designlang.app/badge/<host>.svg` |
|
|
133
135
|
| Remix (v12.3) | `designlang remix <url> --as <vocab>` | Restyle the audited page in another vocabulary (brutalist / swiss / art-deco / cyberpunk / soft-ui / editorial). `--all` emits all 6 |
|
|
134
|
-
| Pack (
|
|
136
|
+
| Pack (v12.4) | `designlang pack <url>` | Bundle every output (tokens / components / Storybook / starter / prompts) into one polished design-system directory |
|
|
137
|
+
| Theme-swap (v12.6) | `designlang theme-swap <url> --primary <hex>` | Recolour the extracted design around a new brand primary. OKLCH hue rotation, neutrals preserved, type/spacing/motion untouched |
|
|
138
|
+
| Brand book (NEW v12.7) | `designlang brand <url>` | Full editorial brand-guidelines document (13 chapters: cover, about, logo, colour, type, spacing, shape, iconography, motion, components, voice, a11y, tokens, how-to-use). Print-ready, dark-mode toggle, hand-off-ready |
|
|
135
139
|
| Watch | `designlang watch <url>` | Monitor for design changes on interval |
|
|
136
140
|
| Diff | `designlang diff <A> <B>` | Compare two sites (MD + HTML) |
|
|
137
141
|
| Multi-brand | `designlang brands <urls...>` | N-site comparison matrix |
|
|
@@ -188,6 +192,8 @@ Commands:
|
|
|
188
192
|
battle <urlA> <urlB> Head-to-head graded battle card (--format html|md|json|all, --open)
|
|
189
193
|
remix <url> Restyle in another vocabulary (--as brutalist|swiss|art-deco|cyberpunk|soft-ui|editorial, --all, --list, --open)
|
|
190
194
|
pack <url> Bundle every output into one design-system directory (--with-clone, --open)
|
|
195
|
+
theme-swap <url> --primary <hex> Recolour around a new brand primary (--from, --format html|md|json|tokens|all, --open)
|
|
196
|
+
brand <url> Generate a full editorial brand-guidelines book (--format html|md|json|all, --open)
|
|
191
197
|
watch <url> Monitor for design changes on interval
|
|
192
198
|
diff <urlA> <urlB> Compare two sites' design languages
|
|
193
199
|
brands <urls...> Multi-brand comparison matrix
|
|
@@ -235,16 +241,37 @@ designlang ships surfaces beyond the CLI:
|
|
|
235
241
|
| **GitHub Action** | [`github-action/`](github-action/) | "Design regression guard" — diffs tokens on every PR and comments. |
|
|
236
242
|
| **Chrome extension** | [`chrome-extension/`](chrome-extension/) | One-click handoff from any tab (MV3, `activeTab` only). |
|
|
237
243
|
| **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). |
|
|
244
|
+
| **Claude Code plugin** | [`.claude-plugin/`](.claude-plugin/) | Five slash commands inside Claude Code — `/extract`, `/grade`, `/battle`, `/remix`, `/pack`. |
|
|
238
245
|
|
|
239
|
-
##
|
|
246
|
+
## Claude Code plugin
|
|
240
247
|
|
|
241
|
-
|
|
248
|
+
Drop designlang straight into Claude Code as a plugin. Every CLI command becomes a slash command:
|
|
249
|
+
|
|
250
|
+
```bash
|
|
251
|
+
/plugin install Manavarya09/design-extract
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
Then inside any Claude Code session:
|
|
255
|
+
|
|
256
|
+
| Slash command | What it does |
|
|
257
|
+
|---|---|
|
|
258
|
+
| `/extract <url>` | Full extraction → DTCG tokens, Tailwind, Figma vars, motion, voice |
|
|
259
|
+
| `/grade <url>` | Shareable HTML "Design Report Card" (+ `--badge` for an SVG) |
|
|
260
|
+
| `/battle <urlA> <urlB>` | Head-to-head graded battle card |
|
|
261
|
+
| `/remix <url> --as <vocab>` | Restyle in brutalist / swiss / art-deco / cyberpunk / soft-ui / editorial |
|
|
262
|
+
| `/pack <url>` | Bundle every output into one design-system directory |
|
|
263
|
+
|
|
264
|
+
Manifest: [`.claude-plugin/plugin.json`](.claude-plugin/plugin.json) · marketplace: [`.claude-plugin/marketplace.json`](.claude-plugin/marketplace.json) · commands: [`commands/`](commands/) · skills: [`skills/`](skills/).
|
|
265
|
+
|
|
266
|
+
## Agent skill (other ecosystems)
|
|
267
|
+
|
|
268
|
+
Works with **Cursor, Codex, and 40+ AI coding agents** via the skills ecosystem:
|
|
242
269
|
|
|
243
270
|
```bash
|
|
244
271
|
npx skills add Manavarya09/design-extract
|
|
245
272
|
```
|
|
246
273
|
|
|
247
|
-
In
|
|
274
|
+
In Cursor / Codex / etc., use `/extract-design <url>`.
|
|
248
275
|
|
|
249
276
|
## Website
|
|
250
277
|
|
package/SUPPORT.md
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Support
|
|
2
|
+
|
|
3
|
+
Need help with **designlang**?
|
|
4
|
+
|
|
5
|
+
- **Bugs** — open an [issue](https://github.com/Manavarya09/design-extract/issues/new/choose) with steps to reproduce and the URL you were extracting.
|
|
6
|
+
- **Feature requests** — see the [open roadmap](https://github.com/Manavarya09/design-extract/issues?q=is%3Aopen+label%3Aroadmap) (issues #56–#70). Feel free to claim one with a comment, or open a new one.
|
|
7
|
+
- **Security issues** — see [SECURITY.md](SECURITY.md). Please report privately.
|
|
8
|
+
- **Questions** — start a [Discussion](https://github.com/Manavarya09/design-extract/discussions) or DM [@manavaryasingh](https://github.com/Manavarya09).
|
|
9
|
+
|
|
10
|
+
## Surfaces
|
|
11
|
+
|
|
12
|
+
| Surface | Where to ask |
|
|
13
|
+
|---|---|
|
|
14
|
+
| CLI (`npx designlang`) | issue with the failing command + Node version |
|
|
15
|
+
| Claude Code plugin | issue tagged `claude-code` |
|
|
16
|
+
| MCP server (`designlang mcp`) | issue tagged `mcp` |
|
|
17
|
+
| Website (designlang.app) | issue tagged `website` |
|
|
18
|
+
| VS Code / Raycast / Figma / Chrome extensions | issue tagged with the surface name |
|
|
19
|
+
|
|
20
|
+
## Response time
|
|
21
|
+
|
|
22
|
+
Best effort within 5 business days. PRs welcome — see [CONTRIBUTING.md](CONTRIBUTING.md).
|
package/bin/design-extract.js
CHANGED
|
@@ -50,6 +50,9 @@ import { formatScoreBadge } from '../src/formatters/badge.js';
|
|
|
50
50
|
import { formatRemix } from '../src/formatters/remix.js';
|
|
51
51
|
import { VOCABULARIES, getVocabulary, listVocabularies } from '../src/vocabularies/index.js';
|
|
52
52
|
import { buildPack } from '../src/pack.js';
|
|
53
|
+
import { recolorDesign } from '../src/recolor.js';
|
|
54
|
+
import { formatThemeSwap, formatThemeSwapMarkdown } from '../src/formatters/theme-swap.js';
|
|
55
|
+
import { formatBrandBook, formatBrandBookMarkdown } from '../src/formatters/brand-book.js';
|
|
53
56
|
import { nameFromUrl } from '../src/utils.js';
|
|
54
57
|
|
|
55
58
|
function validateUrl(url) {
|
|
@@ -1225,6 +1228,184 @@ program
|
|
|
1225
1228
|
}
|
|
1226
1229
|
});
|
|
1227
1230
|
|
|
1231
|
+
// ── Theme-swap command — recolour an extracted design around a new primary
|
|
1232
|
+
program
|
|
1233
|
+
.command('theme-swap <url>')
|
|
1234
|
+
.description('Recolour the extracted design around a new brand primary (preserves type, spacing, neutrals)')
|
|
1235
|
+
.requiredOption('--primary <hex>', 'target primary colour as hex (e.g. "#ff4800")')
|
|
1236
|
+
.option('--from <hex>', 'override the auto-detected source primary (e.g. when the extractor misclassifies)')
|
|
1237
|
+
.option('-o, --out <dir>', 'output directory', './design-extract-output')
|
|
1238
|
+
.option('-n, --name <name>', 'output file prefix (default: derived from URL + target hex)')
|
|
1239
|
+
.option('--format <fmt>', 'output format: html, md, json, tokens, all', 'all')
|
|
1240
|
+
.option('--open', 'open the HTML preview in the default browser')
|
|
1241
|
+
.action(async (url, opts) => {
|
|
1242
|
+
if (!url.startsWith('http')) url = `https://${url}`;
|
|
1243
|
+
validateUrl(url);
|
|
1244
|
+
|
|
1245
|
+
const spinner = ora(`Extracting ${url}...`).start();
|
|
1246
|
+
try {
|
|
1247
|
+
const original = await extractDesignLanguage(url);
|
|
1248
|
+
spinner.text = `Recolouring around ${opts.primary}...`;
|
|
1249
|
+
const { design: recoloured, summary } = recolorDesign(original, {
|
|
1250
|
+
primary: opts.primary,
|
|
1251
|
+
fromPrimary: opts.from,
|
|
1252
|
+
});
|
|
1253
|
+
|
|
1254
|
+
const outDir = resolve(opts.out);
|
|
1255
|
+
mkdirSync(outDir, { recursive: true });
|
|
1256
|
+
const targetSlug = String(opts.primary).replace(/^#/, '').toLowerCase();
|
|
1257
|
+
const prefix = opts.name || `${nameFromUrl(url)}-themeswap-${targetSlug}`;
|
|
1258
|
+
const written = [];
|
|
1259
|
+
|
|
1260
|
+
if (opts.format === 'all' || opts.format === 'html') {
|
|
1261
|
+
const html = formatThemeSwap(original, recoloured, { version: PKG_VERSION });
|
|
1262
|
+
const p = join(outDir, `${prefix}.themeswap.html`);
|
|
1263
|
+
writeFileSync(p, html);
|
|
1264
|
+
written.push(p);
|
|
1265
|
+
}
|
|
1266
|
+
if (opts.format === 'all' || opts.format === 'md') {
|
|
1267
|
+
const md = formatThemeSwapMarkdown(original, recoloured);
|
|
1268
|
+
const p = join(outDir, `${prefix}.themeswap.md`);
|
|
1269
|
+
writeFileSync(p, md);
|
|
1270
|
+
written.push(p);
|
|
1271
|
+
}
|
|
1272
|
+
if (opts.format === 'all' || opts.format === 'json') {
|
|
1273
|
+
const p = join(outDir, `${prefix}.themeswap.json`);
|
|
1274
|
+
writeFileSync(p, JSON.stringify({
|
|
1275
|
+
url: original.meta?.url,
|
|
1276
|
+
from: summary.from,
|
|
1277
|
+
to: summary.to,
|
|
1278
|
+
hueShift: summary.hueShift,
|
|
1279
|
+
changedColors: summary.changes.length,
|
|
1280
|
+
changes: summary.changes,
|
|
1281
|
+
timestamp: new Date().toISOString(),
|
|
1282
|
+
}, null, 2));
|
|
1283
|
+
written.push(p);
|
|
1284
|
+
}
|
|
1285
|
+
if (opts.format === 'all' || opts.format === 'tokens') {
|
|
1286
|
+
const tokens = formatDtcgTokens(recoloured);
|
|
1287
|
+
const p = join(outDir, `${prefix}.themeswap.tokens.json`);
|
|
1288
|
+
writeFileSync(p, typeof tokens === 'string' ? tokens : JSON.stringify(tokens, null, 2));
|
|
1289
|
+
written.push(p);
|
|
1290
|
+
}
|
|
1291
|
+
|
|
1292
|
+
spinner.stop();
|
|
1293
|
+
console.log('');
|
|
1294
|
+
console.log(` ${chalk.bold(`${summary.from} → ${summary.to}`)} ${chalk.gray('·')} ${chalk.cyan(summary.changes.length)} colours ${chalk.gray('·')} ${chalk.gray(url)}`);
|
|
1295
|
+
console.log(` ${chalk.gray(`Hue shift: ${(summary.hueShift).toFixed(1)}° · neutrals preserved · type/spacing/motion untouched`)}`);
|
|
1296
|
+
console.log('');
|
|
1297
|
+
for (const f of written) console.log(` ${chalk.green('✓')} ${chalk.gray(f)}`);
|
|
1298
|
+
console.log('');
|
|
1299
|
+
|
|
1300
|
+
if (opts.open) {
|
|
1301
|
+
const htmlPath = written.find(p => p.endsWith('.html'));
|
|
1302
|
+
if (htmlPath) {
|
|
1303
|
+
const { spawn } = await import('child_process');
|
|
1304
|
+
const cmd = process.platform === 'darwin' ? 'open' : process.platform === 'win32' ? 'start' : 'xdg-open';
|
|
1305
|
+
spawn(cmd, [htmlPath], { detached: true, stdio: 'ignore' }).unref();
|
|
1306
|
+
}
|
|
1307
|
+
}
|
|
1308
|
+
} catch (err) {
|
|
1309
|
+
spinner.fail('Theme-swap failed');
|
|
1310
|
+
console.error(chalk.red(`\n ${err.message}\n`));
|
|
1311
|
+
process.exit(1);
|
|
1312
|
+
}
|
|
1313
|
+
});
|
|
1314
|
+
|
|
1315
|
+
// ── Brand command — full editorial brand-guidelines book ────
|
|
1316
|
+
program
|
|
1317
|
+
.command('brand <url>')
|
|
1318
|
+
.description('Generate a full brand-guidelines book — colour, type, spacing, motion, voice, components, accessibility, tokens, and how-to-use guidance')
|
|
1319
|
+
.option('-o, --out <dir>', 'output directory', './design-extract-output')
|
|
1320
|
+
.option('-n, --name <name>', 'output file prefix (default: derived from URL)')
|
|
1321
|
+
.option('--format <fmt>', 'output format: html, md, json, all', 'all')
|
|
1322
|
+
.option('--open', 'open the HTML book in the default browser')
|
|
1323
|
+
.action(async (url, opts) => {
|
|
1324
|
+
if (!url.startsWith('http')) url = `https://${url}`;
|
|
1325
|
+
validateUrl(url);
|
|
1326
|
+
|
|
1327
|
+
const spinner = ora(`Building brand guidelines for ${url}...`).start();
|
|
1328
|
+
try {
|
|
1329
|
+
// The brand book leans on the full extraction (logo, motion, voice,
|
|
1330
|
+
// anatomy, accessibility), so default to --full unless the caller has
|
|
1331
|
+
// explicitly opted out via env.
|
|
1332
|
+
const design = await extractDesignLanguage(url, {
|
|
1333
|
+
screenshots: true,
|
|
1334
|
+
responsive: false,
|
|
1335
|
+
interactions: false,
|
|
1336
|
+
deepInteract: true,
|
|
1337
|
+
});
|
|
1338
|
+
|
|
1339
|
+
const outDir = resolve(opts.out);
|
|
1340
|
+
mkdirSync(outDir, { recursive: true });
|
|
1341
|
+
const prefix = opts.name || `${nameFromUrl(url)}.brand`;
|
|
1342
|
+
const written = [];
|
|
1343
|
+
|
|
1344
|
+
if (opts.format === 'all' || opts.format === 'html') {
|
|
1345
|
+
const html = formatBrandBook(design, { version: PKG_VERSION });
|
|
1346
|
+
const p = join(outDir, `${prefix}.html`);
|
|
1347
|
+
writeFileSync(p, html);
|
|
1348
|
+
written.push(p);
|
|
1349
|
+
}
|
|
1350
|
+
if (opts.format === 'all' || opts.format === 'md') {
|
|
1351
|
+
const md = formatBrandBookMarkdown(design);
|
|
1352
|
+
const p = join(outDir, `${prefix}.md`);
|
|
1353
|
+
writeFileSync(p, md);
|
|
1354
|
+
written.push(p);
|
|
1355
|
+
}
|
|
1356
|
+
if (opts.format === 'all' || opts.format === 'json') {
|
|
1357
|
+
// A trimmed JSON of the most-used surfaces in the book — useful for
|
|
1358
|
+
// programmatic consumption without re-running extraction.
|
|
1359
|
+
const p = join(outDir, `${prefix}.json`);
|
|
1360
|
+
writeFileSync(p, JSON.stringify({
|
|
1361
|
+
url: design.meta?.url,
|
|
1362
|
+
title: design.meta?.title,
|
|
1363
|
+
timestamp: design.meta?.timestamp,
|
|
1364
|
+
intent: design.pageIntent,
|
|
1365
|
+
material: design.materialLanguage,
|
|
1366
|
+
imagery: design.imageryStyle,
|
|
1367
|
+
library: design.componentLibrary,
|
|
1368
|
+
stack: design.stack,
|
|
1369
|
+
voice: design.voice,
|
|
1370
|
+
colors: design.colors,
|
|
1371
|
+
typography: design.typography,
|
|
1372
|
+
spacing: design.spacing,
|
|
1373
|
+
shadows: design.shadows,
|
|
1374
|
+
borders: design.borders,
|
|
1375
|
+
motion: design.motion,
|
|
1376
|
+
accessibility: design.accessibility,
|
|
1377
|
+
score: design.score,
|
|
1378
|
+
}, null, 2));
|
|
1379
|
+
written.push(p);
|
|
1380
|
+
}
|
|
1381
|
+
|
|
1382
|
+
spinner.stop();
|
|
1383
|
+
const colorCount = (design.colors?.all || []).length;
|
|
1384
|
+
const fontCount = (design.typography?.families || []).length;
|
|
1385
|
+
const grade = design.score?.grade || '—';
|
|
1386
|
+
console.log('');
|
|
1387
|
+
console.log(` ${chalk.bold('Brand book')} ${chalk.gray('·')} ${chalk.cyan(colorCount + ' tokens')} ${chalk.gray('·')} ${chalk.cyan(fontCount + ' fonts')} ${chalk.gray('·')} ${chalk.cyan('grade ' + grade)} ${chalk.gray('·')} ${chalk.gray(url)}`);
|
|
1388
|
+
console.log('');
|
|
1389
|
+
for (const f of written) console.log(` ${chalk.green('✓')} ${chalk.gray(f)}`);
|
|
1390
|
+
console.log('');
|
|
1391
|
+
console.log(chalk.gray(` Open the .html — it's a self-contained, print-ready guidelines book.`));
|
|
1392
|
+
console.log('');
|
|
1393
|
+
|
|
1394
|
+
if (opts.open) {
|
|
1395
|
+
const htmlPath = written.find(p => p.endsWith('.html'));
|
|
1396
|
+
if (htmlPath) {
|
|
1397
|
+
const { spawn } = await import('child_process');
|
|
1398
|
+
const cmd = process.platform === 'darwin' ? 'open' : process.platform === 'win32' ? 'start' : 'xdg-open';
|
|
1399
|
+
spawn(cmd, [htmlPath], { detached: true, stdio: 'ignore' }).unref();
|
|
1400
|
+
}
|
|
1401
|
+
}
|
|
1402
|
+
} catch (err) {
|
|
1403
|
+
spinner.fail('Brand book failed');
|
|
1404
|
+
console.error(chalk.red(`\n ${err.message}\n`));
|
|
1405
|
+
process.exit(1);
|
|
1406
|
+
}
|
|
1407
|
+
});
|
|
1408
|
+
|
|
1228
1409
|
// ── Apply command ──────────────────────────────────────────
|
|
1229
1410
|
program
|
|
1230
1411
|
.command('apply <url>')
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Head-to-head graded battle card between two sites — eight dimensions, bar-by-bar, verdict line.
|
|
3
|
+
argument-hint: <urlA> <urlB>
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Pit two sites against each other and emit a single shareable HTML battle card.
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
npx designlang battle $ARGUMENTS
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
If `$ARGUMENTS` is empty or contains fewer than two URLs, ask the user for both sites.
|
|
13
|
+
|
|
14
|
+
Both sites are extracted in parallel (~30s total). Outputs land in `./design-extract-output/`:
|
|
15
|
+
|
|
16
|
+
- `<a>-vs-<b>.battle.html` — the shareable card
|
|
17
|
+
- `<a>-vs-<b>.battle.md` — markdown summary
|
|
18
|
+
- `<a>-vs-<b>.battle.json` — structured scores
|
|
19
|
+
|
|
20
|
+
After the run:
|
|
21
|
+
|
|
22
|
+
1. Read the `*.battle.md` file
|
|
23
|
+
2. Show the user the verdict line ("X wins" / "tie") and the per-dimension table
|
|
24
|
+
3. Highlight the dimensions where the gap is widest
|
|
25
|
+
4. Offer to open the HTML card
|
|
26
|
+
|
|
27
|
+
This is pure viral content — battles are designed to be tweeted. Pair with `/grade <url> --badge` so each side has a permanent badge to link back to.
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Generate a full editorial brand-guidelines book for any URL. 13 chapters covering colour, typography, spacing, shape, iconography, motion, components, voice, accessibility, tokens, and how-to-use guidance. Print-ready, dark-mode toggle, hand-off-ready single HTML.
|
|
3
|
+
argument-hint: <url> [--open]
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Build a self-contained, hand-off-ready brand-guidelines book from any live URL.
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
npx designlang brand $ARGUMENTS
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
If no URL is provided, ask the user which site to document.
|
|
13
|
+
|
|
14
|
+
Output goes to `./design-extract-output/`:
|
|
15
|
+
|
|
16
|
+
- `*.brand.html` — the editorial book (open this — it's a self-contained, print-ready document with TOC, smooth-scroll, dark-mode toggle)
|
|
17
|
+
- `*.brand.md` — terse markdown summary (good for diffing snapshots)
|
|
18
|
+
- `*.brand.json` — structured slice of the design with the surfaces the book renders
|
|
19
|
+
|
|
20
|
+
After the run completes:
|
|
21
|
+
|
|
22
|
+
1. Read `*.brand.md` to summarise what was captured (host, page intent, material language, tone, palette size, type families, WCAG score)
|
|
23
|
+
2. Tell the user the headline numbers (`X tokens · Y fonts · grade Z`)
|
|
24
|
+
3. Offer to open the HTML book (`--open` does this automatically)
|
|
25
|
+
4. Suggest pairing: `/pack <url>` if they want a developer-facing bundle to drop into a project, `/grade <url>` for the audit, `/theme-swap <url>` to derive a recoloured variant
|
|
26
|
+
|
|
27
|
+
## What's in the book
|
|
28
|
+
|
|
29
|
+
| § | Chapter | What it documents |
|
|
30
|
+
|---|---|---|
|
|
31
|
+
| 01 | About | Page intent, material language, imagery style, component library, stack, voice tone |
|
|
32
|
+
| 02 | Logo | Extracted SVG logo + clearspace + dimensions |
|
|
33
|
+
| 03 | Colour | Brand colours with HEX/RGB/HSL/usage, neutrals grid, full palette, A11y callout |
|
|
34
|
+
| 04 | Typography | Display + body families, weights, scale table, large specimen |
|
|
35
|
+
| 05 | Spacing | Base unit, scale length, visual rhythm bars |
|
|
36
|
+
| 06 | Shape | Border radii visualised, shadow elevation system |
|
|
37
|
+
| 07 | Iconography | Icon library detection + captured icons grid |
|
|
38
|
+
| 08 | Motion | Feel, durations (animated dots), easings, spring presence, scroll-linked flag |
|
|
39
|
+
| 09 | Components | Detected components with slots/variants/sizes |
|
|
40
|
+
| 10 | Voice & tone | Tone, pronoun posture, heading case, top CTA verbs, sample headings |
|
|
41
|
+
| 11 | Accessibility | WCAG score, failing pairs table, suggested replacements |
|
|
42
|
+
| 12 | Tokens | Drop-in code blocks (CSS vars, Tailwind config) + cross-ref to `pack` |
|
|
43
|
+
| 13 | How to use | Six rules of thumb for derivative work |
|
|
44
|
+
|
|
45
|
+
## Useful flags
|
|
46
|
+
|
|
47
|
+
| Flag | Effect |
|
|
48
|
+
|---|---|
|
|
49
|
+
| `--format html\|md\|json\|all` | Pick the output(s). Default `all`. |
|
|
50
|
+
| `--out <dir>` | Output directory. Default `./design-extract-output`. |
|
|
51
|
+
| `-n, --name <name>` | Output file prefix. Default derived from URL. |
|
|
52
|
+
| `--open` | Open the HTML book in your default browser. |
|
|
53
|
+
|
|
54
|
+
## Pairs nicely with
|
|
55
|
+
|
|
56
|
+
- `/pack <url>` — when the recipient wants files to drop into a project, not a guidelines doc
|
|
57
|
+
- `/grade <url>` — when the recipient wants the audit/score, not the full book
|
|
58
|
+
- `/theme-swap <url> --primary <hex>` — when the recipient wants the same system in their brand colour
|
|
59
|
+
- `/remix <url> --as <vocab>` — when the recipient wants a vocabulary swap (brutalist, swiss, etc.)
|