首页
/ impeccable document 深度指南:用 DESIGN.md 固化当前视觉系统,让 AI 生成的新界面永远保持品牌一致

impeccable document 深度指南:用 DESIGN.md 固化当前视觉系统,让 AI 生成的新界面永远保持品牌一致

2026-09-08 20:05:30作者:齐冠琰

在设计交付链路里,最容易被 AI 代理"跑偏"的环节,是它看不到你已有的视觉系统。impeccable 的 document 命令解决的就是这个问题:它扫描项目代码,把当前真实存在的颜色、字体、圆角、间距与组件模式自动抽取出来,写成一个位于项目根目录、遵循官方 DESIGN.md 格式规范的 DESIGN.md 文件,并用两轮结构化提问补齐无法自动抽取的定性语言(氛围、色彩性格、创意北极星)。读完本文,你将掌握 DESIGN.md 的完整 token schema 与八段式正文规范、Scan/Seed 双模式的完整操作流程、.impeccable/design.json sidecar 的组件翻译规则,以及 impeccable 源码中解析与消费这份文件的真实机制,能够在任何已有代码或全新项目上产出"AI 可直接遵循"的品牌化设计规范。

DESIGN.md 是什么:把视觉系统"碳化"成机器可读规范

DESIGN.md 是放在项目根目录的一份设计系统记录文件。它的核心目的(也是 document 命令的存在理由)是:当 AI 代理生成新界面时,有一个权威的、可被工具解析的品牌约束来源。impeccable 在 command-metadata.json 中对 document 命令的定位是:"Generate a DESIGN.md file that captures the current visual design system. Auto-extracts colors, typography, spacing, radii, and component patterns from the codebase, then asks the user to confirm descriptive language for atmosphere and color character. Follows the Google Stitch DESIGN.md format so the file is tool-compatible."

文件遵循官方 DESIGN.md 格式规范,整体结构为两部分:

  • 可选的 YAML frontmatter:携带机器可读的设计 token(颜色、字体、圆角、间距、组件);
  • 最多八个固定顺序的 Markdown 小节:为 token 提供应用语境的散文说明。

两条铁律贯穿始终:Tokens are normative(token 是规范性的)——prose 只是解释怎么用它们;小节可以不写(不相关就省略),但写了的必须保持规定顺序,且必须使用规范标题,以保证文件在各类 DESIGN.md-aware 工具间可移植。

这一设计在源码里体现得非常直接。impeccable 的 Rust 工作区至少有三处独立实现了对这份文件的消费:

  • crates/context/src/design_parser.rs:doctor 覆盖度检查使用的解析器,解析 frontmatter(YAML 子集)并检测 canonical H2 段落;
  • crates/live/src/design_md.rs:live 服务器把完整的解析模型以 /design-system.jsonparsed 字段交给设计面板渲染,目标是字节级对齐 JS 实现(JSON.stringify(parseDesignMd(md)));
  • crates/detect/src/design_system.rs:把 DESIGN.md 归一化成"允许的设计系统"(允许的字体、颜色、圆角、字号),作为静态/动态设计检查的 allowlist。

换句话说,DESIGN.md 不是一份给人看的说明书,而是一份同时被 lint 器校验、被 live 面板渲染、被设计检查消费的活数据。这就是为什么本文后面反复强调"不要重命名小节""不要发明 schema 之外的 token 组"——那会让这些解析器直接失配。

frontmatter:机器可读的 token schema

frontmatter 是文件的机器可读层,也是 Stitch linter 校验、live 面板渲染 tile 的数据来源。原则是"保持精简":每一条目都必须对应项目实际使用的 token。schema 的完整形态如下:

---
name: <project title>
description: <one-line tagline>
colors:
  primary: "#b8422e"
  neutral-bg: "#faf7f2"
  # ...one entry per extracted color; key = descriptive slug
typography:
  display:
    fontFamily: "Cormorant Garamond, Georgia, serif"
    fontSize: "clamp(2.5rem, 7vw, 4.5rem)"
    fontWeight: 300
    lineHeight: 1
    letterSpacing: "normal"
  body:
    # ...
rounded:
  sm: "4px"
  md: "8px"
spacing:
  sm: "8px"
  md: "16px"
components:
  button-primary:
    backgroundColor: "{colors.primary}"
    textColor: "{colors.neutral-bg}"
    rounded: "{rounded.sm}"
    padding: "16px 48px"
  button-primary-hover:
    backgroundColor: "{colors.primary-deep}"
---

五条必须遵守的规则:

  • Token 引用{path.to.token} 语法(如 {colors.primary}{rounded.md})。组件可以引用原始 token;原始 token 之间不能互相引用。
  • 颜色接受任何合法 CSS 颜色字符串。默认推荐 hex(可移植性最好),但当项目现状以 rgb()hsl()oklch()、广色域或混合格式为规范来源时,应保留现状——没有明确理由就不要拆分"唯一事实来源"
  • 组件子 token 只有 8 个属性backgroundColortextColortypographyroundedpaddingsizeheightwidth。阴影、动效、焦点环、backdrop-filter 都放不进去,这些要放进 sidecar(见 Step 4b)。
  • 刻度键名是开放的:直接用项目已有的命名(oxblood-deepsurface-container-low),不要改写成 Material 默认名。
  • 变体是命名约定,不是 schemabutton-primary / button-primary-hover / button-primary-active 作为同级键存在即可。

值得注意的是,这个 frontmatter 并不是标准 YAML 全集。从 crates/live/src/design_md.rscrates/detect/src/design_system.rs 的实现看,impeccable 解析的是缩进驱动的嵌套 map + 标量子集:支持双引号/单引号字符串及转义(含 \x\u\U 十六进制转义)、布尔、null、整数与浮点、行内注释剥离;注释行(# 开头)会被跳过。这也解释了为什么文档建议键名用描述性 slug——解析器对键不做规范化,键就是 token 在系统里的身份。

Markdown 正文:八个 canonical section(固定顺序)

frontmatter 之下是正文,最多八个小节,顺序不可调换:

  1. ## Overview
  2. ## Colors
  3. ## Typography
  4. ## Layout
  5. ## Elevation & Depth
  6. ## Shapes
  7. ## Components
  8. ## Do's and Don'ts

不相关的小节直接省略,而不是硬塞发明出来的规则。内容放置有明确分工:响应式布局放 Layout,深度放 Elevation & Depth,圆角与造型语言放 Shapes,组件行为放 Components。规范允许保留未知小节,但新的视觉指导只要放得下,就应该用 canonical 结构。

"固定顺序 + 精确标题"不是洁癖,而是机器契约。看源码中的 CANONICAL_SECTIONS 常量:

doctor 的覆盖度检查据此判定一份 DESIGN.md 缺了哪些 section;live 面板据此渲染。更关键的是 design_parser.rsmatch_canonical_section 会做容错模糊匹配——## Colors 能匹配,## Color Palette & Roles 也大概率能通过正则兜底匹配到 Colors。这意味着"不要用近义词替换 canonical 标题"(文档 Pitfalls 第 6 条)背后的真实风险是:模糊匹配可能让你以为的"自定义标题"被静默归并到某个 canonical section,打乱工具的渲染与校验预期。文档的原话是:"Tooling parsing depends on exact headers"——解析器依赖精确标题,请一字不差。

何时运行 document

document 的触发时机是四类明确场景:

  • new-work 发现项目已有连贯的既有视觉系统,但没有 DESIGN.md
  • 新世界(visual world)的首次实现完成,临时的设计决策需要被"碳化"(carbonized)为规范;
  • 已有的 DESIGN.md 过时了(设计已经漂移);
  • 大规模重设计之前,先把当前状态留档作为参照。

一个贯穿始终的红线:如果 DESIGN.md 已存在,绝不静默覆盖。先把现有文件展示给用户,无法推断的内容直接问用户,由用户在 refresh(刷新)、overwrite(覆盖)、merge(合并)三者之间选择。

两条路径:Scan mode 与 Seed mode

document 有两条执行路径:

  • Scan mode(默认):项目已有设计 token、组件或渲染产物。先抽取,再确认描述性语言。有代码可分析时使用
  • Seed mode:项目尚在实现之前。确保 PRODUCT.md 存在,然后复用 new-work 的视觉世界工作坊,写一份方向性的 DESIGN.md 种子;等有代码后再以 Scan mode 重跑。

决策方式是"先扫再说":先走 Scan mode 的 Step 1。如果扫描发现既没有 token、没有组件文件、也没有渲染站点,就主动提供 seed mode,而不是静默切换/impeccable document --seed 会请求 new-work 的世界工作坊,但它不授权替换连贯的既有代码:当既有系统存在时,应提供 scan mode,或把明确的"身份替换"请求路由给 new-work。

Scan mode 实操:五步产出品牌化设计规范

Scan mode 的完整方法论是"approach C:自动抽取,然后确认描述性语言"。下面按步骤展开,并标注源码侧的对应机制。

Step 1:按优先级查找设计资产

按以下优先级在代码库中搜索,记录每个 token 的名称、值、定义文件

  1. CSS 自定义属性:在 CSS 文件中 grep --color---font---spacing---radius---shadow---ease---duration- 声明(通常在 src/styles/public/css/app/globals.css 等位置);
  2. Tailwind 配置:存在 tailwind.config.{js,ts,mjs} 时,读取 theme.extend 里的 colors、fontFamily、spacing、borderRadius、boxShadow;
  3. CSS-in-JS 主题文件:styled-components、emotion、vanilla-extract、stitches,找 theme.tstokens.ts 或等价物;
  4. 设计 token 文件tokens.jsondesign-tokens.json、Style Dictionary 产物、W3C token community group 格式;
  5. 组件库:扫描主要 button、card、input、navigation、dialog 组件,记录变体 API 与默认样式;
  6. 全局样式表:根 CSS 文件通常承载基础字体与颜色分配;
  7. 可见的渲染产物:若有浏览器自动化工具,加载线上站点,对关键元素(body、h1、a、button、.card)采样计算样式——这能捕获 token 没覆盖到的值。

源码侧,impeccable 对 DESIGN.md 本身的"查找"机制在 crates/detect/src/design_system.rsresolve_design_md_path:先查当前目录的 DESIGN.md/Design.md/design.md,再按 FALLBACK_DIRS.agents/contextdocs)兜底,并以 .gitpackage.json.impeccable 作为项目根边界标记(PROJECT_ROOT_MARKERS)向上回溯。也就是说,document 生成的 DESIGN.md 会沿着项目边界向上被发现,子项目可以继承根项目的设计系统——这与 init.md 中"PRODUCT.md 路径由 impeccable context 解析、子应用继承根上下文"的模型一致。

Step 2:自动抽取可自动抽取的内容

基于发现的 token 构建结构化草稿,按 token 类别处理:

  • Colors:归组为 Primary / Secondary / Tertiary / Neutral(Stitch 使用的 Material 衍生角色)。项目只有一个强调色时,表达为 Primary + Neutral;不存在的 Secondary 和 Tertiary 就省略,绝不发明
  • Typography:把观察到的字号字重映射到 Material 层级(display / headline / title / body / label),记录字体栈与比例关系;
  • Elevation:盘点阴影词汇表。如果项目是扁平风、用色调分层代替阴影,那同样是一个有效答案,要明确写出来
  • Components:对每个常见组件(button、card、input、chip、list item、tooltip、nav)抽取圆角、配色、hover/focus 处理、内边距;
  • Layout + spacing:把网格、容器、断点、节奏、密度行为抽进 Layout;
  • Shapes:把圆角、边角、边框、裁剪与反复出现的造型行为抽进 Shapes。

Step 2b:暂存 frontmatter

立即从自动抽取结果草拟 YAML frontmatter(Step 4 会写到文件顶部)。这是 live 面板和 Stitch linter 消费的机器可读层:

  • Colors:每个抽取的颜色一条,键 = 描述性 slug(oxblood-deepeditorial-magenta,而不是 blue-800),值 = 项目视为规范来源的格式(OKLCH 或 hex)。不拆分唯一事实来源:frontmatter 用一种格式,不要在 prose 里用不同值重复定义同一 token;
  • Typography:每个角色一条(displayheadlinetitlebodylabel)。Typography 是对象,只包含项目真实用到的属性(fontFamilyfontSizefontWeightlineHeightletterSpacingfontFeaturefontVariation);
  • Rounded / Spacing:项目实际使用的刻度步进,键用项目自己的刻度名(sm/md/lg,或 surface-sm,或数字步进);
  • Components:每个变体一条(button-primarybutton-primary-hoverbutton-ghost),通过 {colors.X}{rounded.Y} 引用原始 token。若某个变体需要 Stitch 8 属性之外的属性(阴影、焦点环、backdrop-filter),把完整片段放进 sidecar。

项目没有的东西全部跳过。空的刻度键、捏造的 token 都会污染规范("Empty scale keys or fabricated tokens pollute the spec")。

从源码看,frontmatter 里的 token 会被 normalize_design_systemcrates/detect/src/design_system.rs)直接转换成设计检查的 allowlist:typography 里的 fontFamily 经 split_font_stack 拆分出 allowed_fonts;字号(含 clamp() 的端点)进 allowed_font_sizescolors 与 sidecar 的 colorMeta.canonical/tonalRampallowed_color_keysrounded 刻度进 allowed_radii(名字含 full/pill/round/rounded-full 的还会置 has_pill_radius)。所以 frontmatter 写得越贴实,后续设计检查的误报越少。

Step 3:用两轮提问收集定性语言

以下内容无法自动抽取,必须询问用户。分两轮、每轮不超过三个问题(或取 harness 允许的下限),轮与轮之间等待回答:

  • 创意北极星(Creative North Star):整个系统的一个具名隐喻("The Editorial Sanctuary"、"The Golden State Curator"、"The Lab Notebook")。给出 2-3 个尊重 PRODUCT.md 品牌人格的选项;
  • Overview 语气:情绪形容词、2-3 句美学哲学、以及确认过的视觉反参照(anti-reference);
  • 色彩性格(针对已抽取的颜色):描述性命名("Deep Muted Teal-Navy",不是 blue-800)。基于色相/饱和度给每个关键色建议 2-3 个选项;
  • 层级哲学(Elevation philosophy):flat / layered / lifted。若存在阴影,其角色是环境光(ambient)还是结构性的(structural);
  • 组件哲学:用一句话概括按钮、卡片、输入框的质感("tactile and confident"对比"refined and restrained")。

只有当 PRODUCT.md 中的某句话是确实约束视觉系统的持久品牌承诺时才搬进 DESIGN.md;页面策略与 surface 概念不属于这里。

Step 4:撰写 DESIGN.md

文件以 Step 2b 暂存的 frontmatter 开头,正文用下面的 canonical 结构:

---
name: [Project Title]
description: [one-line tagline]
colors:
  # ... staged frontmatter from Step 2b
---

# Design System: [Project Title]

## Overview

**Creative North Star: "[Named metaphor in quotes]"**

[2-3 paragraph holistic description: personality, density, and aesthetic philosophy. Start from the North Star and work outward. State only confirmed visual rejections. End with a short **Key Characteristics:** bullet list.]

## Colors

[Describe the palette character in one sentence.]

### Primary
- **[Descriptive Name]** (#HEX / oklch(...)): [Where and why this color is used. Be specific about context, not just role.]

### Secondary (optional; omit if the project has only one accent)
- **[Descriptive Name]** (#HEX): [Role.]

### Tertiary (optional)
- **[Descriptive Name]** (#HEX): [Role.]

### Neutral
- **[Descriptive Name]** (#HEX): [Text / background / border / divider role.]
- [...]

### Named Rules (optional, powerful)
**The [Rule Name] Rule.** [Short, forceful prohibition or doctrine, e.g. "The One Voice Rule. The primary accent is used on ≤10% of any given screen. Its rarity is the point."]

## Typography

**Display Font:** [Family] (with [fallback])
**Body Font:** [Family] (with [fallback])
**Label/Mono Font:** [Family, if distinct]

**Character:** [1-2 sentence personality description of the pairing.]

### Hierarchy
- **Display** ([weight], [size/clamp], [line-height]): [Purpose; where it appears.]
- **Headline** ([weight], [size], [line-height]): [Purpose.]
- **Title** ([weight], [size], [line-height]): [Purpose.]
- **Body** ([weight], [size], [line-height]): [Purpose. Include max line length like 65–75ch if relevant.]
- **Label** ([weight], [size], [letter-spacing], [case if uppercase]): [Purpose.]

### Named Rules (optional)
**The [Rule Name] Rule.** [Short doctrine about type use.]

## Layout

[Describe the grid or spatial model, container behavior, density, responsive changes, and the spacing rhythm. Include exact values only when observed.]

## Elevation & Depth

[One paragraph: does this system use shadows, tonal layering, or a hybrid? If "no shadows", say so explicitly and describe how depth is conveyed instead.]

### Shadow Vocabulary (if applicable)
- **[Role name]** (`box-shadow: [exact value]`): [When to use it.]
- [...]

### Named Rules (optional)
**The [Rule Name] Rule.** [e.g. "The Flat-By-Default Rule. Surfaces are flat at rest. Shadows appear only as a response to state (hover, elevation, focus)."]

## Shapes

[Describe the form language: corner/radius strategy, borders, clipping, and any recurring silhouette or geometry.]

## Components

For each component, lead with a short character line, then specify shape, color assignment, states, and any distinctive behavior.

### Buttons
- **Shape:** [radius described, exact value in parens]
- **Primary:** [color assignment + padding, in semantic + exact terms]
- **Hover / Focus:** [transitions, treatments]
- **Secondary / Ghost / Tertiary (if applicable):** [brief description]

### Chips (if used)
- **Style:** [background, text color, border treatment]
- **State:** [selected / unselected, filter / action variants]

### Cards / Containers
- **Corner Style:** [radius]
- **Background:** [colors used]
- **Shadow Strategy:** [reference Elevation section]
- **Border:** [if any]
- **Internal Padding:** [scale]

### Inputs / Fields
- **Style:** [stroke, background, radius]
- **Focus:** [treatment, e.g. glow, border shift, etc.]
- **Error / Disabled:** [if applicable]

### Navigation
- **Style, typography, default/hover/active states, mobile treatment.**

### [Signature Component] (optional; if the project has a distinctive custom component worth documenting)
[Description.]

## Do's and Don'ts

Concrete visual guardrails grounded in the incumbent implementation or the user's chosen world. Lead each with "Do" or "Don't" and include exact values only when established. Do not turn a task-specific concept or surface strategy into a system-wide prohibition.

### Do:
- **Do** [specific prescription with exact values / named rule].
- **Do** [...]

### Don't:
- **Don't** [specific prohibition confirmed by the incumbent system or the user].
- **Don't** [...]
- **Don't** [...]

文档强调 Do's and Don'ts 要"以既有实现或用户选择的世界为依据":不要把某个任务的特定概念或 surface 策略升级成系统级禁令。这一节的 bullets 会被 live 面板原样展示,是整个文件的"护栏"部分。

Step 4b:撰写 .impeccable/design.json sidecar(扩展项)

frontmatter 拥有 token 原始值(colors、typography、rounded、spacing、components);sidecar 位于 .impeccable/design.json,承载 Stitch schema 装不下的内容:每种颜色的色调阶梯(tonal ramp)、阴影/层级 token、动效 token、断点、完整组件 HTML/CSS 片段(面板把它们渲染进 shadow DOM),以及叙述性内容(north star、rules、do's/don'ts)。它扩展 frontmatter,而不是重复它

每当你重新生成根级 DESIGN.md,都必须同步重新生成 sidecar。 如果用户只要求刷新 sidecar(例如 live 面板提示 stale),则保留 DESIGN.md,只写 .impeccable/design.json

完整的 schema 如下:

{
  "schemaVersion": 2,
  "generatedAt": "ISO-8601 string",
  "title": "Design System: [Project Title]",
  "extensions": {
    "colorMeta": {
      "primary":        { "role": "primary",  "displayName": "Editorial Magenta", "canonical": "oklch(60% 0.25 350)", "tonalRamp": ["...", "...", "..."] },
      "cool-paper": { "role": "neutral",  "displayName": "Cool Paper",    "canonical": "oklch(96% 0.005 230)", "tonalRamp": ["...", "...", "..."] }
    },
    "typographyMeta": {
      "display": { "displayName": "Display", "purpose": "Hero headlines only." }
    },
    "shadows": [
      { "name": "ambient-low", "value": "0 4px 24px rgba(0,0,0,0.12)", "purpose": "Diffuse hover glow under accent elements." }
    ],
    "motion": [
      { "name": "ease-standard", "value": "cubic-bezier(0.4, 0, 0.2, 1)", "purpose": "Default easing for state transitions." }
    ],
    "breakpoints": [
      { "name": "sm", "value": "640px" }
    ]
  },
  "components": [
    {
      "name": "Primary Button",
      "kind": "button | input | nav | chip | card | custom",
      "refersTo": "button-primary",
      "description": "One-line what and when.",
      "html": "<button class=\"ds-btn-primary\">SAVE CHANGES</button>",
      "css": ".ds-btn-primary { background: #191c1d; color: #fff; padding: 16px 48px; letter-spacing: 0.05em; text-transform: uppercase; font-weight: 500; border: none; border-radius: 0; transition: background 0.2s, transform 0.2s; } .ds-btn-primary:hover { background: oklch(60% 0.25 350); transform: translateY(-2px); }"
    }
  ],
  "narrative": {
    "northStar": "The Editorial Sanctuary",
    "overview": "2-3 paragraphs of the philosophy, pulled from DESIGN.md Overview section.",
    "keyCharacteristics": ["...", "..."],
    "rules": [{ "name": "The One Voice Rule", "body": "...", "section": "colors|typography|elevation" }],
    "dos":   ["Do use ..."],
    "donts": ["Don't use ..."]
  }
}

从 schemaVersion 1 到 2 改了什么。 旧版 sidecar 携带 token 原始值数组(tokens.colors[]tokens.typography[] 等);这些值现在归 frontmatter 所有。sidecar 只保留 frontmatter 装不下的元数据(tonal ramp、当 hex 只是近似值时的 canonical OKLCH、显示名、角色提示),并以 frontmatter token 名为键(colorMeta.<token-name>typographyMeta.<token-name>)。组件仍携带完整 HTML/CSS,因为 Stitch 的 8 属性集装不下它们。

组件翻译规则(Component translation rules)

htmlcss 字段必须是自包含、可直接注入的片段,被注入 shadow DOM 后就能正确渲染。面板直接应用它们:无后处理、无框架运行时。六条硬规则:

  1. Tailwind 展开:源使用 Tailwind(如 className="bg-primary text-white rounded-lg px-6 py-3")时,把每个工具类展开为 css 字符串里的字面 CSS 属性。不要引用 Tailwind 类,不要假设 Tailwind CSS 包已加载——每个组件自包含;
  2. Token 解析:若项目把 token 暴露为 :root 上的 CSS 自定义属性(如 --color-primary--radius-md),用 var(--color-primary) 引用,它们会穿透 shadow DOM 继承并保持实时绑定;若 token 只存在于 JS 主题对象(styled-components、CSS-in-JS),则在生成时解析为字面值;
  3. 图标内联为 SVG:不要引用 Lucide/Heroicons 包、图标字体或 <img src="...">。典型图标 16-24px,直接复制 SVG path 数据;
  4. 包含状态:内联 :hover:focus-visible,有意义的再加 :active。只有默认态的静态快照会让面板"死气沉沉";
  5. 去重置噪音:只抽取组件有辨识度的 CSS(背景、颜色、内边距、圆角、字体、过渡)。跳过通用 reset(box-sizing: border-boxline-height: inherit-webkit-font-smoothing)——面板已有中性画布;
  6. 类名加 ds- 前缀:所有类前缀 ds-(如 ds-btn-primaryds-input-search),避免同一 shadow DOM 内组件 CSS 互相冲突。

收录范围

目标是一套精简的 5-10 个最能代表视觉系统的组件

  • Canonical 原语(项目有就必收):button(每个变体一条独立记录)、input/text field、navigation、chip/tag、card;
  • Signature 组件(有辨识度就收):真正定义了所实现系统的、反复出现的自定义模式;
  • 其余跳过:工具组件、表单积木、包装布局——除非视觉上有辨识度,否则不值得记录。

如果项目还没有组件库(纯落地页、全新项目),就从 token 出发、依据与 DESIGN.md 规则一致的业界默认值综合出 canonical 原语——即使第零天,.impeccable/design.json 也必须有可渲染的东西

Tonal ramps(色调阶梯)

为每个颜色 token 生成 8 步 tonalRamp 数组:从深到浅、保持同一色相与彩度,明度从约 15% 步进到约 95%。面板把它渲染成色块下方的色带。如果项目已定义色阶(Material 的 surface-container-low 家族、Tailwind 风格 blue-50..blue-900),直接用;否则在 OKLCH 中合成。

Narrative mapping(叙述映射)

直接从刚写好的 DESIGN.md 提取,不得改写措辞(面板把它作为可折叠的次级上下文展示,Markdown 里的语气必须原样延续):

  • narrative.northStar ← Overview 中的 **Creative North Star: "..."** 行;
  • narrative.overview ← Overview 的哲学段落;
  • narrative.keyCharacteristics**Key Characteristics:** 项目符号列表;
  • narrative.rules ← 全文每个 **The [Name] Rule.** [body],带 section 标签;
  • narrative.dos / narrative.donts ← Do's and Don'ts 的逐条列表,原样。

Step 5:确认与细化

  1. 向用户展示完整 DESIGN.md,点出非显而易见的创意选择(描述性颜色名、氛围语言、named rules);
  2. 说明 .impeccable/design.json 也已一并写出——live 面板此后渲染的是项目真实的 button/input/nav 原语,而非通用近似物;
  3. 主动提供细化入口:"Want me to revise a section, add component patterns I missed, or adjust the atmosphere language?"

最后一句提醒很实用:你自己刚写的内容就是最新来源,本会话后续命令无需重新加载

Seed mode:实现前的方向性种子

Seed mode 面向还没有可抽取视觉系统的项目。它产出的是用户选定的视觉世界脚手架,不是凭空捏造的 token 规范

Step 1:路由到 new-work 的工作坊

PRODUCT.md 是前置条件。缺失时,先加载 init.md 完成产品访谈(init 捕获的是持久产品事实,不发明视觉世界、不写 DESIGN.md;document 记录的是既有系统——两条链路的分工见 init.md 开头说明)。没有持久的产品上下文,就不要创造视觉身份。

PRODUCT.md 存在时,加载 new-work.md 解决视觉权威问题。Seed mode 需要一个具体的第一界面(first surface):用用户指定的目标,或询问用户想先做什么。运行 new-work 的 Create or replace the visual world 流程,再运行 Commit the world,让视觉世界与它的第一次表达被一起选定。在方向性 DESIGN.md seed 与 surface brief 之后停下来,不要实现。结构化模拟用户同样算用户,必须得到同样的选择权。

如果 new-work 在本会话已完成工作坊,直接用其选定的方向,不要重复提问。

Step 2:撰写 seed DESIGN.md

沿用 Scan mode 的 canonical section 顺序。填入选定的工作坊方向,未解决的实现事实留作诚实的占位符。seed 承诺的是一个世界及其不变量,不是假装实现 token 已经存在。

文件以如下标记开头:

<!-- SEED: established with the user before implementation; re-run /impeccable document once there's code to capture the actual tokens and components. -->

各节在 seed 模式下的写法:

  • Overview:选定的设计论点、布局行为、材质特性、图像立场、动效语法、可复用 signature。所选第一界面的表达留在 surface brief 中,不要把它提升为全局世界;
  • Colors:选定的调色策略与角色。仅当用户、既有资产或 new-work 探索确立了具体值时才写值,否则标 [to be resolved during implementation]
  • Typography:选定的字体角色与角色关系。仅当已确立时才写字体名,否则把配对标为 [to be resolved during implementation]
  • Layout:选定的空间语法与响应式行为,不假装具体度量已定;
  • Elevation & Depth:选定的材质与深度行为,作为不变量陈述,而不是从通用预设推断;
  • Shapes:选定的造型与边角语言;
  • Components:完全省略——尚无组件存在;
  • Do's and Don'ts:记录世界选择时确认的持久护栏,而非任务局部的拒绝项。

Seed 模式只写含 namedescription 的最小 frontmatter——没有 colors、typography、rounded、spacing、components。真实 token 在下一次 Scan mode 运行时落地。同理,Seed 模式跳过 .impeccable/design.json sidecar:没有可渲染的东西。

Step 3:确认

  1. 展示 seed DESIGN.md,明确指出它是 seed(那个标记就是字面承诺);
  2. 告知用户:"Re-run /impeccable document once you have some code. That pass will extract real tokens and generate the sidecar."

风格指南:让规范既精确又可引用

  • Frontmatter 优先,prose 其次。 token 进 YAML frontmatter,prose 做语境化。不要在两处重复定义同一 token 值——frontmatter 是规范来源;
  • 只携带持久的产品约束。 绑定性的 logo、身份资产、可访问性需求或 PRODUCT.md 的品牌承诺可以约束 DESIGN.md;surface 策略留在其 surface brief;
  • 对齐规范。 用八个 canonical section 按序排列,不相关的省略。动效指导放到它影响的世界或组件旁,而不是创建 schema 不支持的 token 组;
  • 描述性 > 技术性:"Gently curved edges (8px radius)" 优于 "rounded-lg"。以描述开头,技术值放括号;
  • 功能性 > 装饰性:对每个 token 解释在哪里、为什么用,而不只是它是什么;
  • 精确值进括号:hex、px/rem、字重——始终把数字放在描述旁;
  • 善用 Named Rules**The [Name] Rule.** [short doctrine]。这类规则对 AI 消费方比项目符号列表更易记忆、可引用、黏性更强("The No-Line Rule"、"The Ghost Border Fallback")。每节 1-3 条;
  • 证据充分处要果断。 对真正的不变量用硬语言,对临时指导用软语言;
  • 审计测试要具体且基于事实。 只有基于观察到系统或已确认用户决策的测试才写;一句测试胜过一段原则;
  • 选择性引用 PRODUCT.md。 产品真相解释世界为何成立,但默认不提供页面构图或视觉禁令清单;
  • 按角色分组颜色,不要按 hex 或色相排序。Primary / Secondary / Tertiary / Neutral 是规范顺序。

常见陷阱:写 DESIGN.md 时最该避开的九件事

  • 不要粘贴原始 CSS 类名,翻译成描述性语言;
  • 不要抽取每个 token,停在真正被复用的部分——一次性值会污染系统;
  • 不要发明不存在的组件。项目只有按钮和卡片,就只记录按钮和卡片;
  • 不要未经询问覆盖已有的 DESIGN.md;
  • 不要重复 PRODUCT.md 的内容——DESIGN.md 严格限定于视觉;
  • 不要用近义词替换 canonical 小节。Layout/响应式进 Layout,动效放在受影响的世界或组件旁;
  • 不要哪怕轻微地重命名小节。"Colors" 不能写成 "Color Palette & Roles","Typography" 不能写成 "Typography Rules"——工具的解析依赖精确标题;
  • 不要在 frontmatter 与 prose 间重复 token 值。颜色在 colors.primary 里是 hex,prose 可以命名它、描述角色,但不应重新断言一个不同的 hex——frontmatter 是规范来源;
  • 不要发明 schema 之外的 frontmatter token 组(顶层不允许 motion:breakpoints:shadows:)。Stitch 的 Zod schema 只接受 colorstypographyroundedspacingcomponents,其余一律进 sidecar 的 extensions

仓库实例:Lumina 落地页的完整 DESIGN.md

上面所有规则的最终形态,可以在仓库自带的真实产物 demos/landing-demo/DESIGN.md 中对照观察。它覆盖了一个 AI 原生工作流工具落地页(项目名 Lumina)的完整设计系统:

  • frontmatter 完整遵循 schemaname/description、8 个描述性 slug 的颜色(creamcream-warmpeachlineinksoftaccentaccent-deep,全部 hex)、6 个 typography 角色(display/headline/title/lede/body/label,含 clamp() 流式字号与负字距)、3 档 rounded(card 20px / icon 14px / pill 999px)、7 档 spacing(8px→120px)、5 个组件变体(button-primary、button-ghost、nav-pill、card、icon-tile),组件通过 {colors.ink}{rounded.pill} 引用原始 token;
  • 正文完整按八个 canonical section 顺序组织(数字前缀 ## 1. Overview 等均被 design_parser.rs 的 H2 正则兼容);
  • Named Rules 密集且可引用:Colors 节的 "The Cream-Family Rule"(任何中性面都向品牌色相靠拢,页面不允许纯白、纯黑、未染色灰)与 "The 10% Accent Rule"(焦橙色占比不超过任何渲染表面的 10%);Typography 节的 "The One-Italic Rule"(斜体每页恰好一次)与 "The No-Gradient-Text Rule";Elevation 节的 "The Flat-By-Default Rule"(静态表面扁平,悬停用 transform 而不是阴影);
  • Elevation 明确陈述"无阴影":用色调分层(cream→cream-warm→ink)、发丝级边框、吸顶导航 backdrop-blur 三种方式传达深度,正好示范了文档要求的"If 'no shadows', say so explicitly";
  • Do's and Don'ts 全部锚定在既有实现与 PRODUCT.md 反参照上:禁止玻璃拟态、霓虹光晕、渐变文字、侧条纹卡片强调色,且明确承认页面本身正是被反参照的 "Fraunces-cream-peach SaaS template"——规范记录现状,品牌意图是逐步远离它。

如果你在自己的项目上运行 /impeccable document,产出结构应与这个样例同构;而 crates/live/src/design_md.rs 会把它解析成设计面板可渲染的模型,crates/detect/src/design_system.rs 会把它归一化成设计检查的 allowlist——一条从"代码现状"到"AI 可遵循的品牌规范"再到"规范反哺检查"的完整闭环就此形成。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
898
5.82 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
531
596
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
921
1.84 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.8 K
1.02 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.36 K
1.46 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.02 K
519
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
548
391