1. 为什么你的 React 页面总有一股 AI 味
你有没有遇到过这种情况:让 Claude Code 或者 Cursor 写一个 SaaS 落地页,结构没问题,组件也拆得挺合理,但打开浏览器一看——渐变紫、发光卡片、emoji 图标、千篇一律的圆角阴影。第一眼还行,多看两眼就腻了。
这不是模型不会写页面。React 组件、TailwindCSS 类名、响应式断点,这些它都门儿清。问题出在:你给了它需求、给了它代码上下文,但没告诉它这个页面到底该长什么样。于是模型只能用它训练数据里出现频率最高的那套视觉方案——也就是所谓的"平均值"。设计一旦落到平均值,基本就危险了。
我试过在提示词里写"请使用极简风格""参考 Vercel 的设计语言",效果有改善但不够稳定。因为"极简"这个词太模糊了,模型对它的理解和你对它的理解可能差了十万八千里。你需要一份结构化的、可被 agent 直接读取的设计规范文件,把颜色、字体、间距、圆角、阴影这些设计 token 全部写死。
这就是 DESIGN.md 要解决的问题。它本质上是一份写给 AI 看的设计说明书,放在项目根目录,agent 在生成页面时会把它当作硬约束来执行。配合 React + TailwindCSS 这套技术栈,你可以让 Claude Code 这类 agent 稳定产出高颜值的页面,而不是每次都在开盲盒。
这篇文章我会给你一份可直接复制的 DESIGN.md 模板、对应的 TailwindCSS 配置片段、以及经过实测的 agent 提示词。最后还会给出页面渲染验证步骤和常见报错排查。适合正在用 Claude Code / Codex / Cursor 写前端、但苦于输出风格不稳定的开发者。
2. TaoToken 前置准备:让 agent 稳定调用模型
在开始写 DESIGN.md 之前,你需要确保 agent 能稳定调用模型。Claude Code 默认走的是 Anthropic 官方接口,如果你在国内直连,经常会遇到超时或者local proxy failed这类报错。我的做法是通过 TaoToken 来做 API 接入,它兼容 Anthropic 的接口格式,配置起来比较省事。
先说清楚:TaoToken 不是让你去搞什么灰色通道,它就是一个标准的 API 接入服务,提供 OpenAI 兼容和 Anthropic 兼容两种接口。你注册后在控制台生成 API Key,然后把 Base URL 指向https://taotoken.net/api就行。
具体操作路径是这样的:先访问官网 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 注册账号,然后进控制台 https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_content=console&utm_campaign=rewrite 创建 API Key。Key 的格式一般是sk-开头的一串字符,复制下来保存好,后面配置 Claude Code 和 Cline 都要用。
如果你用的是 Claude Code,它读取的是环境变量ANTHROPIC_BASE_URL和ANTHROPIC_API_KEY。你可以在终端里直接 export,也可以写进 shell 配置文件。我习惯写进~/.zshrc,这样每次开终端都自动生效。
如果你用的是 Cline 或者 Roo Code 这类 VS Code 插件,那就在插件的设置面板里填 Base URL、API Key 和 Model ID 三件套。Model ID 根据你实际用的模型来填,比如claude-sonnet-4-20250514或者claude-opus-4-20250514。
这里有个坑要注意:Claude Code 和 Cline 虽然都走 Anthropic 兼容接口,但它们对 Base URL 的拼接方式不一样。Claude Code 会自动在 Base URL 后面拼/v1/messages,所以你填https://taotoken.net/api就行,不要自己加/v1。Cline 有些版本需要你填完整的https://taotoken.net/api,它内部会处理路径拼接。如果你填错了,最常见的报错就是 404 或者not found。
配置完成后,你可以先用一个最简单的请求验证一下通路。打开终端,用 curl 发一个测试请求:
curl https://taotoken.net/api/v1/messages \ -H "Content-Type: application/json" \ -H "x-api-key: $ANTHROPIC_API_KEY" \ -H "anthropic-version: 2023-06-01" \ -d '{ "model": "claude-sonnet-4-20250514", "max_tokens": 100, "messages": [ {"role": "user", "content": "回复一句:通路正常"} ] }'如果返回的 JSON 里有content字段并且包含"通路正常",说明 API 接入没问题。如果返回 401,检查你的 API Key 是否正确复制,有没有多余空格。如果返回local proxy failed,那多半是你本地网络环境的问题,检查一下终端代理设置。
这一步看起来简单,但它是后面所有操作的基础。agent 调不通模型,DESIGN.md 写得再好也没用。所以先把这步跑通,再往下走。
3. 可复制的 DESIGN.md 模板与 TailwindCSS 配置
现在进入正题。我给你一份可以直接用的 DESIGN.md 模板,风格参考 Vercel 的极简工程师审美。你可以根据自己项目的需要调整色值和间距,但结构建议保留。
# DESIGN.md ## 设计哲学 极简、克制、工程师审美。黑白灰为主,强调留白和秩序感。 参考:Vercel / Linear / Stripe ## 色板 Color Tokens - background: #000000 - foreground: #ffffff - muted: #888888 - border: #333333 - accent: #0070f3 - accent-hover: #0060df - card-bg: #0a0a0a - card-border: #1a1a1a ## 字体 Typography - 字体族: Inter, -apple-system, sans-serif - 标题字重: 600 - 正文字重: 400 - 标题字号: 48px / 36px / 24px - 正文字号: 16px - 行高: 1.6 ## 间距 Spacing - 基础单位: 4px - 常用间距: 8 / 16 / 24 / 32 / 48 / 64 / 96 - 区块垂直间距: 96px - 卡片内边距: 24px ## 圆角 Radius - 小圆角: 6px(按钮、输入框) - 中圆角: 8px(卡片) - 大圆角: 12px(模态框) ## 阴影 Shadow - 卡片默认: 无阴影,用边框区分 - 卡片 hover: 0 0 0 1px #333 - 按钮: 无阴影 ## 组件规范 ### 按钮 - 主按钮: 背景 accent,文字白色,圆角 6px,padding 12px 24px - 次按钮: 透明背景,边框 border,文字 foreground - hover: 主按钮背景变 accent-hover,次按钮边框变 muted ### 卡片 - 背景 card-bg,边框 card-border,圆角 8px - hover 时边框变 muted ### 导航 - 高度 64px,底部边框 border - Logo 左对齐,导航居中,CTA 右对齐这份文件放在项目根目录,文件名就叫DESIGN.md。agent 读取后会把里面的 token 当作硬约束。
接下来是 TailwindCSS 配置。你需要把 DESIGN.md 里的色板和间距映射到tailwind.config.js里,这样 agent 写代码时可以直接用bg-background、text-foreground这类语义化类名,而不是写死bg-black。
/** @type {import('tailwindcss').Config} */ module.exports = { content: [ "./src/**/*.{js,ts,jsx,tsx}", ], theme: { extend: { colors: { background: "#000000", foreground: "#ffffff", muted: "#888888", border: "#333333", accent: "#0070f3", "accent-hover": "#0060df", "card-bg": "#0a0a0a", "card-border": "#1a1a1a", }, fontFamily: { sans: ["Inter", "-apple-system", "sans-serif"], }, borderRadius: { sm: "6px", md: "8px", lg: "12px", }, spacing: { 18: "4.5rem", 22: "5.5rem", }, }, }, plugins: [], };如果你用的是 TailwindCSS v4,配置方式略有不同,需要在 CSS 文件里用@theme指令:
@import "tailwindcss"; @theme { --color-background: #000000; --color-foreground: #ffffff; --color-muted: #888888; --color-border: #333333; --color-accent: #0070f3; --color-accent-hover: #0060df; --color-card-bg: #0a0a0a; --color-card-border: #1a1a1a; --font-sans: Inter, -apple-system, sans-serif; --radius-sm: 6px; --radius-md: 8px; --radius-lg: 12px; }配置好之后,你在提示词里要明确告诉 agent:所有颜色必须使用 tailwind.config.js 里定义的语义化 token,禁止写死颜色值。这样它生成的代码才会和 DESIGN.md 保持一致。
这里有个细节:DESIGN.md 里的色值和 tailwind.config.js 里的色值必须完全一致。如果 DESIGN.md 写#0070f3,config 里写#0071f3,agent 可能会困惑到底以哪个为准。建议你改的时候两边同步改。
另外,如果你用的是 Claude Code,它读取 DESIGN.md 的方式是直接读文件内容。你可以在提示词里写"请先读取项目根目录的 DESIGN.md,然后严格按照其中的设计规范生成页面"。Claude Code 会自动去读这个文件。如果你用的是 Cline,它有一个"Read File"工具,你需要在提示词里明确让它先读 DESIGN.md。
4. 验证请求与页面渲染成功结果
配置好 DESIGN.md 和 TailwindCSS 之后,你需要验证 agent 是否真的按规范生成了页面。这一步不能省,因为 agent 有时候会"忘记"读 DESIGN.md,或者读了但没严格执行。
我的验证流程分三步:先验证 API 通路,再验证 agent 是否读取了 DESIGN.md,最后验证页面渲染结果。
第一步,API 通路验证。前面已经给过 curl 命令,这里不再重复。确保返回正常后再往下走。
第二步,agent 读取验证。在 Claude Code 里输入这样的提示词:
请先读取项目根目录的 DESIGN.md 文件,然后告诉我: 1. 主色调是什么 2. 卡片圆角是多少 3. 按钮的 padding 是多少如果 agent 能准确回答出#0070f3、8px、12px 24px,说明它确实读了 DESIGN.md。如果它回答得含糊或者答错,那可能是文件路径不对,或者 agent 没有读取文件的权限。
第三步,页面渲染验证。给 agent 一个完整的页面生成任务,提示词如下:
你现在是一个资深前端架构师 + SaaS 产品设计师。 请基于项目根目录的 DESIGN.md 设计规范,生成一个完整的 SaaS 官网首页。 产品名称:KkltCodePilot 定位:AI 编程助手 技术要求: - 使用 React(函数组件 + Hooks) - 使用 TailwindCSS,严格遵守 DESIGN.md 的设计系统 - 组件化拆分(Header / Hero / Features / Pricing / FAQ / Footer) - 响应式设计,移动端优先 - 所有颜色使用 tailwind.config.js 中的语义化 token,禁止写死颜色值 页面结构: 1. Header:Logo + 导航(Features / Pricing / Docs)+ CTA 按钮 2. Hero:标题 + 副标题 + 两个按钮(Primary / Secondary) 3. Features:4 个卡片,每个包含 icon、title、description 4. Pricing:3 个套餐(Free / Pro / Team),Pro 高亮 5. FAQ:4 个可折叠问题 6. Footer:产品信息 + 链接 + Copyright 输出要求: - 输出完整可运行的 React 代码 - 包含所有组件 - 不要解释,只输出代码生成完成后,把代码放进项目里跑起来。我用的是 Vite + React 模板,命令如下:
npm create vite@latest kklt-demo -- --template react cd kklt-demo npm install npm install -D tailwindcss postcss autoprefixer npx tailwindcss init -p然后把 agent 生成的组件文件放进src/components/目录,在App.jsx里引入。启动开发服务器:
npm run dev打开浏览器访问http://localhost:5173,你应该能看到一个黑白灰为主、留白充足、边框克制的页面。按钮是蓝色 accent,卡片有细边框,整体风格接近 Vercel 官网。
如果你看到的是渐变紫、发光卡片、emoji 图标,那说明 agent 没有严格执行 DESIGN.md。这时候你需要检查两个地方:一是 DESIGN.md 是否真的在项目根目录,二是提示词里是否明确要求了"严格遵守 DESIGN.md"。
我实测下来,只要 DESIGN.md 写清楚、提示词里明确引用,Claude Code 生成 Vercel 风格页面的成功率很高。偶尔会有个别组件颜色写死,手动改一下就行。
5. 本篇常见错误排查
这一节我整理了几个实际遇到的报错和排查方法,都是真实踩过的坑。
报错一:401 Unauthorized
{"error":{"type":"authentication_error","message":"invalid x-api-key"}}这个最常见。原因通常是 API Key 复制错了,或者环境变量没生效。排查步骤:先在终端执行echo $ANTHROPIC_API_KEY,看看有没有输出。如果没有输出,说明环境变量没设置成功,检查你的~/.zshrc或~/.bashrc里有没有写对。如果有输出但仍然是 401,那可能是 Key 过期了,去控制台重新生成一个。
报错二:local proxy failed
Error: connect ECONNREFUSED 127.0.0.1:7890这个报错说明你的终端在走本地代理,但代理服务没启动。Claude Code 默认会读取HTTP_PROXY和HTTPS_PROXY环境变量。如果你之前设置过代理但后来关了,就会报这个错。解决方法:执行unset HTTP_PROXY HTTPS_PROXY清除代理设置,然后重新运行。
报错三:reading 'choices' of undefined
TypeError: Cannot read properties of undefined (reading 'choices')这个报错通常出现在 Cline 或 Roo Code 里,原因是 Base URL 填错了。Cline 期望的 Base URL 是https://taotoken.net/api,如果你填成了https://taotoken.net/api/v1,它拼接路径后就会变成https://taotoken.net/api/v1/v1/chat/completions,导致返回格式不对。检查你的 Base URL,确保没有多余的/v1。
报错四:OAuth token expired
OAuth token has expired. Please re-authenticate.这个报错出现在 Claude Code 里,说明你之前用 OAuth 登录过 Anthropic 官方账号,现在 token 过期了。但你现在想用 API Key 接入,不需要 OAuth。解决方法:执行claude logout退出登录,然后设置ANTHROPIC_API_KEY环境变量,再重新启动 Claude Code。
报错五:Model not found
{"error":{"type":"invalid_request_error","message":"model: claude-sonnet-4-20250514 not found"}}这个报错说明你填的 Model ID 不对。不同的 API 服务商支持的模型 ID 可能不一样。你需要去 TaoToken 的文档页面 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite 查看当前支持的模型列表,然后填对应的 ID。常见的 Claude 模型 ID 有claude-sonnet-4-20250514、claude-opus-4-20250514、claude-3-5-sonnet-20241022等。
报错六:Tailwind 类名不生效
页面渲染出来后发现bg-background没有生效,背景还是白色。原因通常是tailwind.config.js里的content路径没配对。检查你的content字段是否包含了所有用到 Tailwind 类名的文件路径。如果你用的是 Vite + React,通常是./src/**/*.{js,ts,jsx,tsx}。改完配置后需要重启开发服务器。
报错七:agent 不读 DESIGN.md
你明明把 DESIGN.md 放在根目录了,但 agent 生成的页面还是老样子。原因可能是提示词里没有明确要求它读取。Claude Code 虽然会自动读取项目文件,但如果你不明确说"请先读取 DESIGN.md",它可能会忽略。解决方法:在提示词开头加上"请先读取项目根目录的 DESIGN.md 文件,然后严格按照其中的设计规范生成页面"。
6. 长期编码与 Agent 工作流建议
DESIGN.md 这套方法最适合新项目,尤其是 Landing Page、产品官网、活动页、Side Project。你可以在项目启动阶段就把 DESIGN.md 写好,后面所有页面生成都基于它,风格一致性会非常好。
但它不太适合硬塞进一个已经有成熟样式体系的老项目。我拿现有项目试过一次,结果页面直接开始打架。字重一套、圆角一套、阴影一套,图标和图片还容易溢出。agent 一旦认真执行新的 DESIGN.md,原来的样式逻辑就很容易被带偏。所以如果你要在老项目里用,建议先开一个 git 分支,局部试,慢慢改,别一把梭。
如果你需要长期用 agent 写代码,可以考虑 TaoToken 的 Coding Plan https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite ,它比按量计费更适合高频调用场景。配合 Claude Code 的 Agent 模式,你可以让它在后台持续生成和优化页面,你只需要在关键节点做 review。
另外,DESIGN.md 不是一成不变的。随着项目迭代,你可能会调整色板或者间距。每次调整后,记得同步更新tailwind.config.js,并让 agent 重新读取 DESIGN.md。我习惯在 DESIGN.md 顶部加一个版本号和更新日期,这样 agent 能知道当前用的是哪一版。
最后说一个实用技巧:你可以把 DESIGN.md 拆成多个文件,比如DESIGN.md放全局规范,DESIGN-components.md放组件级规范。然后在提示词里按需引用。这样对于大型项目来说,agent 的上下文压力会小一些,执行也更精准。
如果你还没试过 TaoToken,可以从模型对话 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_content=model-chat&utm_campaign=rewrite 开始,先感受一下接口通不通,再决定要不要接入 Claude Code。API Key 在控制台 https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewrite 生成,文档在 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite 查看。配置过程中遇到问题,优先检查 Base URL 和 Model ID 这两个地方,大部分报错都出在这里。