README quick-start, a dedicated 'Measured clone fidelity' section, the plugin
command table, and the full CLI reference now cover /fidelity and /gallery.
CHANGELOG 12.24.0 entry. Version bumped in lockstep across package.json,
plugin.json, marketplace.json (manifests describe the two new commands); the
version-sync test now guards fidelity + gallery too.
Bump all manifests to 12.23.0 (in sync) and document the new 'site'
command, OKLab clustering, coverage map, consistency grade, and the
plugin command/version fixes.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
scripts/check-plugin-version.mjs fails loud when plugin.json or
marketplace.json drift from package.json; wired as 'npm run check-plugin'
and enforced by tests/plugin-version.test.js (also asserts every new
command has a backing file and is described). Prevents the drift recurring.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The preview felt random. This rebuilds it as a deliberate design-system
specimen instead of a scatter of placeholder components.
- Composed preview: masthead, a centered hero using the site's own strongest
heading + top CTA verbs, labeled Color and Type foundations, then Buttons /
Inputs / Status / In-context cards / Metrics — each under a clear section
eyebrow, on a consistent vertical rhythm. The rebuilt-Page tab reuses the
same crafted components. Honest product copy, no lorem.
- Harmonised deriveTokens: guarantee a legible surface/text pair, filter greys
out of accent selection (no neutral promoted to brand), deepen a near-
invisible accent to read on the surface, hold secondary text above a
legibility floor. Keep white-on-warm-accent convention for accent foreground.
- Calmer chrome: quieter hairlines, consistent 30px rounded controls, pill
tabs, segmented light/dark — the frame recedes so the system is the focus.
Shared studio engine, so the CLI and website /studio get it identically.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add a Light/Dark toggle that generates a dark variant from the extracted
light tokens: surface → near-black tinted toward the brand hue, text →
near-white, muted/border/card recomputed; the brand accent is preserved
(lightened only if it would vanish on dark). Type/shape/spacing/motion carry
over. Contrast grading recomputes live, inspector edits layer on top of
either theme, and the theme is encoded in the shareable URL.
Pure shared deriveDark() in src/studio-tokens.js keeps the CLI and website
studios in lock-step. New unit tests cover the dark derivation and control.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Turn `designlang studio` from a read-only viewer into an interactive
playground, and ship the same experience on the website.
CLI (`designlang studio`):
- Inspector (color/type/shape/spacing/motion) writes a small `--p-*` CSS
variable set; a tabbed live preview — component wall + a page rebuilt from
the extraction's reading order — restyles instantly off those variables.
- Live WCAG contrast grading per color, paper/white/dark backdrops, an edit
counter, and smooth token-driven transitions.
- Export edited system as DTCG tokens / CSS variables / Tailwind theme
(zero-dep client downloads); share via URL (edits encoded as hash deltas).
Website (`/studio`):
- Paste any URL → extract → embed the identical editable studio in a framed
viewport. Shareable via `?url=`; shares the free 2/day demo budget.
- New POST /api/studio reuses the same `studioHtml` engine server-side.
Internals:
- Token derivation extracted to a pure, dep-free module (src/studio-tokens.js)
shared by the CLI and the website route, keeping both surfaces in lock-step.
- New unit tests: derivation, WCAG contrast math, rendered studio document.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
`designlang verify <url>` closes the extract→prove loop. For each detected
component (button+card in v1) it rebuilds a clone styled ONLY by the extracted
tokens (each visual property snapped to nearest token, colours in CIE-Lab ΔE),
renders it, and pixel-diffs against the live component → 0-100 fidelity score +
per-token-family attribution + a verify.html triptych (original | rebuilt |
loss heatmap) + verify.json. `--min` gates CI.
Honest by construction: missing component → n/a (excluded, no silent 100);
property with no token → unmapped (counted as loss, surfaced in attribution);
size mismatch letterboxed, never stretched.
New isolated modules under src/verify/ (tokens/restyle/render/diff/index) +
formatters/verify.js + verify CLI command. Adds pixelmatch+pngjs. 13 unit tests,
full suite green (438). Live smoke vs github.com: button 89/100.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Two new framework targets for the extracted motion language:
- motion-gsap.js: registers extracted cubic-bezier curves as named GSAP
CustomEases, emits gsap.from() reveal helpers + a ScrollTrigger batch
reveal when the page uses scroll/view-timeline.
- motion-waapi.js: zero-dependency Web Animations API preset. WAAPI takes
cubic-bezier easing strings verbatim, so curves reproduce exactly (no
spring approximation); helpers honour prefers-reduced-motion.
Wired into the CLI emit list (`<host>-motion.gsap.js`, `-motion.waapi.js`),
the /api/motion exports, and the motionlang analyzer export cards. Adds 8
emitter tests (425 -> all green). Also ignores .npmrc.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
motionlang:
- New formatter src/formatters/motion-css.js — <host>-motion.css with
--duration-*/--ease-* custom properties, reusable + reconstructed
@keyframes, .mo-* utility classes, and a prefers-reduced-motion guard.
- New formatter src/formatters/motion-tailwind.js — <host>-motion.tailwind.js
require-able theme.extend (transitionDuration, transitionTimingFunction
incl. a spring curve from detected overshoot beziers, keyframes, animation).
- Wired both through api.js (RENDERERS + ext map) and the bin files array as
the motion-css and motion-tailwind renderer ids.
- 13 new tests; full suite 414 pass.
website PDF fix ("downloaded PDF won't open"):
- extract route awaits the Blob cache write before the stream closes, so the
serverless instance can't freeze mid-write and leave /api/pdf/<hash> with
no cached design (was a fire-and-forget write returning 404 JSON).
- ShareExtractionButton fetches + validates content-type is application/pdf
before saving, surfacing an error instead of writing a broken file.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds a stable surface other packages, scripts and AI agents can
import without touching internal modules.
New file: src/api.js
- extract(url, opts) — run the full extraction pipeline, returns design
- render(id, design) — render a single emitter by id
- renderAll(design) — return a { filename: contents } map
- RENDERERS — frozen map of every emitter id → renderer fn
- Re-exports: extractDesignLanguage, compressPalette, diffDesigns,
formatDiffMarkdown
19 renderer ids exposed (every web/native/agent emitter).
package.json gains an exports map:
'designlang' — index.js
'designlang/api' — the new public API
'designlang/mcp' — the existing MCP server entry
Usage:
import { extract, render } from 'designlang/api';
const design = await extract('https://stripe.com', { palette: 8 });
const tailwind = render('tailwind-v4', design);
Bumps the package to v12.12.0 alongside the full website rewrite.
The CLI itself is unchanged from v12.11.0 — this version is published
mainly so the (previously broken) README image URLs propagate to the
npm package page.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds native PDF brand-guide output to the brand command:
--pdf, --paper a4|letter|tabloid, --landscape,
--no-print-background, --attach-tokens
PDF features: per-chapter page breaks, running footer with page
numbers, selectable text, embedded fonts, optional DTCG-tokens
JSON attached as a file inside the PDF (paperclip in Acrobat).
One new dep: pdf-lib (lazy-imported, only used when --attach-tokens
is passed).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
$ npx designlang stats stripe.com vercel.com linear.app
Each URL is extracted in parallel; the pretty path prints each block
with a divider between them, the --as-json path emits an array.
Backwards compatible: a single URL still emits a bare object in
JSON mode, identical pretty output, and uses the exact same flag
surface. Per-URL failures use Promise.allSettled — one bad URL
doesn't kill the batch; the process exits non-zero only when at
least one site failed.
398/398 tests still pass.
Two tight quality-of-life additions on top of the v12.9 extraction pass.
stats command
$ npx designlang stats stripe.com
Grade B · 87/100
Primary #533afd ×899 59% conf
Fonts sohne-var
Type scale 14 sizes
Spacing base 2px · 13 steps
Shape 5 radii · 6 shadows
Colours 31 tokens
WCAG 79%
Stack next · unknown
Material skeuomorphic
Tone neutral
Intent landing
One-screen summary, no files written. Use -j / --as-json for
machine-readable output (CI, scripting).
(--json is already a global program flag for the main extract
command's raw-JSON-to-stdout mode, so the subcommand flag is
--as-json to avoid the clash. Both --as-json and -j shortcuts work.)
Low-confidence note in grade.html
v12.9 added primary.confidence (0-1) on the colours payload but no
surface used it. v12.10 renders an amber callout above the
dimensions grid in the grade report card when confidence < 0.5:
"Primary detection was low-confidence (32%). The brand colour
may be a soft pick — review the palette below."
Soft inline note, not an error. Stays hidden on the common high-
confidence path. Dark-mode aware.
Tests
- 2 new tests cover the present + absent paths of the confidence
note.
- 398/398 total.
No breaking changes, no new dependencies.
Eight features rode on top of the same extractor. This release fixes
four real defects in that extractor — visible across every downstream
output (grade, battle, remix, pack, theme-swap, brand, pair).
Fixed
1. clusterColors() representative bug. Before, the first-encountered
colour seeded each cluster, so a sparsely-used pale shade could
become the canonical hex of a cluster that mostly held a vivid
brand colour. The brand-book primary slot was reading lavender
for Stripe instead of #533afd. Now: representative is the
most-counted member.
2. detectScale() missed common production base units. Before, only
[2, 4, 6, 8] were tried, so Bootstrap-style base-5 and base-7/10/12
sites returned base:null. Now: [2, 4, 5, 6, 7, 8, 10, 12, 16] with
a small bonus for 4 and 8 to keep results stable for production
defaults.
3. Typography noise. Generic CSS stacks (sans-serif, monospace,
system-ui, inherit, -apple-system, ...) and icon fonts (Material
Icons, Font Awesome, Lucide, Tabler, ...) polluted the families
list. Brand books had icon fonts documented as the body family.
Now: an explicit filter at the source.
Added
4. primary.confidence (0–1) on design.colors.primary. Computed from
the brand-score gap between rank 1 and rank 2. Runaway leader →
1.0; near-tie → 0.3. Downstream consumers can surface uncertainty
warnings on low-confidence extractions.
5. asList(v) helper exported from src/utils.js. Coerces anything-
shaped input (array / object / comma-string / scalar) into a clean
string array. Consolidates ad-hoc per-formatter defenses.
Verified live on stripe.com
Before: primary slot showed a washed-out lavender; multiple icon
fonts polluted families; spacing base often null.
After: primary #533afd (count 899, confidence 0.59), families
['sohne-var'], spacing base correctly detected.
No new dependencies, no schema breaks, no public-API changes.
396/396 tests pass (6 new).
`designlang pair <urlA> <urlB>` extracts both sites in parallel, then
mixes their design systems along seven configurable axes (colours,
typography, spacing, shape, motion, voice, components). Default split
is "visuals from A, voice + type + components from B" — i.e. the most
distinctive crossover.
$ npx designlang pair stripe.com linear.app
stripe.com × linear.app
A Colours · stripe.com
B Typography · linear.app
A Spacing · stripe.com
A Shape · stripe.com
A Motion · stripe.com
B Voice · linear.app
B Components · linear.app
✓ stripe-com-x-linear-app.pair.html
✓ stripe-com-x-linear-app.pair.md
✓ stripe-com-x-linear-app.pair.json
How it works
- src/fuse.js — fuseDesigns(a, b, opts) deep-clones both inputs,
picks each axis from the requested source, synthesises a
pair-specific meta URL ("pair://<a>-x-<b>"), and strips score /
cssHealth (those measurements belong to the source extractions,
not the fusion).
- Default axes calibrated for the most interesting crossover:
colour/spacing/shape/motion from A, typography/voice/components
from B. Override any axis with --<axis>-from a|b.
- Layout follows colour (mixing primary from one site with neutrals
from another tends to muddy the brand). Material language and
imagery style track the colour pick. Variables follow colour.
- Components carry their detected library label (componentLibrary)
along with the anatomy.
Pair card formatter
- src/formatters/pair.js — editorial three-card hero (A · B · Fused),
per-axis source matrix, and a fused specimen using the *real*
headline from whichever site contributed the voice axis.
- --brand flag also emits a full brand-guidelines book of the fused
identity (re-uses formatBrandBook on the fused design).
Plugin
- /pair is the 8th slash command (commands/pair.md).
- .claude-plugin/plugin.json + marketplace.json bumped to 12.8.0
with an eight-command description.
Tests (12 new, 390/390 total)
- Default split, per-axis overrides, score-stripping, meta synthesis
- Source-design immutability, missing-input errors
- HTML rendering, voice carry-through to specimen, XSS escaping
- Markdown axis source table
Verified live: Stripe × Linear fuses Stripe's purple palette with
Linear's Inter Variable typography and Linear's actual top heading
("The product development system for teams and agents") as the
specimen quote.
Why
battle (v12.2) answers "which is better"; pair answers "what would
the intersection look like". Same parallel extraction, opposite
operation. Pure logic, no LLM, no new dependencies.
The v12.7.0 brand book had a real-data deficit:
- Cover used a generic grade-coloured accent (not the brand's actual primary).
- Every section opened with a philosophical lede ("the felt pace of an
interface", "form follows feeling", "quiet authority of restraint").
- Components chapter was a metadata table, not a real mock.
- Type specimen reused the same recycled aphorisms across files.
This pass replaces all of that with the extracted values themselves.
Cover
Full-bleed band of the brand's actual primary (auto-detected via the
most-saturated brand-classified colour; falls back through secondary,
accent, most-used). The hex prints inside the band. Host name lives
below the band in massive serif.
Section ledes
Replaced philosophy with one-line data summaries.
"1 primary · 1 secondary · 1 accent · 27 neutrals · 88 total" beats
"Brand colours carry meaning. Neutrals carry structure."
Type specimen
Now uses real headlines extracted from design.voice.sampleHeadings.
Falls back to a single neutral pangram only when those are absent.
Recycled aphorisms removed entirely.
Colour chapter
Primary at full-width hero (aspect 2.6:1), secondary + accent
half-width pair, neutrals flush horizontal strip, full palette grid.
Hex labels render *inside* the swatch in auto-contrast text.
Components chapter
Renders an actual primary + secondary button using extracted brand
colour + radius, plus a card mock using extracted surface + text
+ accent for the link. Metadata moved below the mock.
Accessibility chapter
Failing pairs render as actual stacked colour blocks ("Aa" in
foreground on the failing background, ratio inline). Big WCAG score
on top.
Tokens chapter
Code blocks now have a header bar with language + target filename.
"How to use"
Trimmed from 6 rules of thumb to 4 punchier ones. Dropped the
"rule of thumb" framing.
Layout
Section padding moved into the wrap (no gutter around the hero
band). TOC sits on tinted sub-paper background. Chapter headers
thinner with a bottom rule.
Same 13 chapters, same public API, no breaking changes.
378/378 tests pass (one assertion updated for the lowercase
"Brand guidelines" cover label).
Drop designlang straight into any Claude Code session as a plugin:
/plugin install Manavarya09/design-extract
Every CLI verb becomes a slash command:
/extract <url> — full extraction (DTCG, Tailwind, Figma)
/grade <url> [--badge] — shareable HTML report card + SVG badge
/battle <urlA> <urlB> — head-to-head graded battle card
/remix <url> --as <vocab> — restyle in 6 vocabularies
/pack <url> — bundle every output into one directory
What changed:
- New commands/ directory with five slash-command manifests
(description + argument-hint frontmatter, prompt body wraps CLI and
surfaces a tight summary).
- Refreshed .claude-plugin/plugin.json (was stale at v1.0.0):
name → designlang, description rewritten to cover all v12 surfaces,
added "commands": "./commands/" pointer, expanded keywords.
- Refreshed .claude-plugin/marketplace.json with the same updates plus
marketplace tags.
- New README section "Claude Code plugin" with install + slash command
table. Existing "Agent skill" section retained for Cursor/Codex/40+
other agents via the skills ecosystem.
No CLI behavior change. The slash commands are pure wrappers around
existing `npx designlang …` calls.
357/357 tests pass.
Closes#59.
`designlang pack <url>` runs the full extraction once and writes every
emitter output into a single, signed, layered directory. One artifact a
designer or dev can clone, drop into a project, or zip up and send to a
client.
Layout:
<host>-design-system/
├── README.md bespoke, references source + grade + at-a-glance
├── LICENSE.txt provenance + usage guidance
├── tokens/ DTCG + Tailwind + CSS vars + Figma vars + motion + theme.js
├── components/ typed React stubs (anatomy.tsx)
├── storybook/ runnable Storybook project
├── starter/ minimal HTML starter wired to tokens/variables.css
├── prompts/ v0 / Lovable / Cursor / Claude Artifacts + named recipes/*.md
└── extras/ voice.json + prompt-pack.md rollup
Pure composition — zero new deps, zero new analysis. Reuses formatDtcg,
formatTokens, formatTailwind, formatCssVars, formatFigma, formatMotionTokens,
formatReactTheme, formatAnatomyStubs, formatStorybook, buildPromptPack,
generateClone (opt-in via --with-clone).
Internals:
- `toText()` normaliser handles the inconsistent return shapes across
formatters (some return objects, some return JSON strings already).
- Recipes now write as `<name>.md` files, not array indices.
- 7 new tests cover directory shape, valid JSON token outputs, README
content, starter wiring, recipe filenames, and a regression test for
the double-stringify bug.
357/357 tests pass.
Verified live on stripe.com: 40 files, 232KB, all token JSON parses
cleanly.
A genuinely new product surface. Take an extracted page-shape (sections,
voice, page-intent, anatomy) and re-render it under one of six opinionated
design vocabularies. Same content, different language.
$ designlang remix stripe.com --as cyberpunk
$ designlang remix stripe.com --all # all 6 vocabularies, one extract
Six vocabularies:
brutalist — hard edges, mono type, single screaming accent
swiss — Helvetica, grids, restraint (post-Bauhaus default)
art-deco — gold on ink, geometric ornament, vertical type
cyberpunk — neon on midnight, scanlines, chromatic-aberration headings
soft-ui — cushioned shapes, low contrast, Vision-OS-adjacent
editorial — broadsheet serifs, generous whitespace, ink on paper
Each vocabulary is a self-contained tokens + font-stack + signature CSS
file in src/vocabularies/. The formatter (src/formatters/remix.js) maps
every section role (hero, feature-grid, pricing-table, stats, testimonial,
faq, logo-wall, steps, cta) to vocabulary-styled markup, using the host's
own copy (headings, ledes, CTA verbs from voice).
Hero deduplication: real-world section walkers — especially on SPA
marketing pages — often emit a hero wrapper + an inner hero with the
same h1. Remix dedupes by heading and excludes section-claimed headings
from the voice pool, so heading-less sections (cta bands, logo walls)
don't re-render an already-claimed heading.
14 new tests (350 total, all passing). Cover registry shape, per-vocab
token validity, dedup semantics, no-cross-claim heading pool, XSS
escaping, missing-input errors.
Why: Grade (v12.1) is the audit. Battle (v12.2) is the comparison.
Remix is the transformation. No competitor (Dembrandt, Superposition,
html.to.design, Builder Visual Copilot) ships site-shape-preserving
vocabulary swap.
Website: bumps v12.2 → v12.3 across home/features/gallery/spec/permalink,
adds /features#remix section, swaps Battle CTA chip to Remix.
Two ships on top of the v12.1 Grade flywheel.
`designlang battle <urlA> <urlB>` — head-to-head graded card, parallel
extraction, dimension-by-dimension bar table with verdict + win/tie/loss
tally. Self-contained HTML, also emits .battle.md and .battle.json.
Design-score SVG badges:
- `designlang grade --badge` writes *-badge.svg locally
- New formatter src/formatters/badge.js — shields.io style, color by
letter grade, accessible (aria-label, role=img), Verdana-width math so
it renders identically across GitHub / npm / arbitrary markdown
- Live endpoint at website/app/api/badge/[host]/route.js — reuses the
same blob cache /api/extract writes to, edge-cached 6h with 24h SWR
for friendly behavior under GitHub's image proxy
- Friendly URL rewrites: /badge/<host> and /badge/<host>.svg → /api/badge/<host>
Why both: Grade is the artifact, Battle is the viral content layer
("Stripe vs Vercel — guess who lost"), Badge is the permanent
distribution layer (every README adoption is a backlink to a live
grade page).
13 new tests (336 total, all passing). Cover battle markup, score
comparison thresholds, SVG escaping, grade-color mapping, missing-score
handling.
Website: bumps v12.1 → v12.2 across home/gallery/spec/features/permalink,
adds /features#battle section, swaps Grade CTA chip to Battle.
Adds `designlang grade <url>` — a self-contained, editorial-style HTML
audit page (plus JSON + Markdown variants). Big serif letter grade,
eight scored dimensions with arc gauges, evidence pulled from the
audited site itself (palette swatches, type specimen, spacing rhythm),
and a strengths / what-to-fix ledger. Paper/ink theme with a dark
toggle, print-ready, OG meta for shareable links.
Why this exists: html.to.design, Locofy, Builder, Polypane all ship
extraction or layout cloning. None of them grade the design system
itself in a form you can post on Twitter or send to a client.
- src/formatters/grade.js — new formatHTML + formatMarkdown formatters
- bin/design-extract.js — `grade` subcommand with --format / --open
- 6 new tests covering shape, escaping, scale-shape regression
- README — trimmed 649 → 241 lines, restructured around outputs/moats
- website — adds /features#grade section, bumps v12 → v12.1 throughout
- clone v2: driven by sectionRoles + voice + materialLanguage. Emits a
working Next.js repo that mirrors the target's actual section order,
CTA verbs, and material treatment — not a generic palette demo.
- ci: one-shot PR-comment markdown (score + drift + optional visual-diff).
Works in any CI. Writes GITHUB_STEP_SUMMARY automatically. Exits
non-zero on configured drift threshold.
- studio: zero-dep local web studio over the latest extraction.
localhost:4837. Clickable swatches, voice/DNA/motion, /raw endpoint.
- website: new V11 showcase below hero ("Stop shipping tokens. Start
shipping the outcome."). v10 demoted to editorial supporting strip,
v9 rewritten to numbered rows — kill the uniform-card-grid slop.
- icon-system.js fingerprints the icon library from stroke/fill
dominance, stroke width, grid size, and rounded-caps presence.
Recognises Lucide, Heroicons (outline+solid), Phosphor, Tabler,
Feather, Remix, Material.
- background-patterns.js classifies noise/dot-grid/line-grid/
gradient-mesh/svg-pattern/plain from background-image values.
- stack-intel.js extends stack-fingerprint with 12 CMS, 13 analytics,
and 7 experimentation platform detectors.
- Bin now reads its version from package.json — no more drift.
- New outputs: *-icon-system.json, *-stack-intel.json.
- background-patterns merged into *-visual-dna.json.
- 313/313 tests passing.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- perf.js: fresh Playwright context measures LCP/CLS/INP via
PerformanceObserver, categorises network responses into
js/css/font/image/document/other bytes, counts third-party requests
against a known-host list, synthesises an interaction so INP
reports. Returns grade buckets per vital.
- seo.js: pure extractor for OG, Twitter, canonical, manifest,
theme-color, viewport, favicons, and inline JSON-LD blocks.
- Crawler captures favicons + manifest link + JSON-LD script text.
- New flag --perf, auto-on with --full.
- New outputs: *-seo.json, *-perf.json.
- 307/307 tests passing.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- dark-mode-pair.js joins light+dark passes into semantic role pairs
(primary/secondary/accent/background/text), pairs CSS variables
that actually differ, and emits a drop-in Tailwind darkMode config
plus an audit of tokens missing from either pass
- responsive-screenshots.js captures full-page PNGs at mobile/tablet/
desktop/wide × (light,dark) with a JSON index
- New flag --responsive-shots, auto-on with --full
- New outputs: *-dark-mode.json, *-responsive.json
- CLI version test now reads from package.json so future minor
releases don't need to update the test
- 303/303 tests passing
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replaces the v9 hardcoded-selector screenshot pass with a cluster-
aware, retina (2×), multi-variant pipeline.
- New src/extractors/component-screenshots.js groups candidates by
kind + variantHint + sizeHint and captures up to three reps per
group. Falls back to the v9 hardcoded list when nothing clusters
(auth / docs pages).
- Dedicated Playwright context at deviceScaleFactor: 2 for crisp crops
- New *-screenshots.json index maps every crop to cluster/bounds
- Markdown gains a Component Screenshots section
- No new CLI flags — --screenshots / --full still opt into capture
- 299/299 tests passing
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Six new extractors (page-intent, section-roles, component-library,
material-language, imagery-style, logo), a multi-page crawl
orchestrator with cross-page consistency, an optional --smart LLM
fallback, and a ready-to-paste prompt pack for v0 / Lovable / Cursor /
Claude Artifacts.
v9 captured *how* a site looks. v10 captures *what it is* — the
semantic signal an LLM needs to rebuild a site faithfully.
- page-intent.js: landing/pricing/docs/blog/product/about/dashboard/auth/legal
- section-roles.js: hero/feature-grid/logo-wall/stats/testimonial/
pricing-table/faq/steps/comparison/bento/cta/footer + slot copy +
reading order
- component-library.js: shadcn/Radix/MUI/Chakra/Mantine/AntD/HeroUI/
Vuetify/Bootstrap/Tailwind detection with evidence + alternates
- material-language.js: glass/neumorph/flat/brutalist/soft-ui/
material-you/skeuo from shadow + geometry + saturation
- imagery-style.js: photo/3d/iso/flat-illustration/mesh/icon-only/
screenshot + dominant aspect + image-radius profile
- logo.js: SVG/PNG extraction + sampled clearspace
- multipage.js: auto-discovers canonical pages from nav, runs full
pipeline per page, emits Jaccard consistency
- classifiers/smart.js: opt-in LLM refinement via OPENAI_API_KEY or
ANTHROPIC_API_KEY, zero-dep fetch
- formatters/prompt-pack.js: v0.txt, lovable.txt, cursor.md,
claude-artifacts.md, per-component recipe cards
New CLI flags: --smart, --pages <n>, --no-prompts.
New output files: *-intent.json, *-visual-dna.json, *-library.json,
*-logo.{svg,png,json}, *-multipage.json, *-prompts/.
Extended markdown: 6 new sections.
297/297 tests passing.
Website: v10 capabilities section, version stamps bumped to v10,
and a fix for the Specimens IntersectionObserver that was hijacking
--accent on page load before the specimens strip was ever in view.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Reliability fixes that restore trust on real sites:
- colors.js: brand-color detection rewritten — ranks chromatic clusters by
interactiveBg x100 + saturation x2 + log(usage), requires HSL sat >25 or
an interactive-bg hit. Linear primary: #d0d6e0 (gray) -> #e4f222 (lime).
Stripe: #533afd. Verified on 5 ground-truth sites.
- accessibility.js + crawler.js: crawler now emits hasText per element
(direct text-node child with visible chars); WCAG extractor filters
decorative glyph spans, transparent overlays, non-text containers.
Linear: 25% (171 failing pairs) -> 83% (1 failing pair).
- scoring.js: rubric recalibrated against Stripe/Linear/Vercel/GitHub/Apple.
Loosened color/shadow/radii/type-scale thresholds; softened spacing
no-base penalty when tokenization is present; cssHealth now weighted in
the overall. Linear 47->76, Stripe 81->88, Apple 83->86.
New CLI flags:
- --selector <css>: scope extraction to a DOM subtree. Stripe: 2409 -> 112
elements when scoped to footer. Falls back to full doc if invalid.
- --system-chrome: channel: 'chrome' in Playwright launch; skips the
bundled Chromium download.
- --json: full extraction to stdout (already partial in v7, now first-class
and documented).
New distribution surfaces (each publishes to its own registry):
- vscode-extension/: Extract-from-URL + inject-into-workspace commands.
- raycast-extension/: Extract, Score, Copy-CLI commands.
- figma-plugin/: URL or paste-JSON -> Figma Variables with multi-mode.
- github-action/: "Design regression guard" runs designlang on PRs, diffs
tokens vs baseline, comments the delta, optional fail-on-change.
- smithery.yaml + smithery.dockerfile + docs/MCP-REGISTRY.md: MCP registry
submission checklist.
- chrome-extension/PRIVACY.md + STORE_LISTING.md: Chrome/Firefox/Edge
store listing prep (extension code already existed in v7.1).
- docs/LAUNCH.md: PH + Show HN + Twitter copy + day-of checklist.
- docs/demo.tape: VHS tape for the animated README hero.
README updated: hero references demo.gif with PNG fallback, adds "Install
everywhere" table for the new surfaces, documents the three new flags.
.npmignore excludes every companion-surface directory so the npm tarball
stays 109KB / 73 files.
All 275 tests pass.
* docs: v7.1 spec — designer toolkit
* feat(v7.1): cookie-file loader + --insecure + --user-agent + Chrome extension
Ships three community-requested features in one release.
## Cookie handling
- `--cookie-file <path>` loads cookies from JSON array, Playwright storageState, or Netscape cookies.txt.
- `src/utils-cookies.js` with 8 unit tests covering all three formats plus merge-with-CLI behavior.
## Network / auth
- `--insecure` sets `ignoreHTTPSErrors: true` on the Playwright context and adds the matching Chromium flags.
- `--user-agent <ua>` overrides the browser UA.
## Chrome extension (chrome-extension/)
- Manifest v3 popup with activeTab permission only.
- Handoff button opens the hosted extractor with the current URL prefilled (via `?url=`).
- Copy-CLI button drops `npx designlang <url>` into the clipboard.
- Four PNG icons rendered from the existing favicon SVG.
- Install-in-dev-mode instructions in chrome-extension/README.md.
## Website
- HeroExtractor now honours `?url=` query param (Chrome extension handoff, deep links). Prefill is mount-only and URL-validated.
## Contributing
- CONTRIBUTING.md adds a 'Good first issues' list and a 'Credits' section. Bumped to v7.1.0.