前言
我第一次认真看 Design.md,是因为前端页面被 AI 改散了。
这类问题不一定马上出现在代码层。页面能启动,组件也能渲染,按钮点击以后状态也会变化。麻烦在于多改几轮以后,页面开始不像同一个产品。第一次生成的卡片是 16px 圆角,第二次加弹窗变成 12px,第三次补空状态又带了很重的渐变背景。每一次单独看都能接受,合在一个项目里,风格就开始漂。
人写前端时,会记得自己之前做过什么。哪类按钮用主色,哪类卡片只保留轻阴影,哪些页面不能做得太营销化,这些判断会在脑子里留下痕迹。AI agent 没有这种长期项目记忆,它更依赖当前上下文。你给它一个页面,它会把这个页面改好;你让它跨多个页面保持同一种视觉气质,就需要给它一个能反复读取的设计上下文。
Design.md 正好补的是这个位置。
它把颜色、字体、间距、圆角、组件边界和设计判断写进一个 Markdown 文件里。AI agent 修改页面时,不再只从当前文件里猜项目风格,也能从 Design.md 里读取这个产品应该长什么样、哪些设计效果要克制、哪些组件规则不能随手改。
我现在更愿意把它看成 AI 编程时代的设计约束文件。它不替代 Figma,也不替代代码里的 theme 配置。它负责把那些很难靠变量名表达的设计判断写下来,让 AI 在多轮生成和多次修改中少跑偏。
一、先把风格从 Prompt 里拿出来
很多人让 AI 写前端页面时,会把设计要求直接塞进 Prompt。
比如:
text
页面要简洁、现代、有科技感,使用蓝紫色渐变,卡片圆角,按钮清晰。
这种写法适合一次性生成页面。它的问题也在这里,只对这一次任务有效。下次你让 agent 改设置页,设计要求可能被压缩;再下次让它补空状态,前面的风格描述可能已经不在上下文里。项目越大,Prompt 里的临时约束越容易丢。
Design.md 的思路更接近项目级约束。它把视觉规则从单次 Prompt 里拿出来,放到仓库根目录里。只要 agent 在执行任务前能读取这个文件,页面生成、组件改造、空状态补全、表单重构这些操作都能回到同一套风格描述下。
我会把它和 README.md、AGENTS.md 放在同一层看。
| 文件 | 主要承接内容 | 对 AI agent 的作用 |
|---|---|---|
README.md |
项目定位、启动方式、目录说明 | 让 agent 知道项目怎么跑 |
AGENTS.md |
开发规则、测试命令、提交边界 | 让 agent 知道代码怎么改 |
DESIGN.md |
视觉身份、设计 token、组件边界 | 让 agent 知道页面应该长什么样 |
theme.ts / tailwind.config.ts |
可执行样式变量 | 让样式真正落到代码里 |
这个分工很重要。theme.ts 能统一颜色值,但它不会告诉 AI 主色应该少用。tailwind.config.ts 能统一间距,但它不会告诉 AI 表单页不能被拉得太散。Design.md 处理的就是这些写进代码变量后仍然不够明确的东西。
我在项目里最想避免的情况,是 AI 每次都把局部任务完成了,却一点点改掉产品气质。Design.md 可以先把这个边界收住。
二、token 写数值,正文写取舍
Design.md 最有用的地方,是它没有只做成一份 JSON,也没有只写成纯说明文。它通常会分成两层。
前面是 YAML front matter,适合放机器可读的设计 token。后面是 Markdown 正文,适合写人能理解的设计理由和使用边界。
比如下面这段 token:
yaml
---
name: Indie Builder Dashboard
colors:
primary: "#6D5DF2"
text: "#172033"
muted: "#7A8194"
surface: "#FFFFFF"
background: "#F6F7FB"
radius:
card: 18px
button: 12px
spacing:
xs: 6px
sm: 10px
md: 16px
lg: 24px
---
这段内容能让 agent 知道项目主色、文字色、背景色、圆角和间距。它解决的是数值统一问题。可只给这些值还不够,因为 AI 不一定知道这些值该怎么使用。
主色是用在一个主按钮上,还是用在整张卡片背景上?18px 圆角是给内容卡片,还是所有小标签都要跟着变大?背景色是页面底色,还是可以在每个容器里反复套娃?这些判断不会自动从 token 里长出来。
所以我会在后面的正文里继续写:
markdown
## Overview
这是一个面向独立开发者的产品后台。页面需要保留轻量科技感,但功能页要优先保证信息读取和任务处理。首页可以有少量品牌表达,进入具体功能页以后,界面要回到表格、表单、日志面板和状态卡片。
## Colors
主色用于主要按钮、当前选中状态和少量图标点缀。列表、表单和数据卡片不要大面积使用主色背景。背景保持浅灰,内容卡片使用白色,分割线使用低对比度灰色。
## Components
主按钮只用于当前页面最重要的动作。普通编辑、取消、筛选、导出这类操作使用次级按钮或文本按钮。卡片圆角保持统一,不在同一个页面里混用多套圆角。
这部分 prose 才是 Design.md 真正有价值的地方。它给 AI 的不是某个变量,而是一组取舍。
我在实际使用时会特别重视这些说明。因为 AI 生成页面最容易出问题的地方,往往不是颜色值错了,而是它把一个本来应该安静的工具页做成了营销页,把一个普通列表卡片做成了强调卡片,把一个次要操作做成了主按钮。
token 负责把值统一起来,正文负责告诉 agent 这些值背后的使用方式。两部分放在一起,Design.md 才能真正进入 AI 编程流程。
三、它要贴着组件库走
Design.md 不能孤立存在。它如果只是一份写得很漂亮的说明文件,时间一长就会和代码脱节。真正进入项目后,它应该和组件库、样式变量、页面模板保持对应关系。
我会把项目结构整理成这样:
text
project-root
├── DESIGN.md
├── AGENTS.md
├── README.md
├── package.json
├── tailwind.config.ts
└── src
├── components
├── app
└── styles
DESIGN.md 写设计意图,tailwind.config.ts 写可执行变量,components 目录承接最终组件。这样 agent 执行任务时有三层信息可以参考。
先读 Design.md,知道项目的视觉方向;再看 theme 配置,拿到实际颜色和间距;最后修改 Button、Card、Dialog、EmptyState 这些组件,让规则落到代码里。
如果项目里已经有基础组件,Design.md 里的内容不要写得太抽象。比如不要只写"按钮层级清晰",可以直接写到组件边界:
| 组件 | Design.md 里应该写清楚的内容 |
|---|---|
| Button | 主按钮数量、危险按钮样式、次级按钮使用场景 |
| Card | 圆角、阴影、内边距、标题和正文层级 |
| Dialog | 宽度范围、确认类弹窗和编辑类弹窗的区别 |
| EmptyState | 插图高度、主按钮数量、辅助说明长度 |
| Table / List | 行高、字段优先级、空数据和加载状态 |
我会优先写这些组件,因为 AI 最喜欢在这些地方自由发挥。你让它补一个空状态,它可能马上加插图、加渐变、加两个按钮、加一段很长的说明。你让它改一个弹窗,它可能顺手把宽度、阴影和按钮顺序一起换掉。Design.md 把这些边界写清楚以后,agent 的发挥空间会被压到可控范围内。
这里还有一个现实问题。很多小团队没有完整设计系统,只有一些零散页面和一套大致风格。Design.md 对这类团队反而很有用。你不需要先搭完整组件库,也可以先把视觉判断写下来,再让 AI 改页面时逐步收敛到同一套规则。
四、我会优先写 AI 容易发挥过头的地方
Design.md 不需要一开始写得很全。写得太全也未必有用,因为 agent 真正会反复参考的,通常是那些和当前任务有关的内容。
我会先写 AI 最容易失控的几类内容。
第一类是品牌气质。这里不要只写"简洁、现代、科技感"。这些词太宽,AI 会生成一堆常见模板。更好的写法是把产品场景写出来。
比如:
markdown
这是一个面向开发者的任务工作台。用户进入页面后,主要任务是查看任务状态、处理运行结果、检查错误日志和继续下一步操作。页面可以有少量品牌色,但功能区要优先保证信息读取,不要用大面积渐变背景。
这段话比"科技感后台"有用得多。它告诉 agent 用户进入页面后要做什么,也告诉它功能区要把装饰收住。
第二类是主色使用边界。AI 很容易把主色用得过满,尤其是蓝紫色、绿色、橙色这类视觉存在感强的颜色。Design.md 里要明确主色只放在哪些位置。
比如主按钮、当前选中状态、进度条和少量图标可以使用主色;普通卡片背景、列表项背景、表单容器就不要继续铺主色。
第三类是组件层级。很多页面看起来乱,并不是组件丑,而是所有元素都在抢注意力。标题很大,按钮很亮,卡片阴影很重,标签又有高饱和背景。Design.md 要把这些东西压住。
我会写成这种规则:
markdown
同一屏里只保留一个主要操作。普通编辑、筛选、导出、取消使用次级按钮或文本按钮。状态标签使用低饱和背景,不和主按钮抢视觉焦点。
第四类是禁用效果。这个部分很容易被忽略,但对 AI 很有用。与其让 agent 自己猜哪些效果不要用,不如直接写出来。
| 容易跑偏的效果 | 我会写进 Design.md 的限制 |
|---|---|
| 大面积渐变 | 只允许出现在首页或少量引导卡片里 |
| 重阴影 | 功能页卡片使用轻阴影或无阴影 |
| 玻璃拟态 | 不用于表单、列表和日志面板 |
| 过多主按钮 | 同一任务区域只保留一个主操作 |
| 复杂插图 | 空状态插图不能占据主要阅读区域 |
| 过强动效 | 状态变化使用轻量过渡,不影响任务处理 |
这些限制看起来细,但对 agent 很有效。因为 AI 生成 UI 时经常会主动"补好看",而项目里很多页面其实需要的是稳定、克制和一致。
五、接入时要从页面反推
如果我给一个新项目接入 Design.md,不会一上来就写一份完整设计规范。我会先选三个页面跑一遍。
登录页、主工作台、高频业务页。
登录页决定产品第一眼的气质,主工作台决定信息密度,高频业务页决定组件规则。拿这三个页面反推 Design.md,比坐在空白文档前直接写规范更靠谱。因为很多规则只有放到真实页面里,才知道它是不是成立。
我的流程大概是这样:
- 先把已有页面里的颜色、字体、圆角、间距整理成 token。
- 再写产品气质、主色边界、按钮层级、卡片规则和禁用效果。
- 让 agent 按 Design.md 改一个低风险页面,比如设置页、空状态页或详情页。
- 对比生成结果,把不符合预期的地方补回 Design.md。
- 稳定后再同步到基础组件和 theme 配置里。
这里最重要的是第四步。Design.md 不是一次写完就放着不动的文件,它需要被生成结果反向修正。
比如 agent 总是把空状态做得太花,我会补一条"空状态只保留一个主按钮,插图高度不超过容器高度的三分之一"。如果 agent 总是把表格行距拉得很松,我会补充列表密度和行高范围。如果 agent 每次都把普通按钮改成主色按钮,我会继续收紧按钮层级规则。
这个过程有点像调 Prompt,但它比 Prompt 更适合沉淀。Prompt 是一次任务里的上下文,Design.md 是项目里的长期约束。每次修正 Design.md,后面的页面都能受益。
我也会把它纳入代码审查。只要团队开始依赖 Design.md,就不能让它随便被删 token、改主色、改组件规则。一个颜色变量变化,可能影响几十个页面;一个按钮规则变化,可能让所有确认流程都跟着变。Design.md 进入 PR 后,视觉规则就能像代码规则一样被讨论。
六、它有边界,不能替你做产品判断
Design.md 很有用,但它不能替代需求分析,也不能替代页面设计。
它能告诉 agent 这个项目的卡片应该用什么圆角,按钮应该怎么分层,空状态不要做得太满。可它不能替你判断一个搜索页要不要左侧筛选栏,也不能替你判断危险操作是否要二次确认,更不能替你决定一个页面的信息架构。
这些内容仍然要写进具体任务里。
比如你要让 agent 重构一个搜索页,Design.md 可以提供风格边界,但 Prompt 里仍然要交代:
- 搜索条件有哪些
- 高频筛选和低频筛选怎么区分
- 小屏使用弹层还是折叠区域
- 大屏是否展示侧栏
- 分页状态是否需要保留
- 筛选变化后是否要重置页码
Design.md 只能保证页面改出来以后像同一个产品。业务上的取舍,还要放回需求、PRD、任务说明和具体 Prompt。
我在项目里会把它放在中间层。上面接需求,下面接组件。需求告诉 agent 要做什么,Design.md 告诉 agent 应该以什么视觉边界去做,组件库负责把这些边界真正执行出来。
这三层分开以后,AI 编程的可控性会好很多。以前每次生成页面都要重复讲"主色不要铺满、按钮不要太多、卡片轻一点、背景不要太花"。有了 Design.md,这些话可以沉到项目里,不用每个任务都重新说一遍。
总结
Design.md 值得关注的地方,在于它把设计判断写成了 AI agent 能反复读取的项目上下文。颜色、字体、间距、圆角这些 token 负责统一数值,正文里的使用边界负责约束模型发挥。两部分合在一起,才能减少页面在多轮生成中的风格漂移。
我会把它放在 AI 编程流程的中间位置。早期项目先写轻量版,把品牌气质、主色边界、按钮层级、卡片规则和禁用效果沉淀下来;项目稳定后,再和 theme 配置、基础组件、代码审查慢慢接起来。
对独立开发者和小团队来说,这个文件不需要一开始就很完整。先从几个真实页面反推规则,再根据 AI 生成结果不断补充,比一开始写一份大而全的设计规范更容易落地。真正要保住的,是每一次 AI 修改之后,项目仍然像同一个产品。