extract-design-md
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseExtract DESIGN.md from a site
从站点提取DESIGN.md
Given a live URL, produce a —
YAML design tokens (colors, typography, , , ) plus
prose in canonical section order — good enough to hand a coding agent so it builds
new UI matching the source site.
DESIGN.mdroundedspacingcomponentsCore idea (from research): tokens map ~1:1 to a site's CSS custom properties +
computed styles, so the heavy lifting is a cheap in-browser extraction — not vision.
Screenshots feed prose only. The official linter is a free quality gate.
URL ─▶ 1 DISCOVER ─▶ 2 EXTRACT TOKENS ─▶ 3 HARVEST COMPONENTS
─▶ 4 CAPTURE FEEL ─▶ 5 SYNTHESIZE ─▶ 6 VALIDATE ─▶ DESIGN.md给定一个可访问的URL,生成一个文件——包含YAML格式的设计令牌(颜色、排版、、、)以及按标准章节顺序排列的文字说明,足以交给编码Agent构建与源站点风格一致的新UI。
DESIGN.mdroundedspacingcomponents核心思路(来自研究): 设计令牌与站点的CSS自定义属性和计算样式几乎是1:1对应的,因此主要工作由低成本的浏览器内提取完成,而非视觉识别。截图仅用于文字描述部分。官方linter作为免费的质量校验关卡。
URL ─▶ 1 DISCOVER ─▶ 2 EXTRACT TOKENS ─▶ 3 HARVEST COMPONENTS
─▶ 4 CAPTURE FEEL ─▶ 5 SYNTHESIZE ─▶ 6 VALIDATE ─▶ DESIGN.mdPrerequisites
前置条件
This skill drives three external tools — make sure each is available before running:
- playwright-cli on — the in-browser extraction and screenshots run through it. Install once with
PATHthennpm install -g @playwright/cli@latest(needs Node.js 18+). Check:playwright-cli install --skills.which playwright-cli - A reachable Firecrawl instance — used for page
discovery () and optional copy scraping. The hosted API or a self-hosted / local instance both work; if Firecrawl is unreachable the skill falls back to playwright link discovery (thinner page coverage). Confirm your instance responds before a run.
firecrawl map - (Node.js) — pulls the official
npxlinter on demand for the quality gate. If it's unavailable the skill writes the file anyway and notes "lint skipped".@google/design.md
If your agent sandboxes network or filesystem access, allow the outbound calls this skill makes (headless browsing, Firecrawl,) before running.npx
Let = this skill's directory. Pick a stable playwright session name, e.g. .
SKILLS=designmd本技能会调用三个外部工具——运行前请确保每个工具都可用:
- playwright-cli 需在中——浏览器内提取和截图都通过它运行。执行一次安装:
PATH,然后运行npm install -g @playwright/cli@latest(需要Node.js 18+)。检查命令:playwright-cli install --skills。which playwright-cli - 可访问的Firecrawl实例——用于页面发现()和可选的文案抓取。托管API或自托管/本地实例均可;如果Firecrawl不可访问,本技能会回退到playwright链接发现(页面覆盖度较低)。运行前请确认你的实例可以正常响应。
firecrawl map - (Node.js)——按需拉取官方
npxlinter用于质量校验。如果不可用,本技能仍会生成文件,并标注“lint已跳过”。@google/design.md
如果你的Agent对网络或文件系统访问做了沙箱限制,请在运行前允许本技能发起的出站调用(无头浏览、Firecrawl、)。npx
设为本技能的目录。选择一个稳定的playwright会话名称,例如。
SKILLS=designmdFlags
参数标志
| Flag | Default | Effect |
|---|---|---|
| required | Entry-point URL |
| 5 | Max pages to sample |
| auto | Pin exact pages (skips the confirm prompt) |
| shots ON | Skip the feel pass; prose then leans on token names + copy |
| | |
| | Output folder |
| lint ON | Skip the linter (auto-skips if |
| 参数标志 | 默认值 | 作用 |
|---|---|---|
| 必填 | 入口URL |
| 5 | 最大采样页面数 |
| 自动 | 指定确切的页面(跳过确认提示) |
| 开启截图 | 跳过质感采集步骤;文字描述将依赖令牌名称+页面文案 |
| | |
| | 输出文件夹 |
| 开启lint | 跳过linter校验(如果 |
Stage 1 — Discover pages
阶段1 — 发现页面
bash
firecrawl map "<url>" > "<out>/raw/map.json"Bucket the returned URLs into page-type slots and pick the best match per slot
(always include the homepage), capped at (default 5):
--pages- homepage (the input URL, always) — core palette + type + hero CTA
- pricing / product — cards, toggles, tables
- auth / login / signup / contact — inputs, form fields
- blog / docs / changelog — long-form prose type
- brand / about / design — often states colors & fonts explicitly; high value
Show the auto-picked list and accept add/remove/replace before crawling (one concise
prompt; skip it if was given). Skip a slot with no match — never force a
sample. If Firecrawl is down, fall back to playwright link discovery
( returning ) — see
.
--pages-listrun-code[...document.links].map(a=>a.href)references/edge-cases.mdbash
firecrawl map "<url>" > "<out>/raw/map.json"将返回的URL按页面类型分类,每个类别选取最佳匹配页面(始终包含首页),总数不超过参数指定的数量(默认5个):
--pages- 首页(始终为输入的URL)——核心调色板+字体+首屏CTA
- 定价/产品页——卡片、开关、表格
- 认证/登录/注册/联系页——输入框、表单字段
- 博客/文档/更新日志页——长文本排版
- 品牌/关于/设计页——通常会明确说明颜色和字体;价值很高
爬取前展示自动选取的页面列表,支持添加/移除/替换(仅一次简洁提示;如果指定了则跳过)。没有匹配页面的类别直接跳过——绝不强制采样。如果Firecrawl不可用,回退到playwright链接发现(返回)——详见。
--pages-listrun-code[...document.links].map(a=>a.href)references/edge-cases.mdStage 2 — Extract global tokens (the core)
阶段2 — 提取全局令牌(核心步骤)
Open the homepage, wait for it to settle, run the bundled extractor. The extractor
() reads noise-filtered vars, mode-samples computed
styles of visible main-content elements, tags the prominent CTA + first input, and
forces hover/focus — see for what it returns and why.
scripts/extract-tokens.js:rootreferences/extraction.mdIntermediate artifacts live under so the two deliverables stay uncluttered
at the folder root — see Output layout. Create the folders once:
<out>/raw/bash
S=designmd
mkdir -p "<out>/raw/tokens" "<out>/raw/components" "<out>/raw/copy" "<out>/raw/logs" "<out>/screenshots"
playwright-cli -s=$S open "<homepage-url>"
sleep 2 # let CSS/fonts settle (FR-ROB.1)
playwright-cli -s=$S run-code "$(cat "$SKILL/scripts/extract-tokens.js")" \
| bash "$SKILL/scripts/slice-result.sh" > "<out>/raw/tokens/tokens.home.json"slice-result.shvarsTotalvarsvarsvarsExtrareferences/edge-cases.md打开首页,等待页面稳定后,运行内置的提取器。提取器()会读取经过噪声过滤的变量,对可见主内容元素的计算样式进行模式采样,标记突出的CTA和第一个输入框,并触发hover/focus状态——返回值及设计原因详见。
scripts/extract-tokens.js:rootreferences/extraction.md中间产物存放在目录下,这样两个最终交付物在文件夹根目录下保持整洁——详见输出结构。一次性创建所需文件夹:
<out>/raw/bash
S=designmd
mkdir -p "<out>/raw/tokens" "<out>/raw/components" "<out>/raw/copy" "<out>/raw/logs" "<out>/screenshots"
playwright-cli -s=$S open "<homepage-url>"
sleep 2 # let CSS/fonts settle (FR-ROB.1)
playwright-cli -s=$S run-code "$(cat "$SKILL/scripts/extract-tokens.js")" \
| bash "$SKILL/scripts/slice-result.sh" > "<out>/raw/tokens/tokens.home.json"slice-result.shvarsTotalvarsvarsvarsExtrareferences/edge-cases.mdTheme detection (decision 8)
主题检测(决策8)
Inspect in the JSON. A site is dual-theme when it exposes a
light/dark switch — a class or on , or a
response. When two themes exist and is /,
extract once per theme: toggle, re-settle, re-run the extractor into a second file
(). Toggle order of preference:
themeSignal.darkdata-theme<html>prefers-color-scheme--themeautobothraw/tokens/tokens.home.dark.json- click the site's own theme switch, else
- set the class/attribute directly, e.g. doing
run-code(ordocument.documentElement.classList.add('dark')), elsesetAttribute('data-theme','dark') - emulate .
prefers-color-scheme
Re- after toggling. If the alternate theme can't be triggered reliably,
capture the loaded theme only, emit one , and say so in the report.
pins one theme even on a dual-theme site. Full detail:
(EC-TH).
sleep 2DESIGN.md--theme light|darkreferences/edge-cases.md检查JSON中的字段。如果站点提供明/暗主题切换——即标签上有类或属性,或对有响应——则该站点为双主题。当存在两个主题且参数为/时,每个主题各提取一次:切换主题,等待页面重新稳定,重新运行提取器,输出到第二个文件()。主题切换的优先顺序:
themeSignal<html>.darkdata-themeprefers-color-scheme--themeautobothraw/tokens/tokens.home.dark.json- 点击站点自身的主题切换按钮,若不行则
- 直接设置类/属性,例如通过执行
run-code(或document.documentElement.classList.add('dark')),若不行则setAttribute('data-theme','dark') - 模拟。
prefers-color-scheme
切换后再次。如果无法可靠触发另一个主题,则仅采集已加载的主题,生成一个文件,并在报告中说明。即使是双主题站点,也会固定使用单一主题。详细说明:(EC-TH)。
sleep 2DESIGN.md--theme light|darkreferences/edge-cases.mdStage 3 — Harvest components + states (pages 2–N)
阶段3 — 采集组件与状态(第2至N页)
For each additional page, don't re-dump global vars (they're shared) — sample the
components that page is good for (inputs on auth, cards/toggles on pricing, prose on
blog). Reuse the same extractor; keep each page's JSON:
bash
playwright-cli -s=$S goto "<page-2-url>"
sleep 2
playwright-cli -s=$S run-code "$(cat "$SKILL/scripts/extract-tokens.js")" \
| bash "$SKILL/scripts/slice-result.sh" > "<out>/raw/tokens/tokens.<slug>.json"Any bespoke per-page component captures (card/pill candidates, etc.) go to
; scraped copy to ; per-step logs to .
<out>/raw/components/<out>/raw/copy/<out>/raw/logs/The extractor already forces on the CTA and on the first input and
returns the diffs in . Keep only states that differ from the base (FR-ST.3)
when you synthesize. Merge across pages: union the CSS vars (homepage wins the core
palette, flag conflicts); accumulate components, collapsing identical styles.
hoverfocusstates对于每个额外的页面,不要重新导出全局变量(它们是共享的)——只采样该页面特有的组件(例如认证页的输入框、定价页的卡片/开关、博客页的文本排版)。复用同一个提取器;保留每个页面的JSON:
bash
playwright-cli -s=$S goto "<page-2-url>"
sleep 2
playwright-cli -s=$S run-code "$(cat "$SKILL/scripts/extract-tokens.js")" \
| bash "$SKILL/scripts/slice-result.sh" > "<out>/raw/tokens/tokens.<slug>.json"所有页面特有的定制化组件采集结果(如候选卡片/标签等)存放在;抓取的文案存放在;每步的日志存放在。
<out>/raw/components/<out>/raw/copy/<out>/raw/logs/提取器已经对CTA触发了状态,对第一个输入框触发了状态,并将差异返回到字段中。合成时仅保留与基础状态不同的状态(FR-ST.3)。跨页面合并:合并所有CSS变量(核心调色板以首页为准,冲突处标记出来);累加组件,合并相同样式。
hoverfocusstatesStage 4 — Capture feel (optional, default ON)
阶段4 — 采集设计质感(可选,默认开启)
One viewport screenshot per sampled page (not full-page), into :
screenshots/bash
playwright-cli -s=$S screenshot --filename="<out>/screenshots/<slug>.png"Optionally the homepage + brand page for
copy/tagline, saved to . Screenshots stay at (they
feed prose and the user may look at them). Screenshots and copy feed prose only
(Overview, Do's & Don'ts) —
never read token values off them. skips this stage.
firecrawl scrape --only-main-content "<url>"<out>/raw/copy/<out>/screenshots/--no-screenshots每个采样页面截取一张视口截图(非整页),保存到目录:
screenshots/bash
playwright-cli -s=$S screenshot --filename="<out>/screenshots/<slug>.png"可选地对首页和品牌页执行以抓取文案/标语,保存到。截图存放在(用于文字描述,用户也可以查看)。截图和文案仅用于文字描述部分(概述、注意事项)——绝不要从截图中读取令牌值。参数会跳过此阶段。
firecrawl scrape --only-main-content "<url>"<out>/raw/copy/<out>/screenshots/--no-screenshotsStage 5 — Synthesize the DESIGN file(s)
阶段5 — 合成DESIGN文件
Read the merged and map them onto the DESIGN.md schema. The full schema,
the token→DESIGN mapping table, and the canonical prose section order live in
— read it before writing the file. Key rules:
raw/tokens/*.jsonreferences/design-md-schema.md- Resolve primary-palette colors to hex from the computed values; keep the raw CSS var (
rgb(...)/lab()etc.) as a fallback. Never invent a color.color-mix() - Name colors by semantic role (→
--color-accent/primary); fold long gray ramps into a representativeaccentset — capture the system, not every shade.neutral - Use refs inside
{path.to.token}so values stay DRY and the linter validates them. Acomponentscolor must exist or the linter errors.primary - Capture only components the pages actually expose (decision 10) — never invent a
/
cardthat isn't there. Track which of the common set (button, input, card, link, chip) were found vs. missing for the report.chip - Emit prose sections only where you have real evidence, always in canonical order,
never a duplicate heading.
##
读取合并后的文件,将其映射到DESIGN.md schema。完整schema、令牌到DESIGN的映射表以及标准文字章节顺序都在**中——写入文件前请先阅读。** 核心规则:
raw/tokens/*.jsonreferences/design-md-schema.md- 主调色板的颜色需从计算得到的值转换为hex格式;保留原始CSS变量(
rgb(...)/lab()等)作为备用。绝不要虚构颜色。color-mix() - 按语义角色为颜色命名(→
--color-accent/primary);将较长的灰色阶折叠为有代表性的accent集合——采集的是设计系统,而非每个色阶。neutral - 在中使用
components引用,保持值的DRY原则,同时便于linter校验。{path.to.token}颜色必须存在,否则linter会报错。primary - 仅采集页面实际存在的组件(决策10)——绝不要虚构不存在的/
card组件。在报告中记录常见组件集(按钮、输入框、卡片、链接、标签)中哪些被找到、哪些缺失。chip - 仅在有实际依据时才输出文字章节,始终按标准顺序排列,绝不出现重复的标题。
##
Dual-theme output (decision 8)
双主题输出(决策8)
When two themes were captured, emit + — each a
complete, lint-valid file. , , and are shared;
and any color-dependent are per theme. A single-theme site emits one
. Prose may note the sibling theme exists.
DESIGN.light.mdDESIGN.dark.mdtypographyroundedspacingcolorscomponentsDESIGN.md如果采集了两个主题,则输出** + ——每个都是完整的、通过lint校验的文件。、和是共享的**;和所有依赖颜色的是按主题区分的。单主题站点输出一个。文字描述中可以说明存在另一个主题。
DESIGN.light.mdDESIGN.dark.mdtypographyroundedspacingcolorscomponentsDESIGN.mdStage 6 — Validate (quality gate)
阶段6 — 验证(质量关卡)
Lint every generated file:
bash
npx -y @google/design.md lint "<out>/DESIGN.md"- Auto-fix structural errors only: wrong section order, broken , missing
{refs}/required fields.primary - Flag value-level issues (out-of-gamut color, odd dimension) in the report — never silently delete a captured token to satisfy the linter (decision 12). The user decides on flagged values.
- Surface non-fatal warnings (e.g. WCAG AA contrast) without blocking.
- Re-lint after fixes; the final file must be error-clean. If /the linter is unavailable, write the file anyway and warn "lint skipped" in the report.
npx
对每个生成的文件执行lint:
bash
npx -y @google/design.md lint "<out>/DESIGN.md"- 仅自动修复结构错误:章节顺序错误、引用失效、缺少
{refs}/必填字段。primary - 在报告中标记值层面的问题(超出色域的颜色、不合理的尺寸)——绝不为了通过linter校验而静默删除已采集的令牌(决策12)。由用户决定如何处理标记的值。
- 展示非致命警告(例如WCAG AA对比度问题),不阻塞流程。
- 修复后重新执行lint;最终文件必须无错误。如果/linter不可用,仍生成文件,并在报告中警告“lint已跳过”。
npx
Output layout
输出结构
The two deliverables sit at the folder root; everything intermediate is tucked under
so the output reads cleanly at a glance.
raw/.design_mds/<domain>-YYYYMMDD/ # <domain> = host with dots→hyphens
├── DESIGN.md # single-theme (or DESIGN.light.md + DESIGN.dark.md)
├── screenshots/<slug>.png # 1 desktop-viewport PNG per page (if enabled)
└── raw/ # intermediate artifacts (audit trail + re-runs)
├── tokens/tokens.<slug>.json # raw extracted token/computed-style data per page/theme
├── components/ # any bespoke per-page component captures
├── copy/ # scraped page copy (if screenshots stage ran)
├── logs/ # per-step playwright/firecrawl logs
└── map.json # firecrawl page-discovery resultThe are always kept (decision 9) so prose can be regenerated
without re-crawling and any value is traceable. Conflict guard: if the folder already
exists for today's domain, ask (overwrite / suffix / abort) — never silently overwrite.
raw/tokens/*.json-2两个交付物位于文件夹根目录;所有中间产物都放在目录下,这样输出目录一目了然,非常整洁。
raw/.design_mds/<domain>-YYYYMMDD/ # <domain> = host with dots→hyphens
├── DESIGN.md # single-theme (or DESIGN.light.md + DESIGN.dark.md)
├── screenshots/<slug>.png # 1 desktop-viewport PNG per page (if enabled)
└── raw/ # intermediate artifacts (audit trail + re-runs)
├── tokens/tokens.<slug>.json # raw extracted token/computed-style data per page/theme
├── components/ # any bespoke per-page component captures
├── copy/ # scraped page copy (if screenshots stage ran)
├── logs/ # per-step playwright/firecrawl logs
└── map.json # firecrawl page-discovery resultraw/tokens/*.json-2Final report
最终报告
Keep it tight and honest. State what was captured, which components were found vs.
missing, which themes, and exactly what the linter said. If a stage degraded (no design
system, Firecrawl down, lint skipped), say so — don't imply full fidelity.
DESIGN.light.md + DESIGN.dark.md → .design_mds/cursor-com-20260630/
Sampled 4 pages: home, pricing, sign-in, blog
Themes: light + dark (detected via .dark on <html>)
Captured: 9 colors/theme, 6 type roles, 7 radius, full spacing
Components found: button-primary (+hover), input-field (+focus), card · missing: chip
Lint: ✓ both files clean (1 contrast warning on dark: text-muted on bg — AA borderline)
Screenshots: screenshots/ (4, desktop viewport)报告应简洁如实。说明采集了哪些内容,哪些组件被找到、哪些缺失,有哪些主题,以及linter的具体结果。如果某个阶段降级(无设计系统、Firecrawl不可用、lint跳过),要明确说明——不要暗示完全保真。
DESIGN.light.md + DESIGN.dark.md → .design_mds/cursor-com-20260630/
Sampled 4 pages: home, pricing, sign-in, blog
Themes: light + dark (detected via .dark on <html>)
Captured: 9 colors/theme, 6 type roles, 7 radius, full spacing
Components found: button-primary (+hover), input-field (+focus), card · missing: chip
Lint: ✓ both files clean (1 contrast warning on dark: text-muted on bg — AA borderline)
Screenshots: screenshots/ (4, desktop viewport)Ask-first rule (standing)
先问规则(常设)
Whenever <95% confident about a mapping or an ambiguous choice — which of two colors
is "primary", whether a site even has a real design system, how to resolve a same-day
output conflict — ask with a recommendation rather than guess. At minimum, surface
the ambiguity in the report. Any sub-agents you spawn run sequentially, never in
parallel, and must carry the Firecrawl + sandbox rules above.
每当对映射关系或模糊选择的置信度低于95%时——比如两种颜色中哪个是“primary”,站点是否真的有设计系统,如何解决当日输出冲突——带着建议询问用户,而非猜测。至少要在报告中说明模糊之处。你生成的任何子Agent都必须顺序运行,绝不能并行,且必须遵守上述Firecrawl和沙箱规则。
Bundled files
内置文件
- — the in-browser extractor for
scripts/extract-tokens.js(noise filter, mode sampling, CTA/input detection, hover/focus). The proven nucleus, productionized.run-code - — strips playwright-cli's markdown wrapper to clean JSON.
scripts/slice-result.sh - — what the extractor returns, field by field, and how to use
references/extraction.mdto relax the filter.varsExtra - — the DESIGN.md YAML schema, token→DESIGN mapping table, and canonical prose order. Read before Stage 5.
references/design-md-schema.md - — no design system, non-Tailwind, dual-theme toggling, merge conflicts, crawl/load failures, empty results.
references/edge-cases.md
- ——用于
scripts/extract-tokens.js的浏览器内提取器(噪声过滤、模式采样、CTA/输入框检测、hover/focus触发)。经过验证的核心模块,已生产化。run-code - ——去除playwright-cli的markdown包装,输出干净的JSON。
scripts/slice-result.sh - ——提取器返回的字段逐一说明,以及如何使用
references/extraction.md放宽过滤条件。varsExtra - ——DESIGN.md的YAML schema、令牌到DESIGN的映射表以及标准文字章节顺序。阶段5前必读。
references/design-md-schema.md - ——无设计系统、非Tailwind站点、双主题切换、合并冲突、爬取/加载失败、空结果等边缘情况。
references/edge-cases.md