useAiWork开发者文档
介绍

技术栈

了解组成 Offer快帮 的核心技术与选型理由。

了解组成 Offer快帮 简历工作台的核心技术与选型理由。本文按职责划分技术层次,帮助你在动手前建立完整心智模型:哪些库承担页面与渲染,哪些库负责数据与 AI,哪些库负责把 Next.js 应用真正带到 Cloudflare 边缘。

技术栈选型围绕四个目标展开:让真实经历更容易整理、让 AI 修改可解释且可回退、让运营成本随边缘运行时下降、让代码仓库本身可被 AI 编程工具准确理解与改写。下面按层次说明每一类技术的角色。

应用骨架

Next.js 16

Next.js 是项目唯一的页面与服务端框架,使用 App Router 组织路由、布局与渲染边界。

  • App Router + Server Actions:营销页、应用工作区与 API 入口都通过 src/app/** 暴露;表单提交、数据变更与权限校验优先复用 Server Action 与 Route Handler,避免再叠一层后端服务。
  • Turbopack 默认开启:通过 pnpm dev 启动的开发服务器使用 Turbopack;Next.js 16 起 Turbopack 已稳定为默认打包器,提供 2–5× 的生产构建提速和最高约 10× 的 Fast Refresh 加速。
  • 缓存与渲染:revalidateTag、updateTag 与可选的 Cache Components 让 ISR、按标签失效和读后即写语义保持一致;本项目主要在简历预览与范本页面使用增量渲染。

本机 next dev 与 OpenNext 提供的 opennextjs-cloudflare preview 不是同一种环境。涉及 D1、R2、KV 或 Durable Objects 的逻辑要在 preview/deploy 后再验证一遍。

React 19

React 19 提供 Server Components、Actions、Suspense 与新 Hooks,是 AI 流式返回与简历富文本编辑的共同底座。

  • Server Components:营销页与简历预览默认在服务端渲染,把交互范围控制在编辑器、对话面板与即时反馈区域。
  • Actions + useActionState:登录、注册、范本维护、简历保存等表单直接走 Action,乐观更新与加载态由 React 自身接管。
  • Refs 作为 prop 与新 Context API:让简历编辑器、TipTap 工具栏与命令面板组合更简洁,减少 forwardRef 样板代码。

TypeScript

TypeScript 7 在整个仓库严格开启;tsconfig.json 通过 next typegen 生成的类型涵盖 Next.js 与 Cloudflare 绑定,CI 中执行 pnpm typecheck 作为类型门禁。

  • 数据库 Schema、AI 契约与 API 路由共享一套类型;新增字段必须同步编辑、预览、持久化与历史版本四个链路。
  • 不通过新增 any、@ts-ignore 或关闭 strict 来掩盖类型问题,必要例外需在评审中说明范围。

样式与界面

Tailwind CSS 4

Tailwind CSS 4 提供工具优先的样式层。项目使用 tw-animate-css、@tailwindcss/postcss 与 CSS-first 配置,主题令牌放在 globals.css 中以 @theme 直接管理。

  • v4 由 Rust 编写的 Oxide 引擎驱动,全量构建显著加快,HMR 接近即时。
  • 设计令牌统一从 globals.css 读取,便于在亮暗模式下维护同一套语义令牌,与 DESIGN.md 中的语义主题规则保持一致。
  • 不使用任意值组合动态类名;动态类必须完整写在源代码中以保证 Tailwind 静态扫描能识别。

Radix UI 与 Lucide

Radix UI 提供可访问的底层原语(Dialog、Popover、Select、Tabs、Tooltip、Switch、Slider 等),全部封装在 src/components/ui 中。

  • 所有交互控件遵循 docs/agent-rules/ui.md 的约定:必须显示指针光标,破坏性操作走 ConfirmPopover,仅图标控件同时具备 aria-label 与可见提示。
  • Lucide 提供图标;图标与产品品牌、版式规则保持一致,不随意替换。

shadcn/ui 风格的本地组件

项目以 src/components/ui 为基础组件目录,组件代码留在仓库里、可以任意扩展与修改;不存在外部主题黑盒。components.json 仅作为本地添加新组件的脚手架入口,不接管样式或动画实现。

Motion(Framer Motion)

Motion(framer-motion 的继承者)承担简历模板切换、对话框展开、Toast 入场与统计数字变化的动效,强调克制——所有阴影与位移都遵循 DESIGN.md 的“对象专属阴影”规则,不为装饰而动。

TipTap

TipTap 是简历富文本编辑器的引擎,基于 ProseMirror,并通过 @tiptap/react 与 @tiptap/starter-kit 接入。

  • 富文本支持加粗、斜体、列表、标题、链接、行内代码、任务列表与代码块,覆盖工作 / 项目 / 教育 / 技能等简历区块的表达需求。
  • 简历内容以结构化 JSON 持久化;导出 PDF、PNG、Markdown 与 JSON 时分别走对应渲染器,避免把内部 ProseMirror 结构直接暴露给用户。
  • 编辑器在 SSR 下需要 immediatelyRender: false,避免水合阶段的运行时错误。

AI Elements

src/components/ai-elements 是项目内的 AI 专用 UI 组件层,沿用 src/components/ui 的 Tailwind v4 + Radix 约定,源码完全留在仓库,可自由扩展与主题化;它不是封闭的 UI 框架,而是为 Vercel AI SDK 7 流式输出准备的可组合原语。

  • message / response:承担 Markdown、CJK、代码块、数学与图表渲染,与 Streamdown 协同负责流式内容的可读性。
  • conversation:处理流式消息与自动贴底,配合 use-stick-to-bottom 让长对话保持最新内容可见。
  • reasoning / tool / sources:分别承接推理过程、工具调用状态与引用来源,把模型的中间状态显式呈现给用户。
  • actions / suggestion / prompt-input / model-selector:承载重新生成、快捷建议、附件输入与模型切换等交互。
  • code-block:提供复制、下载与语言识别等代码块增强能力。

业务功能从 src/features/chat、src/features/ai-resume、src/features/career 与 src/features/ai-image 组合使用这些原语;新增 Agent 工具时通常只需补一个工具状态组件并接入对应消息数据,不需要重写聊天工作区。

命令面板与画布交互

cmdk 提供快速键命令面板原语,封装在 src/components/ui/command.tsx 中,承担简历区块跳转、AI 命令、范本搜索等高频交互;react-zoom-pan-pinch 提供头像与简历导出 PNG 的双指/滚轮缩放和拖动,封装在 src/components/ui/image-preview-dialog.tsx 中。两者都遵循 src/components/ui 的 Tailwind v4 + Radix 风格。

样式与 class 工具集

class-variance-authority(cva)负责声明按钮、徽章、Sidebar 等组件的尺寸、颜色、状态变体;clsx 与 tailwind-merge 在 src/lib/utils.ts 中组合成 cn(),合并动态类时正确处理 Tailwind 冲突。三者一起保证样式变体可读、动态拼接不出错。

状态、数据获取与表单

TanStack Query

TanStack Query 承担登录后工作区的服务端状态缓存,例如简历列表、范本目录、AI 任务进度与积分余额。

  • 默认的查询策略只缓存请求级与页面级数据;账户身份与 Cookie 会话仍走 Better Auth,不重复建模。
  • 缓存键全部使用强类型常量,避免散落的字符串拼接。

Zustand

Zustand 用于编辑器本地状态,例如当前选中的简历区块、布局配置、未保存草稿与命令面板状态。

  • 不在 Zustand 中保存从数据库拉取的列表数据,避免与 TanStack Query 形成两份真相源。

React Hook Form + Zod

React Hook Form 与 Zod 4 是表单的事实标准。

  • 校验 schema 在 validation.ts 中声明,运行时验证、数据库 schema 推导(通过 drizzle-zod)和 Server Action 入参校验复用同一份定义。
  • 服务端校验是最终权威:客户端通过不等于信任,载荷进入业务前必须再次通过 Zod 校验。

业务边界与服务端动作

next-safe-action

Next Safe Action 把输入校验、错误响应与上下文注入统一封装。src/lib/safe-action.ts 暴露的工厂注入数据库访问、当前会话与统一错误类型。

  • 破坏性操作(删除简历、移除范本、清空历史)使用 ConfirmPopover 二次确认后,再走 Safe Action。
  • 任何写入数据库或调用第三方服务的代码必须位于 Safe Action 或 src/features/<feature>/api/service.ts,不直接在页面或 Route Handler 中拼接业务规则。

AI 与内容生成

Vercel AI SDK 7

ai(ai@7)是 AI 调用的统一入口,由 @ai-sdk/react、@ai-sdk/google、@ai-sdk/anthropic 与 @ai-sdk/openai-compatible 共同支撑。

  • 模型注册表位于 src/ai/core/models,可在运行时按需切换 Gemini、Claude 与兼容 OpenAI 的服务,避免把供应商协议泄漏到业务层。
  • 结构化生成走 Output.object、Output.array,生成的简历字段、面试题与改写建议必须经过 Zod 校验后才能进入业务。
  • 流式返回通过 streamText、useChat 与项目内的 AI Elements 组件渲染,长对话使用 use-stick-to-bottom 让用户始终看到最新内容。

Streamdown

Streamdown 是为 AI 流式输出优化的 Markdown 渲染器,由 @streamdown/code、@streamdown/cjk、@streamdown/math、@streamdown/mermaid 等插件提供代码高亮、中文标点修正、数学公式与流程图能力。

  • 简历中的代码片段、面试问答、职位描述引用等场景共用一套渲染管线,避免不同页面重复实现。
  • 必须在 globals.css 中添加 @source "../node_modules/streamdown/dist/*.js"; 与各插件对应的 @source 行,Tailwind v4 才能识别 Streamdown 使用的工具类。

Gemini 与其他模型

当前实际调用的是 Google Gemini(通过 @ai-sdk/google)。Claude、OpenAI-compatible provider 已接入模型注册表,可在配置 GOOGLE_GENERATIVE_AI_API_KEY 之外通过替换环境变量切换。

  • AI 只负责“改写真实经历”的表达层,不参与简历事实层;最终落库的内容由用户在编辑器中确认。
  • 调用积分、暂计费与并发限流由 src/ai 与 src/integrations/credits 共同处理,避免模型调用绕过用量控制。

数据与持久化

Drizzle ORM

Drizzle ORM 定义 src/integrations/database/schema.ts 中的所有表与关系,并生成可编译为 SQL 的类型安全查询。

  • Schema 与迁移都和代码同仓库,迁移文件位于 drizzle/,可通过 pnpm db:generate 与 pnpm db:migrate:dev / pnpm db:migrate:prod 推进;不要在线上手动改表。
  • 查询按已认证用户标识限定范围,不信任请求体里的所有权字段。
  • drizzle-zod 把 Drizzle 表结构推导为 Zod schema,复用到 Server Action 与 API 校验中(例如 src/integrations/payment/types.ts 用 createSelectSchema 直接得到支付记录的运行时校验器)。

Cloudflare D1

D1 是基于 SQLite 的边缘关系数据库,绑定名 NEXT_TAG_CACHE_D1,用于简历、用户、积分、AI 设置与范本等主存储。

  • 在 Worker 中通过 OpenNext 的 getCloudflareContext() 拿到当前请求的 binding,本地开发依赖 wrangler d1 migrations apply --local。
  • D1 是 SQLite 方言,没有连接池概念,每次请求得到新 binding;要避免在热路径上做长事务。

LibSQL

@libsql/client 在脚本与本地工具中作为 D1 的 SQLite 兼容客户端出现,仅用于 Drizzle Kit、备份脚本与本地集成测试。

认证与会话

Better Auth

Better Auth 负责邮箱密码登录、Google 登录、邮箱验证与密码重置等账户能力。

  • 通过 Drizzle 适配器(drizzleAdapter(db, { provider: "sqlite" }))接入 D1,没有使用 Better Auth 的 D1 直连适配器,所有表都在 Drizzle Schema 中显式定义。
  • 服务端在任何敏感操作前重新读取 getSession(),不依赖客户端传入的角色或权限字段。
  • Cookie 配置与跨域策略集中在 src/features/auth 中,登录页、注册页与受保护路由都通过统一的中间逻辑处理跳转与回跳。

支付与商业能力

Creem(默认支付)

Creem 是默认的 Merchant of Record,托管全球税务与合规,提供订阅、一次性付费、积分包与 Webhook。

  • 单点集成即可在 190+ 国家合规收单;不需要自行处理 VAT、Sales Tax 与发票格式。
  • Webhook 入口在 src/integrations/payment,用于把订单状态同步到本地积分与权限模型。
  • 价格 ID、回调密钥和 Webhook 密钥通过 CREEM_* 系列环境变量注入,不要写入仓库。

Stripe(可选)

项目同时保留 Stripe 适配,便于需要按 Stripe 收款或在 Creem 覆盖范围之外的地区扩展;@stripe/stripe-js 用于浏览器端,Webhook 与订阅管理走对应的 src/integrations/payment 模块。

邮件与通知

Resend

Resend 提供事务邮件 API;DKIM、SPF、DMARC 与送达统计由其控制台统一管理。

  • 发件域名、收件 Audience 与 API Key 集中在 .dev.vars 与 Cloudflare Secrets 中,避免散落在多处。
  • Webhook 用于订阅确认、密码重置与简历分享通知,与前端 use-intl 钩子协作只发当前语言版本的邮件。

React Email

React Email 6 以 React 组件方式编写邮件模板,输出与主流收件箱(Gmail、Outlook、Apple Mail)兼容的 HTML。

  • 模板放在 src/integrations/mail/templates,通过 pnpm exec react-email dev 预览;邮件中的链接与按钮统一使用品牌色 #ffd621 与深墨色文字,避免在浅黄背景上写白色或低对比度文案。
  • next.config.ts 用 stub 模块替换 prettier/plugins/html 与 prettier/standalone,避免 React Email 的 render 在 Cloudflare Worker 中拖入 Prettier。

Sonner

Sonner 是项目内唯一的 Toast 组件,承载保存成功、导出完成、AI 改写被接受等即时反馈。

  • 不同语义(成功 / 失败 / 加载中 / Promise)共用同一套 API,避免页面引入多个 Toast 库。

对象存储

Cloudflare R2 + S3 兼容接口

头像、简历导出缓存等静态对象存储在 Cloudflare R2 中,通过 aws4fetch 与 S3 兼容协议访问,不依赖 Worker 的 R2 binding。

  • 桶名与区域写在 wrangler.jsonc 的 vars 中;访问密钥通过 wrangler secret put 注入,不要硬编码。
  • 上传链路在 src/integrations/storage,校验文件类型、大小与目录后生成预签名 URL,前端直传减少 Worker 流量。

文档与内容管理

Fumadocs 16

Fumadocs 16 与 fumadocs-mdx、fumadocs-ui 共同提供文档、博客与法律页的内容系统。

  • 内容源位于 src/content/project、src/content/blog、src/content/legal,本地新增 MDX 后由 source.config.ts 自动收录。
  • 文章内可通过 MDX 组件复用 src/components/ui 中的基础控件,避免另写样式。

Shiki

Shiki 在文档站与简历编辑器中提供语法高亮,使用与主题一致的 github-light / github-dark 配色,保证亮暗模式下都有正确对比度。

MDX

MDX 让文档可以直接嵌入 React 组件。@types/mdx、mdast-util-toc、remark 与 unist-util-visit 提供前置依赖与目录提取能力。

国际化

next-intl 4

next-intl 4 提供路由、消息加载与翻译键的自动补全;use-intl 是它的客户端补充包。

  • 当前默认且唯一公开的运行时语言是简体中文,URL 不使用 /zh 前缀,访问 /zh/* 或 /en/* 会被规范化到无前缀中文路径。
  • 所有用户可见文案集中放在 messages/*.json,新增文案必须同步修改 messages/zh.json 并避免散落到 JSX 中。

数据可视化与辅助组件

  • Recharts 3:用于积分趋势、订阅概况与后台统计的图表;图表配色与设计令牌一致,不引入与品牌色冲突的第二主色。
  • Number Flow:用于积分余额、价格、简历完成度等数字的过渡动画,比单纯 setText 更有可读性。
  • use-stick-to-bottom:AI 流式对话、简历改写预览与长列表自动滚动到底端。
  • qrcode:用于简历公开分享链接与登录二维码。
  • html-to-image:把简历预览区域导出为 PNG。
  • pdfjs-dist:解析用户在导入阶段上传的 PDF 简历与职位描述。
  • sanitize-html:清洗粘贴到简历与简历中的富文本,阻止 script、危险属性与外部资源。
  • @tanstack/react-table:后台表格(用户管理、积分流水、范本目录等)使用 headless 表格核心,按列排序、筛选、分页由 src/components/admin/* 维护,配合 TanStack Query 拉取数据。
  • html-react-parser:把外部简历与职位描述的 HTML 字符串转成 React 节点,配合 sanitize-html 在简历预览与 AI 对话中回放富文本。
  • fflate:压缩/解压库,用于简历附件(.docx、模板包等)的 zip 解析与生成(src/features/career/files/resume-file.ts)。

通用工具与基础设施

  • uuid v4/v5:长 ID 生成;支付流水、积分交易、AI 示例消息 ID 等场景要求稳定的全局唯一键(src/integrations/payment、src/integrations/credits、src/components/ai/chat)。
  • nanoid:短 ID 生成;AI Elements 的 prompt-input 用它给附件与消息片段打本地键,避免上传到服务端。
  • ufo:URL 工具集;src/middleware.ts 用 withQuery 给跳转链接附加查询参数,src/integrations/payment/providers/creem.ts 用 joinURL 拼接 Creem 回调 URL。
  • deepmerge:在 src/i18n/ 中深度合并基础消息模块与语言叠加模块,使部分缺失的翻译自动回退到默认文案而不报错。
  • cookie:解析 Cookie 头,Better Auth 与 src/i18n/lib/request-locale.ts 的语言探测都依赖它。

部署与基础设施

OpenNext for Cloudflare

@opennextjs/cloudflare 把 Next.js 构建产物适配到 Cloudflare Worker 运行时,保留 App Router、Server Components 与 ISR 等行为。

  • pnpm opennext:build 生成 .open-next/worker.js,pnpm preview 在本地用真实 workerd 预览,pnpm deploy 部署到生产。
  • D1、R2、KV 与 Durable Objects 都通过 getCloudflareContext() 在 Worker 内获取;本地 next dev 拿不到真实绑定,需要在 preview 与 deploy 后验证依赖绑定的逻辑。

Cloudflare Workers / KV / Durable Objects

  • Workers:应用运行时的宿主;通过 nodejs_compat 与 nodejs_compat_populate_process_env 开启 Node.js API 兼容。
  • KV(NEXT_INC_CACHE_KV):增量缓存与会话相关键值存储。
  • Durable Objects(NEXT_CACHE_DO_QUEUE):用于 OpenNext 的队列与一致性协调。

Wrangler

Wrangler 是 Cloudflare 的部署与本地工具。仓库预置的脚本包括:

  • pnpm dev:本地 Turbopack 开发。
  • pnpm opennext:build:构建 Cloudflare Worker 产物。
  • pnpm preview:本地用 workerd 预览。
  • pnpm deploy:部署到生产。
  • pnpm db:migrate:dev / pnpm db:migrate:prod:本地与远程 D1 迁移。
  • pnpm cf-typegen:刷新 cloudflare-env.d.ts 中的 Cloudflare 绑定类型。

质量与工具链

Biome 2.5

Biome 2.5 同时承担格式化与 lint,速度优于 ESLint + Prettier 组合。规则以 biome.json 为准,pnpm lint 与 pnpm lint:staged 在本地与 CI 中执行。

  • 不在 Biome 之外再叠加 Prettier,避免两套格式化器产生冲突。
  • 修改行为时同步更新注释与文档;自明的 UI 包装与局部函数不强制注释。

Drizzle Kit

Drizzle Kit 用于生成迁移与应用迁移;pnpm db:studio 提供本地 Schema 浏览器。

Node 测试与内置能力

scripts/check-storage-boundaries.mjs 与 src/test/storage/*.test.mjs、src/test/scripts/*.test.mjs 在 pnpm check:storage 中执行,使用 Node 内置 --test 框架;新增存储边界与脚本需要在测试中体现。

隐私与合规

vanilla-cookieconsent

vanilla-cookieconsent 提供 GDPR 合规的 Cookie 同意层。Google Analytics、Umami、Plausible 等分析供应商的配置集中在 src/config/analytics.ts,同意前的脚本加载逻辑由同意组件统一控制。

选型原则小结

  • 真实优先:所有技术都为“让真实经历更容易整理”这件事服务;不为追新而引入新库。
  • 边界清楚:AI、积分、支付、邮件与存储各自独立于业务边界,第三方升级不会污染业务层。
  • 边缘优先:数据、AI 之外的渲染、缓存与会话状态尽量贴近用户,部署在 Cloudflare 全局网络。
  • 类型贯穿:Schema、API 契约、AI 输出与表单校验复用同一套 Zod 校验,编译期捕获问题。
  • 可被 AI 改写:组件代码留在仓库里、Tailwind 主题用语义令牌、API 边界清晰,让 AI 编程工具能够理解、改写并继续在现有结构上工作。

想深入了解每一层的目录组织与运行机制,看项目结构;了解 API 拆分与服务边界,看API 分层;了解数据模型与迁移流程,看数据库。

本页目录