08 · 可复用资产清单(别从零造轮子)
本机
~/personal下已有 40+ 个项目。本节列出「接棒 Baton」可以直接拷贝的现成资产。 重要原则:能cp源文件就不要从文档里复制代码。 文档里的代码可能被转义损坏,源文件不会。
#1. 统一密码门(四个文件,直接 cp)
范式来源:~/personal/english-daily。这是当前最新的 Next 16 proxy.ts 写法。
⛔ 不要抄 media-studio / media-studio-oss 的 middleware.ts,那是过时范式。
# 在 baton 项目根目录执行(假设用非 src 结构,与 english-daily 一致)
cp ~/personal/english-daily/lib/hub-auth.ts ./lib/hub-auth.ts
cp ~/personal/english-daily/proxy.ts ./proxy.ts
cp ~/personal/english-daily/app/login/page.tsx ./app/login/page.tsx
cp ~/personal/english-daily/app/api/login/route.ts ./app/api/login/route.ts四个文件各自的作用
| 文件 | 作用 |
|---|---|
lib/hub-auth.ts |
HMAC-SHA256 签发/校验会话令牌,纯 Web Crypto,Edge 和 Node 都能跑。导出 AUTH_COOKIE / COOKIE_DOMAIN / signToken / verifyToken / checkPassword |
proxy.ts |
放在项目根目录(与 app/ 同级)。导出 export async function proxy(req) + config.matcher。未配置 env 时全部拦下(绝不裸奔) |
app/login/page.tsx |
登录页,纯内联样式零依赖,可原样用。但今晚要按浅色干净风重做样式,逻辑照抄 |
app/api/login/route.ts |
POST 校验密码签发 Cookie,DELETE 登出。密码错误时 sleep 600ms 拖慢暴力破解 |
必须改的一处:proxy.ts 的 matcher 排除列表。Baton 会新增 API 路由,凡是不需要登录也要能访问的路径必须加进排除列表。今晚至少要加:
/((?!login|api/login|api/health|_next/static|_next/image|favicon.ico).*)其余 /api/* 全部要走门(因为里面是员工资料)。
环境变量(值从 (密码门凭据文件,路径从略) 取,⛔ 不要写进代码或 git)
HUB_SITE_PASSWORDHUB_AUTH_SECRETHUB_COOKIE_DOMAIN(可省,默认.saveme505.help)
⚠️ 本地开发的坑(实测):english-daily 的本地 .env.local 里没有这三个变量——它们只配在 Vercel。结果是本地 npm run dev 时 proxy 判定"未配置"→ 全站拦截且 /api/login 返 503。
今晚的做法:在 .env.local 里补齐这两个值(本地文件已 gitignore,安全),这样本地 dev 和 Playwright E2E 都能跑通登录流程。E2E 必须能跑通登录,否则所有页面测试都进不去。
#2. 技术栈版本基线(照抄,别用更新的)
理由:这套组合是本机多个项目验证过能正常 build 并部署到 Vercel 的唯一组合。用更新版本 = 今晚重新踩雷 = 没时间。
"next": "16.2.10",
"react": "19.2.4",
"react-dom": "19.2.4",
"tailwindcss": "^4",
"@tailwindcss/postcss": "^4",
"shadcn": "^4.13.1",
"@supabase/supabase-js": "^2.110.7"- shadcn CLI 是新版
shadcn(⛔ 不是老的shadcn-ui) components.json直接cp ~/personal/english-daily/components.json ./components.json,其中:"style": "base-nova"、"baseColor": "neutral"、"iconLibrary": "lucide"、"cssVariables": true- 如果
npx shadcn@latest init出来的配置和上面不一致,以上面为准
#3. 视觉基线:浅色干净风
⚠️ zhixingyuan 项目本机磁盘上已经不存在(find 全盘无命中,只剩 Claude Code 会话索引)。不要浪费时间找它。
用这两个做视觉底子:
#3.1 shadcn 中性浅色主题(主选)
cp ~/personal/english-daily/app/globals.css ./app/globals.css # 然后按 Baton 需要改 accent:root 是纯灰阶 oklch(chroma≈0):--background: oklch(1 0 0)、--foreground: oklch(0.145 0 0)、--border: oklch(0.922 0 0)、--radius: 0.625rem。这是"最不会出错"的浅色起点,但没有品牌色。
#3.2 Baton 的品牌色(在上面基础上叠一层)
接棒 = 交接 = 传递。用靛蓝 indigo 作单一强调色,其余全灰阶。克制,不要第二个强调色。
:root {
--bg-page: #f6f7f9; /* 页面底色,浅灰,不要纯白 */
--card: #ffffff; /* 卡片纯白,靠阴影和 1px 边框分层 */
--accent: #6366f1; /* indigo-500,只用在主按钮、选中态、进度条 */
--line: #e5e7eb;
}(这套取自 ~/personal/daily-digest/app/globals.css,全文 31 行,是本机视觉最干净的一份,可以直接读来参考。)
#3.3 视觉硬规则(明早人类会用这几条挑毛病)
- 页面底
#f6f7f9,卡片纯白,不要纯白底 + 纯白卡片(会糊成一片) - 圆角统一
--radius: 0.625rem(10px),不要有的 4px 有的 16px - 只有一个强调色。状态色只用 shadcn 默认的 destructive
- 中文字体栈必须有
"PingFang SC",否则 Mac 上中文会难看 - 表格行高不小于 44px,留白宁多勿少
- ⛔ 不要深色科技风、霓虹、玻璃拟态、渐变大背景
#4. Supabase 接入(Leo-hub)
项目 id:<ID>(Leo-hub)
#4.1 client 范式(直接抄 english-daily)
cp ~/personal/english-daily/lib/supabase.ts ./lib/supabase-base.ts # 作为 db.ts 的底层它是单例 client + publishable key + auth: { persistSession: false }。
#4.2 ⭐ 关键安全事实:Leo-hub 现有的 RLS 是全开的
实测 pg_policies:en_* 系列表的策略全是 for all to public using (true) with check (true)。
也就是说:Leo-hub 上的 RLS 不提供任何隔离能力,它只是"开了 RLS 但放行一切"。
对 Baton 的直接影响(这是今晚最重要的架构结论之一):
员工之间的数据隔离,必须 100% 在应用层做,RLS 一点都指望不上。
所以:
- 所有 DB 访问必须走
src/lib/db.ts的scopedQuery(employeeId)单一入口,它强制往每个查询注入employee_id过滤 - 禁止在任何客户端组件里
import { getSupabase },禁止把 supabase client 暴露到浏览器做业务查询 - 所有业务查询走 Route Handler / Server Action
- 这条要有专门的自动化守卫测试(见
02-TDD规程的 AC-SEC 系列)
#4.3 建表 SQL 范式
alter table bt_xxx enable row level security;
create policy bt_xxx_all on bt_xxx for all to public using (true) with check (true);和现有表保持一致(否则用 publishable key 会连读都读不到)。真正的隔离在应用层。 这个取舍要写进 README 的安全边界章节,不要藏着。
#4.4 环境变量命名(统一用这两个,别引入第三种)
NEXT_PUBLIC_SUPABASE_URLNEXT_PUBLIC_SUPABASE_KEY
(注:gifmoji 用的是 ..._ANON_KEY,是历史不一致,不要跟。)
⛔ 不要抄 media-studio 的 DATABASE_URL 直连 + ms_app 角色模式,那是它的特例,且它的 DATABASE_URL 现在还是坏的(占位值)。
#5. 导航站收录(P5 必做)
文件:~/personal/projects-hub/src/lib/projects-meta.tsx
改两处:
- 文件顶部
import { ... } from "lucide-react"块里,按字母序加一个图标名(建议用Repeat2或ArrowLeftRight或Handshake) PROJECT_META对象里加一条,键名必须等于 Vercel 项目名(不是域名):
baton: {
icon: Handshake,
description: "给小公司每人配一个 Agent 管住自己的资料,离职换岗一键把该给的交出去",
tint: "text-violet-500 bg-violet-500/10 dark:text-violet-400 dark:bg-violet-400/10",
group: "backend",
},改完 projects-hub 要单独 commit + push(它自己会自动部署)。
不补的话会显示灰色地球 + "还没配图标和简介"。
#6. LLM / Embedding(云雾中转)
配置来源:~/Desktop/配置信息/云雾API-中转/README.md
YUNWU_API_BASE=https://yunwu.ai/v1 # OpenAI 兼容
YUNWU_API_KEY=<从现有项目的 Vercel env 或本地 .env.local 取,⛔ 不写进 git>
LLM_MODEL=deepseek-v4-flash # 对话/抽取用,便宜快、结构化稳定
EMBEDDING_MODEL=text-embedding-3-small # 1536 维Node 侧两种调法都验证过:
openaiSDK:new OpenAI({ apiKey, baseURL: "https://yunwu.ai/v1" })- Vercel AI SDK:
createOpenAICompatible({ name:"yunwu", apiKey, baseURL, supportsStructuredOutputs: true })⚠️supportsStructuredOutputs: true必开,否则generateObject不下发response_format,记忆条目抽取会拿到非结构化文本。
⚠️ 云雾现在是一个项目一把 key。今晚不要去后台建新 key(需要人工登录)。做法:
- 从某个现有项目的本地
.env.local里取一把能用的(只在本地.env.local用,不进 git) - 在
blockers.md写一条:「待人类在云雾后台建baton专属 key,并在 Vercel 环境变量里替换」
#7. 测试基线:零
实测:~/personal 下所有项目的 package.json,vitest / playwright / @testing-library 命中数 = 0。
结论:今晚的测试体系是从零搭的,没有现成配置可抄。 完整配置见 02-TDD规程与反作弊.md,那里给了可直接落地的 vitest.config.ts 和 playwright.config.ts。
这也意味着:Baton 会是本机第一个有测试的项目。这本身就是明早一个漂亮的交付点,值得在一页纸总结里单独说。
#8. 部署流水线(⛔ 铁律,不许变通)
来自用户全局 CLAUDE.md 的最高准则:
改本地代码 → git commit(身份 Leo / 中文注释)→ git push origin main
→ Vercel GitHub 集成检测到 push → 自动部署 → 部署成功后发邮件汇报- ⛔ 禁止
vercel deploy/vercel --prod/ 任何 CLI 直接部署 - ✅ 唯一保留的 CLI 用途:域名绑定
vercel domains add/vercel alias - 新项目起步就要
vercel link+vercel git connect,确保 GitHub 仓库和 Vercel 项目连上、生产分支自动部署已开 - ⚠️ 跑任何 vercel 写类命令前先
cp .env.local .env.local.bak - ⚠️ Vercel 上标为 sensitive 的变量写进去后三条路都读不回明文 → 凡是自己生成的密钥,先在本地留一份再写上去
#9. 关键路径速查表
| 要什么 | 去哪 |
|---|---|
| 密码门四文件 | ~/personal/english-daily/{lib/hub-auth.ts,proxy.ts,app/login/page.tsx,app/api/login/route.ts} |
| shadcn 配置 | ~/personal/english-daily/components.json |
| 浅色主题 token | ~/personal/english-daily/app/globals.css、~/personal/daily-digest/app/globals.css |
| Supabase client | ~/personal/english-daily/lib/supabase.ts |
| 导航站元数据 | ~/personal/projects-hub/src/lib/projects-meta.tsx |
| 密码门密码/密钥 | (密码门凭据文件,路径从略) |
| 云雾 API 配置 | ~/Desktop/配置信息/云雾API-中转/README.md |
| Resend key | ~/Desktop/配置信息/resend-api-key.txt |
| 上一版方案(含 VPS 现状调研) | ~/Desktop/OpenFDE-Demo-接棒方案-20260730.md |
| 本次方案原文 | ~/Desktop/接棒-Agent交接方案-20260730.md |
来源:沉淀/03-项目方案与交接/接棒-通宵施工包-20260731/08-可复用资产清单.md(整理于 2026-08-18)