Communitygithub.com

preview-first

在编写任何应用代码之前,先在设计阶段展示多个完整的设计方向,供开发者挑选并锁定设计合约。

preview-first 是什么?

该技能是一个“设计工作室”阶段,不是网站生成器。它强制在编写任何前端或UI代码之前,先进行多轮设计探索。技能会自动读取项目现有约束(如 package.json、Tailwind 配置、CSS 自定义属性、Logo、字体等),然后最多向开发者提出四个关键问题(产品描述、情感调性、固定约束、页面类型)。之后,它会运行一组确定性且只依赖标准库的 Python 脚本,生成 3 至 5 个完全不同、风格各异的设计方向,并在浏览器中展示包含色彩对比度验证、排版、按钮与组件、动效、草稿页面以及多种设备(iPhone、Samsung、Pixel、iPad、笔记本电脑)视图的完整预览。开发者可以在预览中实时调整并选择,最终输出一个正式的设计合约(design/DESIGN.md)和设计令牌(design/tokens.json 等),作为所有后续 UI 开发的唯一依据。该技能支持 Cursor、Claude Code、Codex 等平台。

兼容平台✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/moraneus/preview-first/tree/main/skills/preview-first

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

preview-first 是做什么的?

先看再建。此技能在所有应用程序代码编写之前插入一个设计阶段:开发者在浏览器中看到几个完整且截然不同的设计方向,选择一个,然后这个选择就变成了一份书面合约,所有后续会话都必须遵循。

这是一个设计工作室阶段,而不是网站生成器。此技能永远不会编写开发者的应用程序代码。它产生一个决策和一份合约。脚本是确定性的,只使用标准库 Python;判断(阅读概要、命名方向、撰写文案)是你自己的事情。

何时运行,何时提供

当开发者即将开始、重启或重新设计某个 Web 项目时,运行完整的阶段:"为 X 构建一个落地页"、"启动前端"、"我不喜欢这个外观"、"选择颜色和字体",或明确使用 /preview-first。

当项目已有 UI 代码但不存在 design/DESIGN.md 时,用一句话提供此技能:"想先看看设计方向吗?我可以展示当前外观以及替代方案。" 如果接受,将现有外观作为一个方向导入(参见导入),以便在同等条件下进行比较。

切勿在已经设置好样式的应用程序中进行小的编辑时触发(如 "添加一个按钮"、"修复内边距")。当 design/DESIGN.md 存在时,直接跳转到移交后阶段。

流程

所有脚本都位于此技能的 scripts/ 目录中。使用 python3(或如果项目使用 uv,则使用 uv run python3)运行它们。以下路径相对于项目根目录。

1. 读取项目,然后最多问四个问题

在提问之前先读取已存在的内容:package.json、Tailwind 配置、CSS 自定义属性、Logo SVG、现有字体、README。任何找到的内容都是一个约束,而不是问题。

只问仓库无法回答的问题,用通俗语言,一条信息:

  1. 产品是什么,目标用户是谁,用一句话回答。
  2. 三个词描述它应有的感觉,或者一个他们欣赏的网站。
  3. 任何固定内容:品牌色、Logo、字体、仅支持浅色或深色模式。
  4. 最重要的页面类型:营销页、应用页、内容页还是商店页。

2. 撰写概要

将答案规范化为 .design-preview/brief.json:

{
  "product": "Ledgerline,面向自由开发者的发票工具",
  "audience": "个人开发者和小型工作室",
  "product_type": "product-type.saas",
  "moods": ["精确", "冷静", "可信赖"],
  "page_type": "marketing",
  "constraints": {"brand_colors": ["#154d8c"], "fonts": [], "scheme": "both"},
  "admired": ["https://linear.app"],
  "words": {"name": "Ledgerline", "tagline": "与你的 Git 日志相匹配的发票"}
}

使用 recommend.py --list product-types 和 --list moods 将自由文本映射到节点 ID。未知词语也可以;推荐器会通过别名和令牌重叠进行回退。自由文本在 product_type 中也是允许的。

3. 撰写文案,然后在一分钟内打开预览

首先编写 .design-preview/copy.json;这只需要一条简短回复,它能让草稿读起来像是产品本身而不是模板。使用产品自己的名词:导航是它的部分,功能是它做的事情,标题是用户会重复的主张。

{
  "headline": "501、Cricket 和 Around the Clock 的实时比分",
  "subhead": "Oche 负责计分,让玩家可以继续玩。",
  "lead": "专为酒吧联赛玩家和在家朋友打造。",
  "cta_primary": "新游戏", "cta_secondary": "继续",
  "nav": ["游戏", "玩家", "统计", "设置"],
  "features": [{"title": "501 和 301 含结算路线", "body": "每个剩余分数都显示标准结算路线。"}],
  "proof": "", "meta": {"city": "利兹", "year": "2026"},
  "footer": "Oche 负责计分。"
}

然后运行一条命令:

python3 <skill>/scripts/quick_start.py --brief .design-preview/brief.json --copy .design-preview/copy.json --count 5 --open

它会推荐组合,编写 directions.json,构建预览并启动服务器。立即给开发者 URL。如果省略 --copy,草稿会使用从概要自身名词派生的文案;永远不要这样呈现一个方向作为已完成。在他们查看的同时完善 directions.json(名称、理由、布局、方案),并重新构建;页面会刷新到同一个 URL。

每个预览页面在其工具栏中都带有三个生成器,因此开发者永远不必返回以获取更多内容:给我惊喜(随机组合的方向:未使用的样式、合适的调色板和配对、想法的随机抽取、部分和方案)、变体(他们当前查看的方向的五种变体:相同的样式、其他调色板、配对、想法和方案)以及,在图库页面上,显示所有样式(针对此概要的每个样式一个方向)。每个生成器都会跳转到新的草稿,该草稿带有相同的按钮。从终端运行: random_direction.py --directions .design-preview/directions.json --build .design-preview [--like B | --all]。

3a. 手动候选组合

python3 <skill>/scripts/recommend.py --brief .design-preview/brief.json --count 4

每个组合都是一个样式、调色板、字体配对、组件处理、动效模式、图标集以及 8 到 12 个设计理念(ideas:有源头的移动,例如带有实时时间的拆分导航、标本英雄、巨大数字、胶片颗粒、支架按钮、版权页页脚),以及证明其合理性的图边和用于交换的实时替代方案。强制多样性:不同的样式系列,最多两个同一温度调色板,最多两个同一类型类别的配对,没有调色板或配对使用两次。默认情况下为 3 到 5 个组合,当开发者要求查看更多时最多可达 8 个。不要低于 3 个;如果概要很窄(仅深色模式,一个品牌色),请说明情况但仍显示三个。

4. 编写 directions.json

将组合转换成 .design-preview/directions.json(模式在 knowledge/schema.json 中,files.directions)。为每个方向提供脚本无法提供的内容:

  • name:一个想法,而不是一个样式("Ledger","Greenhouse","Night shift")。永远不要用 "Modern" 或 "Clean"。
  • rationale:一个段落,引用概要自己的话语,说明为什么这个方向回答了它们。提及一个大胆的选择以及什么保持低调。
  • copy:来自概要的真实文案:标题、副标题、两个行动号召、四个导航标签、三到六个功能(每个带标题和一句话说明)、一个诚实的证明行(或为空)、一个表单标题(包含字段标签和提交文本)、一个页脚行。句子大小写,主动语态,产品名词,没有破折号,没有表情符号,没有箭头,没有 "无论你是 X 还是 Y",没有三连击,没有 Lorem Ipsum,没有虚构的数字。文案在各个方向之间是相同的,除非某个方向的语气确实不同。
  • layout(可选):覆盖部分变体;否则由方向的想法和样式默认值选择。
  • bundle.ideas(保留或编辑):推荐器附加的想法。删除一个不适合产品的想法,当概要或受钦佩的网站要求时,从 recommend.py --list ideas 中添加一个。带有渲染钩子的想法会改变草稿;其余的想法会进入合约。
  • copy.numbers 和 copy.stats(可选):有来源的数据 {value, label, source};只有当这些存在时才渲染数字英雄和统计墙,绝不使用虚构的数据。
  • copy.meta(可选):{"city": "里斯本"},用于拆分导航、版权页和叠加时钟。
  • 产品类型带有一个主题工具包(艺术作品种类、主题组件,例如终端、余额、时间表、合成器、记分板以及产品的名词)。第一个屏幕及其后的部分会使用它,因此记分板会显示分数,商店会显示产品。将 layout.topic 设置为 none 以删除主题组件。
  • overrides(可选):{"brand_primary": "#hex", "brand_accent": "#hex"},当概要固定了品牌色时。构建器会重新计算对比色并报告任何对比度失败。

在构建之前,针对 references/anti-patterns.md 中的反模式检查对每个方向运行检查。除非概要明确要求,否则拒绝该反模式,并在理由中说明。

第一个屏幕规则:没有一个方向以通用模板开头(居中标题、两个按钮、一个截图,然后是三个相同的卡片)。每个样式都默认为从受钦佩的网站上观察到的布局原型(带标题数据的陈述段落、围绕平面光盘的排版、产品优先阶段、显示字体与物体并排、全出血艺术、侧边栏索引、海报类型)以及从调色板生成的艺术品(蓝图、等距图形、终端、瑞士构图、轮廓、半色调、轨道环、贴纸、火花线、单个标记)。保留这些默认值,除非概要明确要求熟悉的样式。至少有 2 个方向来自标记为 distinct 的样式;推荐器强制执行此操作,并且还确保没有两个方向共享导航设备、第一个屏幕设备或纹理。

5. 构建并打开预览

python3 <skill>/scripts/build_preview.py --directions .design-preview/directions.json
python3 <skill>/scripts/serve_preview.py --dir .design-preview --open

build_preview.py 写入 .design-preview/:一个图库,以及为每个方向提供的样式瓷砖(两种模式下的调色板(含对比度等级)、类型刻度、间距、半径、高程、图标、每种状态下的每个组件、可播放的动效模式)、针对概要页面类型起草的页面,以及设备视图,该视图将草稿渲染在 CSS 绘制的框架内,这些框架代表最流行的手机、折叠屏、平板电脑和笔记本电脑的实际视口大小。每个页面上的控件可以实时切换调色板、字体配对、半径、密度、动效级别和主题。

serve_preview.py 启动一个分离的 localhost 服务器,写入 .design-preview/server.json,打印 URL 并立即返回。为离线会话添加 --vendor-fonts 到构建中;否则当 Web 字体加载失败时,瓷砖会显示可见通知。

如果浏览器无法打开(SSH、容器、CI),则打印 URL 和每个方向的一行说明,并继续在聊天中进行。

6. 告知开发者,然后等待

说明你构建了什么,给出 URL,用一行说明命名每个方向,然后停止。不要替他们选择,不要开始编码,不要轮询。开发者可能会在预览中花费很长时间。当他们回复时:

  • 如果 .design-preview/selection.json 存在,则读取它。它包含方向 ID 和他们最终选择的实时覆盖项(调色板、字体配对、半径、密度、动效、主题)。
  • 否则,从他们的话中确定选择("B"、"那个深色的"、"A 但是用 D 的字体")并自己编写 selection.json,并包含匹配的覆盖项。
  • 对于变异("B 但更暖"、"减少圆角"、"替换标题字体"),编辑 directions.json(或使用组合中的替代方案),重新构建,并将他们指回同一个 URL。服务器保持运行;让他们刷新页面。
  • 对于 "显示更多",使用 --count 5 或更改后的概要重新运行 recommend.py,在新区块 ID 下添加新方向,然后重新构建。

serve_preview.py --dir .design-preview --wait 1800 会阻塞直到选择存在,仅用于脚本化使用。--status 和 --stop 用于管理服务器。

7. 导出合约

python3 <skill>/scripts/export_design.py --selection .design-preview/selection.json \
  --directions .design-preview/directions.json --project .

这会写入 design/DESIGN.md(合约:身份、带有来源和构建说明的设计理念、包含对比度表的调色板、排版、间距和半径、高程、布局、每种状态下的每个组件及其令牌、动效令牌和允许的模式、图标设计、图像设计、写作风格、无障碍基线、设备检查以及一份“禁止”列表)、design/tokens.json(W3C 设计令牌格式)、design/tokens.css、design/tailwind.css(当检测到 Tailwind v4 时)、CLAUDE.md 中的指针行,以及 .design-preview/ 的 .gitignore 条目。重新导出会保留“项目说明”部分,并将以前文件复制到 design/history/。

用一条简短消息确认写入的内容以及开发者应该提交的内容(design/ 和 CLAUDE.md 行)。然后根据合约进行构建。

移交后

每当 design/DESIGN.md 存在时:

  • 在任何 UI 更改之前读取它。在组件中使用来自 design/tokens.css 的 --pf-* 令牌,永远不要使用原始十六进制、像素或毫秒值。
  • 坚持允许的动效模式和动效级别。尊重减少动效的偏好。
  • 在每个新的颜色对上运行 contrast.py FG BG --role body|label|large|ui。
  • 遵循“禁止”列表;当请求与合约冲突时,说明情况并提供重新运行此阶段的选项,而不是默默偏离。
  • 在构建完一个重要的页面后,提供设备检查:打开 .design-preview/<id>/devices.html?url=http://localhost:PORT/path 以在相同框架中查看真实页面。无法显示发送了阻止框架的标头的页面;请说明原因。
  • 保留 design/DESIGN.md 中的空闲部分(在结束标记下方)用于项目决策。

导入

要将项目当前外观或开发者钦佩的网站作为方向进行比较:

python3 <skill>/scripts/import_direction.py --css src/styles.css --into .design-preview/directions.json --name "Today"
python3 <skill>/scripts/import_direction.py --tailwind tailwind.config.js --into .design-preview/directions.json
python3 <skill>/scripts/import_direction.py --tokens design-tokens.json --into .design-preview/directions.json
python3 <skill>/scripts/import_direction.py --url https://example.com --into .design-preview/directions.json --name "Reference"

导入会导出一个调色板、字体配对和最接近的样式,然后重新构建。导入的调色板会像其他调色板一样被检查;失败会显示在瓷砖中。

知识与刷新

决策来自 knowledge/graph.json:样式、调色板(OKLCH,两种模式)、字体配对、组件处理、动效模式、产品类型、情绪、图标集、平台特性、参考网站,通过加权的 pairs_with、suits、avoid_with、requires、ex 连接...

相关技能