1. 为什么 Codex 写前端总从空白页开始
你让 Codex 写一个登录页,它不会先问你项目用什么技术栈,而是直接开写。第一行import React from 'react',第二行开始堆useState,样式随手写几个 Tailwind 类名,路径别名没配就用相对路径../../components/Button。页面能跑,但交付出去之后你会发现:这个页面和项目里其他页面完全不像一个团队写的。
我试过让 Codex 连续生成三个页面,结果三个页面的目录结构、状态管理方式、组件拆分粒度全都不一样。第一个页面把表单逻辑写在组件里,第二个抽了个useFormhook,第三个直接用了受控组件加onChange回调。这不是 Codex 能力问题,是它每次都在从零做决策——技术栈选什么、组件库用不用、别名怎么配、目录怎么分,这些决策每次重新做一遍,结果必然发散。
前端项目冷启动的核心矛盾就在这里:Codex 擅长写业务逻辑,但不擅长替你做工程决策。你让它写一个页面,它会写;你让它在一个已有骨架里写页面,它写得又快又稳。所以正确的做法不是让 Codex 从空白开始,而是先给它一个工程骨架,让它在这个骨架里填业务代码。
GitHub 上有一类叫 skill 的东西正好解决这个问题。skill 不是插件,不是依赖包,它是一份带脚本和规则的目录,告诉 Codex「这个项目长什么样、用什么技术栈、按什么流程走」。你把这个目录放进项目,Codex 读完之后就会按骨架来写,而不是每次重新发明轮子。
这篇要交付的就是一套可复制的 skill 目录结构、一份config.toml骨架,以及用 TaoToken 统一 Key 通道的配置方式。目标很明确:让 Codex 基于工程骨架生成页面,而不是从空白开始。适合正在用 Codex 做前端、但被「每次生成风格不一致」困扰的人。
2. TaoToken 前置:统一 Key 通道解决什么问题
在讲 skill 目录之前,先说 Key 通道的事。因为 skill 里会配 Codex 的调用参数,而 Codex 每次请求都要走一个 API 端点。如果你用多个模型、多个项目、多个环境,Key 管理会变成一件很烦的事。
TaoToken 在这里的角色是统一入口。官网地址是 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,API 端点是 https://taotoken.net/api 。你在这个平台上拿一个 Key,就可以在 Codex 的配置里统一指向这个端点,不用每个项目单独配一套。
具体来说,TaoToken 解决三个问题。第一,Key 统一。你不需要在.env、config.toml、CI 变量里各放一份不同的 Key,一个 Key 走所有环境。第二,端点统一。Codex 的base_url指向https://taotoken.net/api,模型名按平台支持的填,切换模型不用改代码。第三,额度可控。你在控制台能看到每个 Key 的用量,方便排查是哪个项目在烧额度。
拿 Key 的路径是:进控制台,创建 API Key,复制出来。控制台地址是 https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_content=console&utm_campaign=rewrite ,API Keys 管理页是 https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewrite 。这两个页面你收藏一下,后面配config.toml的时候要用。
注意:Key 不要写进 skill 目录里提交到 Git。skill 目录是给 Codex 读的规则和脚本,Key 应该放在环境变量或本地配置文件里,用
.gitignore排除。
如果你还没决定用哪个模型,可以先在模型对话页试一下 https://taotoken.net/chat?utm_source=taotoken_aicg_blog_end&utm_content=model-chat&utm_campaign=rewrite ,确认端点通不通、模型响应正不正常,再写进 Codex 配置。长期做编码和 Agent 任务的话,Coding Plan 页面 https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite 里有套餐说明,按自己的调用量选。
3. 可复制的 skill 目录结构与 config.toml 骨架
现在进入正题。skill 的本质是一个目录,里面放三类东西:规则文件(告诉 Codex 怎么做)、脚本(替 Codex 做初始化)、配置(告诉 Codex 走哪个端点)。下面这套结构你可以直接复制。
web-skeleton-skill/ ├── SKILL.md ├── config.toml ├── scripts/ │ ├── init-project.sh │ └── verify-skeleton.sh └── templates/ ├── vite.config.ts ├── tailwind.config.js └── tsconfig.jsonSKILL.md是入口,Codex 读的第一个文件。它不需要很长,但要把技术栈、目录约定、执行流程写清楚。下面是一份可用的骨架:
# Web Skeleton Skill ## 技术栈 - React 18 + TypeScript - Vite 5 构建 - Tailwind CSS 3.4 - shadcn/ui 组件库 - 路径别名 @/ 指向 src/ ## 执行流程 1. 运行 scripts/init-project.sh <项目名> 生成骨架 2. 在 src/pages/ 下新建页面文件 3. 组件放 src/components/,工具函数放 src/lib/ 4. 不要新建第二套技术栈或组件体系 5. 完成后运行 scripts/verify-skeleton.sh 自检 ## 设计约束 - 避免过度居中布局、紫色渐变、清一色圆角 - 字体和圆角不要全靠一个模板 - 配色至少有两种以上层次config.toml是 Codex 的调用配置,重点是base_url和api_key两项:
# config.toml - Codex 调用配置骨架 [model] provider = "openai-compatible" base_url = "https://taotoken.net/api" api_key = "${TAOTOKEN_API_KEY}" model = "gpt-4o" [project] name = "web-skeleton" root = "." skill_dir = "./web-skeleton-skill" [generation] temperature = 0.3 max_tokens = 8192这里api_key用环境变量引用,不写死。你在终端里export TAOTOKEN_API_KEY="你的Key",Codex 启动时自动读取。base_url指向 TaoToken 的 API 端点,所有请求走这一个通道。
scripts/init-project.sh是初始化脚本,负责把templates/里的配置文件复制到新项目,并安装依赖:
#!/usr/bin/env bash set -euo pipefail PROJECT_NAME="${1:?请传入项目名}" TARGET_DIR="./${PROJECT_NAME}" if [ -d "$TARGET_DIR" ]; then echo "目录已存在: $TARGET_DIR" exit 1 fi mkdir -p "$TARGET_DIR/src/pages" "$TARGET_DIR/src/components" "$TARGET_DIR/src/lib" cp templates/vite.config.ts "$TARGET_DIR/" cp templates/tailwind.config.js "$TARGET_DIR/" cp templates/tsconfig.json "$TARGET_DIR/" cd "$TARGET_DIR" npm create vite@latest . -- --template react-ts --force npm install npm install -D tailwindcss@3.4 postcss autoprefixer npx tailwindcss init -p echo "骨架生成完成: $TARGET_DIR"这个脚本做的事很直白:建目录、拷配置、初始化 Vite、装 Tailwind。Codex 不需要自己决定用哪个构建工具,脚本已经定好了。
scripts/verify-skeleton.sh是自检脚本,Codex 写完页面后跑一遍,确认骨架没被破坏:
#!/usr/bin/env bash set -euo pipefail echo "检查目录结构..." [ -d "src/pages" ] || { echo "缺少 src/pages"; exit 1; } [ -d "src/components" ] || { echo "缺少 src/components"; exit 1; } echo "检查路径别名..." grep -q '"@/\*"' tsconfig.json || { echo "tsconfig 缺少 @/ 别名"; exit 1; } echo "检查 Tailwind 配置..." [ -f "tailwind.config.js" ] || { echo "缺少 tailwind.config.js"; exit 1; } echo "骨架自检通过"这三个文件加两个脚本,就是一套最小可用的 skill。你把它放进项目根目录,Codex 读SKILL.md之后就知道该按什么流程走。
4. 验证请求:Codex 调用 skill 后的成功结果
配好之后要验证。验证分两步:先确认 API 通道通,再确认 Codex 按 skill 执行。
第一步,用 curl 测 TaoToken 端点:
curl -s https://taotoken.net/api/v1/chat/completions \ -H "Authorization: Bearer $TAOTOKEN_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "gpt-4o", "messages": [{"role": "user", "content": "回复 ok"}], "max_tokens": 10 }'返回里如果有choices字段和内容,说明 Key 和端点都正常。如果返回 401,检查 Key 有没有复制全;返回 404,检查base_url是不是写成了https://taotoken.net/api而不是别的路径。
第二步,让 Codex 执行 skill。你在 Codex 里给的任务应该这样写:
按 web-skeleton-skill/SKILL.md 执行。 先运行 scripts/init-project.sh my-app 初始化骨架。 骨架生成后,在 src/pages/ 下新建 Dashboard.tsx。 使用已有的 Tailwind 和 shadcn/ui 约定,不要新建技术栈。 完成后运行 scripts/verify-skeleton.sh 自检。Codex 执行完之后,你应该看到这样的结果:
my-app/ ├── src/ │ ├── pages/ │ │ └── Dashboard.tsx │ ├── components/ │ └── lib/ ├── vite.config.ts ├── tailwind.config.js └── tsconfig.jsonDashboard.tsx里应该 import 了@/components/...而不是../../components/...,样式用的是 Tailwind 类名,没有自己写 CSS 文件。跑npm run dev能起来,页面能渲染。
如果 Codex 生成的页面里出现了import styled from 'styled-components'或者自己建了src/styles/目录,说明它没读 skill 或者读了没遵守。这时候你要在任务里加一句「不要引入 styled-components,样式统一用 Tailwind」,把约束写死。
验证通过的标准就三条:目录结构对、路径别名对、能跑起来。三条都满足,说明 skill 生效了。
5. 本篇常见错排查
配 skill 和 Key 通道的过程中,有几个错我踩过,列出来你对照。
错误一:Codex 没读 SKILL.md 就开写。表现是它直接生成页面代码,没有先跑init-project.sh。原因是任务描述里没明确让它先读 skill。解决方法是把「先读 SKILL.md」写进任务第一句,或者用 Codex 的--skill参数显式指定 skill 目录。
错误二:base_url写错导致 404。TaoToken 的 API 端点是https://taotoken.net/api,不是https://taotoken.net/api/v1。有些客户端会自动补/v1,有些不会。你在config.toml里写base_url = "https://taotoken.net/api",让客户端自己拼路径。如果还是 404,检查是不是多写了斜杠。
错误三:Key 写进 config.toml 提交了。这是安全问题。config.toml里用${TAOTOKEN_API_KEY}引用环境变量,本地.env文件加进.gitignore。如果你已经提交了,去控制台把那个 Key 删掉重新生成一个。
错误四:skill 脚本没有执行权限。init-project.sh复制过去之后可能没有+x权限,Codex 跑的时候报Permission denied。解决方法是chmod +x scripts/*.sh,或者在任务里让 Codex 用bash scripts/init-project.sh调用。
错误五:Tailwind 版本冲突。模板里写的是 Tailwind 3.4,但npm install tailwindcss默认装最新版可能是 4.x,配置方式不一样。脚本里要写死tailwindcss@3.4,避免版本漂移。
错误六:路径别名在 Vite 里没配。tsconfig.json里配了@/别名,但vite.config.ts里没配resolve.alias,运行时报模块找不到。两个地方都要配,缺一不可。
提示:排查顺序建议是先测 API 通道(curl),再测 skill 脚本(手动跑一遍),最后测 Codex 集成。这样能快速定位是 Key 问题、脚本问题还是 Codex 理解问题。
6. 把 Key 通道和 skill 接进日常工作流
骨架立起来之后,日常用法就固定了。每次新页面任务,你给 Codex 的指令模板是:
按 web-skeleton-skill/SKILL.md 执行。 在 src/pages/ 下新建 <页面名>.tsx。 使用已有技术栈和组件约定。 完成后运行 verify-skeleton.sh。Key 通道那边,你只需要维护一个环境变量TAOTOKEN_API_KEY。换模型的时候改config.toml里的model字段,端点不动。多项目共用同一个 Key,额度在控制台统一看。
如果你要接 CI,把TAOTOKEN_API_KEY配成 CI 的 secret,config.toml里的${TAOTOKEN_API_KEY}会自动读取。接入文档在 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite ,里面有不同客户端的配置示例,Codex 的配置可以对照着改。
长期做编码任务的话,Coding Plan 页面 https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite 里有按量套餐,比单次调用划算。Claude Code 用户看 https://taotoken.net/claudecode-anthropic?utm_source=taotoken_aicg_blog_end&utm_content=claudecode-anthropic&utm_campaign=rewrite ,里面有 Anthropic 兼容端点的配置方式。
最后说一个实际经验:skill 目录不要写太大。我见过有人把整个团队的编码规范塞进 SKILL.md,结果 Codex 读完之后反而不知道重点在哪。skill 的作用是定骨架,不是定所有细节。骨架定好之后,业务代码让 Codex 自由发挥,这样它写得快,你也省心。