关于 taste
taste 是用于分析网站设计并提取设计规范的技能,会从 URL 生成可读说明和结构化 JSON,供后续设计工作使用。它借助 Playwright MCP 捕获页面,并记录设计取舍及其依据。
主要功能
- 01提取颜色、字体与间距等设计令牌
- 02记录设计取舍及证据
- 03生成 Markdown 与 JSON 文件
- 04支持单页或关联页面分析
- 05导出至指定设计工具的规则或样式
适用场景
- 01将网站视觉风格转为项目设计指导
- 02为设计系统提取样式令牌
- 03比较竞品网站的设计选择
- 04为 Cursor 或 Windsurf 等工具生成设计参考
MCP 相关
运行时需要已连接的 Playwright MCP 服务,以浏览器访问和捕获页面。技能使用其浏览器工具采集截图与 DOM 数据。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ senlindesign/ taste-skill --skill taste安装后在 Claude Code 中输入/taste确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
README.md.gitignoredocs/Cherry.glbindex.htmlevals/evals.jsonreferences/extract.jsexport-formats.mdstep1-measure.mdstep2-pattern.mdstep4-observer.mdstep3-taste.md详细介绍
Taste — 反向解析网站的设计 DNA
此技能可将 URL 转化为两个文件:
./{domain}.md— 供人阅读,包含两个部分:- Design Map — 实用设计标记(颜色、字体比例、间距、圆角、阴影、网格)
- Taste DNA — 3-4 条鲜明的设计取舍(触发因素 → 决策 → 原因 → 证据)
./{domain}.json— 结构化数据,包含相同内容,采用机器可解析的格式,供下游工具(Cursor、Windsurf、设计系统)使用。
此流程会拒绝“简洁现代”这类泛泛描述。完成后的 taste.md 应读起来像一位资深设计师在解释:这个页面为什么做出这些特定选择,以及它拒绝了哪些看似合理的替代方案。
何时启用
每当用户想要研究网站设计,并将其整理为未来设计工作的指导时,都应触发此技能。包括以下所有情况:
- 明确的斜杠命令:
/taste <url> - 自然语言请求:“分析 vercel.com 的设计”“Stripe 网站为什么这么出色”“提取 linear.app 的设计标记”“给我 are.na 的设计 DNA”
- 模仿意图:“我想让我的仪表盘有 Linear 的感觉”“按照 的风格为我制作一个落地页”“把这个网站的设计移植到我的项目中”
- 竞品研究:“比较我们和 的视觉风格”“ 使用了哪些设计惯例”
- 用户在任何场景下提到 URL,并询问其设计选择、字体排印、颜色、间距、设计理念或“感觉”
只要用户在视觉或设计相关话题中提到 URL,就倾向于启用此技能——Claude 往往不会充分触发技能。如有疑问,就使用它。误调用技能的代价很小;而当此技能本可提供具体且有证据支撑的分析时,却给出泛泛的设计建议,代价就很大。
不要在以下情况启用:“从网站提取数据”(使用抓取技能)、“总结 的内容”(使用 WebFetch)、“部署这个网站”(无关)。
前置条件
此技能要求安装并连接 Playwright MCP 服务(https://playwright.dev/docs/getting-started-mcp)。使用以下命令验证:
claude mcp list | grep playwright
如果看到 playwright: ... - ✓ Connected,说明已就绪。否则,请安装:
claude mcp add playwright -s user -- npx -y @playwright/mcp@latest --isolated
为什么要使用 --isolated:每次运行 /taste 都会从全新的浏览器状态开始,因此 Cookie、登录会话和先前的缓存不会泄漏到被分析的页面中。如果不使用它,当你恰好已登录 Linear 时运行 /taste https://linear.app,分析到的会是应用仪表盘,而不是公开的营销页面——页面选错,设计品味也就错了。
为什么要使用 npx @playwright/mcp@latest(不带 --browser 标志):Playwright 会下载并使用自带的 Chromium(约 100MB,只需下载一次)。这比依赖用户系统中的 Chrome 更具可移植性——它可在未安装 Chrome 的设备上运行,为不同用户提供一致的渲染效果,也绝不会在用户真实的浏览器配置文件中打开窗口。
安装后,用户必须重启 Claude Code,才能让 MCP 工具(mcp__playwright__browser_*)出现在当前会话中。如果运行此技能时 Playwright 不可用,请停止并明确告知用户:“我需要 Playwright MCP 来抓取页面。运行 claude mcp add playwright -s user -- npx -y @playwright/mcp@latest --isolated 并重启 Claude Code,然后再试一次。”
首次运行时,Playwright 可能需要约 30-60 秒,browser_navigate 才会首次返回——这是一次性下载 Chromium 所需的时间。后续运行只需几秒。如果用户想提前下载以避免等待,可以在调用此技能前运行一次 npx playwright install chromium。
工作流程
按顺序遵循以下五个阶段。每个阶段都有明确的成功标准——当前阶段未产出下一阶段所需内容之前,不要进入下一阶段。
阶段 0 — 解析 URL 并确定导出目标
步骤 1 — URL
从用户的消息中提取 URL。接受以下形式:
/taste https://linear.app- “analyze the design of vercel.com”(如果缺少
https://,则补上) - 提示中的任意位置出现的裸 URL
如果用户没有提供 URL,请询问。如果用户提供的是文件路径或明显不是 URL 的内容,请询问他们指的是否是托管页面。在获得有效 URL 之前,不要继续。
导航前,先解析常见的简写形式:linear.app → https://linear.app,https://www.stripe.com 可以保持原样。
步骤 2 — 提取域名用于命名文件
从 URL 中提取主机名,并去掉任何 www. 前缀。例如:
https://linear.app→linear.apphttps://www.stripe.com→stripe.comhttps://vercel.com/home→vercel.com
将其存为 {domain}。所有输出文件都将以此命名:{domain}.md、{domain}.json 以及任何导出文件。切勿使用通用名称 taste.md — 用户在同一目录中对多个网站运行此技能时,该名称会冲突。
步骤 3 — 导出目标 + 抓取范围
如果用户已在消息中同时指定导出目标和抓取范围,则完全跳过此问题。如果缺少其中任一项,请在一条消息中一次性询问:
“开始前有两个简短问题:
导出目标 — 你正在使用哪个工具?
1 Cursor → .cursor/rules/{domain}-taste.mdc 2 Windsurf → .windsurf/rules/{domain}-taste.md 3 Claude Code → CLAUDE.md(追加 Design Taste 部分) 4 GitHub Copilot → .github/copilot-instructions.md(追加) 5 Bolt → .bolt/prompt 6 Antigravity → GEMINI.md 7 v0 by Vercel → taste-tokens.css + instructions 8 Figma Make → taste-figma.css + instructions 9 Lovable → 输出可粘贴到 Project Knowledge 的文本 10 跳过 → 仅保留 {domain}.md + {domain}.json抓取范围 — 仅此页面,还是浏览 2–3 个链接页面?
1 仅此页面 → 更快,专注于你提供的页面 2 浏览链接页面 → 我会访问 2–3 个导航页面并合并数据 ```”
将答案存为 {exportTarget} 和 {crawlScope}。默认值:{exportTarget} = "skip",{crawlScope} = "single"。不要再次询问。
阶段 1 — 捕获页面数据(Playwright MCP)
按顺序执行以下步骤。如果任何步骤出错,请停止整个流程并向用户报告错误 — 不要在数据不完整的情况下悄然继续。
-
调整视口大小至 1440×900,确保每次运行的测量结果一致:
mcp__playwright__browser_resize width=1440 height=900 -
导航至该 URL:
mcp__playwright__browser_navigate url=<the URL> -
稍作等待,让客户端完成水合。对于大型 SPA(figma.com、notion.so),在
domcontentloaded后需要等待几秒钟,才能渲染实际内容。使用:mcp__playwright__browser_wait_for time=3如果 3 秒后页面快照看起来仍是加载骨架屏,再等待 3 秒。如果之后仍是骨架屏,请在最终输出中注明(“页面可能未能完整渲染;部分测量值为近似值”)。
-
截取两张屏幕截图 — 先截取视口,再截取整页:
4a. 视口截图(1440×900,不缩放 — 这是步骤 1 的主要视觉参考):
mcp__playwright__browser_take_screenshot type=jpeg filename={domain}-viewport.jpeg4b. 有条件地截取整页截图 — 首先检查页面高度:
mcp__playwright__browser_evaluate function=() => document.documentElement.scrollHeight- 如果高度不超过视口高度的 6 倍(在 1440×900 分辨率下不超过 5400px):截取常规整页截图:
mcp__playwright__browser_take_screenshot fullPage=true type=jpeg filename={domain}-fullpage.jpeg - 如果高度超过视口高度的 6 倍:跳过整页截图(页面太长,会浪费 token)。改为截取两个指定位置的视口截图:
// 页面中部(滚动 50%) mcp__playwright__browser_evaluate function=() => window.scrollTo(0, document.documentElement.scrollHeight * 0.5) mcp__playwright__browser_take_screenshot type=jpeg filename={domain}-mid.jpeg // 页脚 mcp__playwright__browser_evaluate function=() => window.scrollTo(0, document.documentElement.scrollHeight) mcp__playwright__browser_take_screenshot type=jpeg filename={domain}-footer.jpeg // 滚回顶部 mcp__playwright__browser_evaluate function=() => window.scrollTo(0, 0)
在步骤 1 中,将视口截图用作主要视觉参考——它展现了设计师希望用户看到的第一印象。使用整页截图或中部+页脚截图,核实页面较下方才出现的样式(页脚排版、后续版块的颜色变化等)。与 PNG 相比,JPEG 能减少 token 消耗。
- 如果高度不超过视口高度的 6 倍(在 1440×900 分辨率下不超过 5400px):截取常规整页截图:
-
运行 DOM 提取器。读取
references/extract.js,并将其完整内容作为function参数传入:mcp__playwright__browser_evaluate function=<contents of references/extract.js>工具会返回一个 JSON 对象。将其暂存为
domData,以便在步骤 1 中使用。
6.(可选清理)浏览器会在会话剩余时间内保持打开。除非用户要求,否则无需关闭。
多页面采集(仅当 {crawlScope} 为 "multi" 时):
采集完主要页面后,提取导航链接,并访问同一网站中最多 2 个其他页面。
6a. 提取导航链接,从已加载的主要页面中获取:
(function() {
const links = [];
const seen = new Set([location.pathname]);
const skip = /\/(login|logout|signup|sign-in|register|auth|account|checkout|cart|password|reset)\b/i;
document.querySelectorAll('nav a, header a, [role="navigation"] a').forEach(a => {
try {
const u = new URL(a.href);
if (u.hostname !== location.hostname) return;
if (skip.test(u.pathname)) return;
if (seen.has(u.pathname)) return;
if (u.pathname === '/' && location.pathname !== '/') return;
seen.add(u.pathname);
links.push({ href: u.origin + u.pathname, text: (a.innerText || a.textContent).trim().slice(0, 40) });
} catch(e) {}
});
return links.slice(0, 6);
})()
6b. 选择 2 个页面,从返回列表中挑选。优先选择:
- 路径较短的页面(
/product优于/product/features/detail) - 版块名称不同的页面(Product、Community、Pricing、Docs,而非同一版块下仅 slug 不同的页面)
- 如果已采集根路径
/,则避免再次选择
6c. 对每个其他页面,执行较精简的采集流程(导航 → 等待 3s → 仅截取视口截图 → DOM 提取器)。第 2 至第 3 页无需截取整页/中部/页脚截图——视口截图足以确认设计是否一致,DOM 提取器会采集整个页面。截图命名为 {domain}-viewport-2.jpeg、{domain}-viewport-3.jpeg。将每个页面的数据保存为 pages[1]、pages[2](pages[0] 为主要 URL)。
如果链接页面加载失败或受到阻止,则静默跳过,并在第 6 阶段的报告中注明。
6d. 在阶段 2 之前合并数据。合并所有页面的颜色候选项(取并集)和排版数据(取并集)。同一值出现在 2 个或更多页面上时,即为系统信号——请标记。只在单个页面上出现的值属于局部值——仍需记录,但降低其权重。
在步骤 1–3 中,始终说明分析了多少个页面(“在 3 个页面中:……”),并区分系统样式与局部样式。多个页面达成一致,是判断设计偏好最有力的依据。
阶段 1 的成功标准:至少有一张截图,并且主要页面的 domData JSON 已填充 colors、typography、layout、effects、cards、images、spacingSamples、sectionGaps 和 grid 字段。如果其中任一字段完全为空,且截图中显示了实际内容,则说明提取器需要改进——请注明此情况并继续。
数据不完整时的处理方式:如果 domData.errors 不为空,说明提取器部分失败。在步骤 1 中,将受影响的类别标记为 ~approx (extractor section failed),并依据截图测量这些类别。在阶段 6 的报告中,将失败的部分列为注意事项。
阶段 2 — 运行 4 步分析
截图是事实依据。 在阅读任何参考文件之前:视口截图展示了人们实际看到的内容。DOM 数据提供精确数值。两者冲突时,以截图为准。DOM 中出现、但覆盖可见表面面积 <5% 的颜色属于装饰色——不要将其列为品牌色。截图中未出现的分区分隔线,无论 DOM 报告什么,都视为不存在。无法察觉的阴影(≤3% 不透明度)是 CSS 伪影,不是设计决策。
references/ 中的四个参考文件包含各步骤的完整提示词。到达每一步时再阅读对应文件(不要一次性预读全部四个文件——这些步骤是刻意按顺序设计的,前面的步骤不需要后续步骤的说明)。
每个步骤:
- 阅读对应的参考文件。
- 在你自己的回复中生成该文件要求的输出。
- 使用参考文件指定的标记行作为输出开头(例如,
### Step 1 Output — Measurements)。 - 下一步会将你之前的输出作为输入——将它们保留在对话中,不要把它们概括掉。
步骤 1 — 测量
- 阅读
references/step1-measure.md - 输入:
domData(browser_evaluate返回的 JSON)+ 截图 - 产出:20 类测量数据,每个数值都要标明具体的 px / hex / 比率
步骤 2 — 模式
- 阅读
references/step2-pattern.md - 输入:步骤 1 的输出
- 产出:5-8 个系统性模式,每个都包含 Pattern / Evidence / Design Goal
步骤 3 — 品味
- 阅读
references/step3-taste.md - 输入:步骤 1 + 步骤 2 的输出
- 产出:4 条品味原则(每条都包含 Trigger / Decision / Reason / Evidence),至少包含一项克制取舍
步骤 4 — 观察者
- 阅读
references/step4-observer.md - 输入:步骤 1 + 2 + 3 的输出 + 原始 URL(必须将其填入 JSON 的
source字段) - 产出:一个带围栏的
json代码块,后接 Markdown 设计地图 + 品味 DNA
阶段 3 — 写入输出文件
步骤 4 的回复包含两种格式。提取它们:
- JSON:找到步骤 4 输出中的第一个
json围栏代码块。解析它(必须是有效 JSON——如果不是,说明步骤 4 失败;指出解析错误并重新运行步骤 4)。 - Markdown:取步骤 4 输出中 JSON 代码块结束后的全部内容。移除开头的空白字符。
然后使用你在阶段 0 中提取的 {domain},将两个文件写入当前工作目录(如需确认目录位置,可使用 pwd):
./{domain}.md— Markdown 部分./{domain}.json— JSON,使用 2 个空格缩进美化输出
如果任一文件已存在,直接覆盖,无需询问。用户对同一网站重复调用此技能时,期望最新分析结果覆盖旧结果。
阶段 4 — 自我审查(反空话检查)
通过 Bash 工具运行此 grep——不要凭记忆检查:
grep -icE 'clean|modern|sleek|visually appealing|user-friendly|intuitive|seamless|\belegant\b|minimalist|polished|refined|sophisticated|delightful|stunning|\bbeautiful\b|\bpremium\b' ./{domain}.md
如果计数为 0,则文件通过检查。如果 >0,显示命中的行:
grep -inE 'clean|modern|sleek|visually appealing|user-friendly|intuitive|seamless|\belegant\b|minimalist|polished|refined|sophisticated|delightful|stunning|\bbeautiful\b|\bpremium\b' ./{domain}.md
对于每个命中:
- 出现在引用的反衬描述中(“他们本可以选择‘简洁现代’的风格,但却……”)——没问题,计为通过。
- 用作对此设计的正面描述——属于空话。编辑相应原则,重新保存,并重新运行 grep,直到计数为 0。
还要通过 Bash 验证:
grep -c "Design Map\|Taste DNA" ./{domain}.md
必须返回 2。如果小于 2,说明缺少某个章节——指出缺失章节并重新运行步骤 4。
验证 JSON:
python3 -m json.tool ./{domain}.json > /dev/null && echo "valid" || echo "INVALID"
如果任何检查失败,先修复并重新运行,再交付。
阶段 5 — 导出为你的构建工具
你已在阶段 0 记录了 {exportTarget}。不要再次询问。
如果 {exportTarget} 是 "skip",直接进入阶段 6。
如果 {exportTarget} 是 "all",生成所有基于文件的格式(选项 1–8)。
否则,根据 {exportTarget} 确定导出内容。接受自然语言的同义说法:"cursor"、"windsurf"、"claude" / "claude code"、"copilot"、"bolt"、"antigravity" / "gemini"、"v0"、"figma" / "figma make"、"lovable"。
阅读 references/export-formats.md,了解每个目标对应的确切文件路径、frontmatter 结构和内容规范。所有格式都基于 {domain}.json 生成,并且必须遵循相同的 Anti-Slop 规则——避免模糊的感觉描述,引用具体的 px/hex。
阶段 6 — 报告
向用户输出以下内容(替换实际的 {domain}、行数和字节数):
✓ Wrote ./{domain}.md (<line-count> lines) and ./{domain}.json (<byte-count> bytes)
[if export file(s) written]: ✓ Also wrote <path(s)>
Sharpest principle: "<name of the strongest taste principle>"
→ <one-sentence quote of its Decision>
Open {domain}.md to read the full Design Map + Taste DNA.
保持简洁。让文件说明一切。
错误处理
| 失败情况 | 响应 |
|---|---|
| 未安装/未连接 Playwright MCP | 使用上方“先决条件”部分中的准确安装命令停止操作。不要尝试回退到 WebFetch——截图对步骤 1 至关重要。 |
| URL 无法访问 / 404 / DNS 失败 | 告知用户页面未能加载。不要基于错误页面提交分析。 |
| Cloudflare / 机器人检测拦截 | 截图会显示“verify you are human”页面。在步骤 1 中检测到此情况(大片空白,只有一个标有“Verify”的按钮)。告知用户该网站阻止自动访问;如果用户想要截图,建议他们在自己的浏览器中手动打开 URL,或尝试同一域名下的其他页面。 |
| SPA 等待后仍在渲染 | 等待两次,每次 3 秒后,使用当前已加载的内容继续。向报告添加一行说明:“页面可能仍在进行 hydration;部分测量值为近似值。” |
| 用户提供的是文件路径,而非 URL | 询问用户是否指托管版本。不要尝试打开本地文件——此技能适用于在线页面。 |
| 用户提供的 URL 需要登录 | 检测登录页面(含密码输入框的表单)。告知用户此技能不处理需要身份验证的页面,并建议改用公开的营销页面。 |
| 步骤 4 返回格式错误的 JSON | 指出具体解析错误后,重新运行一次步骤 4。如果再次失败,将原始输出保存为 ./{domain}-raw.md,并告知用户手动检查。 |
关于理念的说明(阅读一次,牢记,然后基本上放下)
此技能建立在一个鲜明的观点之上:设计令牌对 AI Agent 毫无用处。令牌只会说“间距是 8px”;品味则会说“间距是 8px,因为设计师选择了易读的节奏,而非数据密度;在 1× 缩放下,8px 是仍能营造明确设计感的最小单位”。正是这种原因,才能让同一个 Agent 为不同的页面生成出色设计,而不是只会照抄数字。
references/ 中的四个提示词,是基于 Gemini 的生产验证流水线的移植版本。早期版本中最大的失败模式是输出内容泛泛而谈——大段诸如“此设计采用简洁现代的美学风格,搭配直观的导航”的文字,却不包含任何有用信息。Anti-Slop 检查(禁用短语、强制要求说明克制取舍、证据要求)之所以存在,是因为每删除一条薄弱原则,都抵得上新增十条证据充分的原则。
如果不确定某条品味原则是否有价值,就问自己:“如果我从未见过这个特定网站,还能写出这条原则吗?”如果可以,那就是废话。删掉它。