产品研发规范库

技术选型与落地

本参考给出新 TypeScript 全栈项目的推荐基线。它不是要求把所有技术一次装齐的清单:只有技术确实让当前用户任务、可靠性或交付更简单时才采用。版本以新项目自己的锁文件和 Node LTS 兼容性为准,不复制参考项目的版本、镜像、地址或环境取值。

选择原则

先确定首条完整用户链路,再选为该链路减少复杂度的技术。需要账号、数据或业务副作用的产品,Web 界面、API、业务服务、数据库和必要的真实开发数据源必须一起落地。任何框架都不能替代这一链路;前端 mock、静态卡片和假 API 响应只可用于明确标识的短期演示。

问题 优先选择 采用条件与边界
Web 与服务端应用 Next.js App Router + TypeScript 默认保持一个全栈模块化单体。Server Component 用于服务端读取和首屏组合;Client Component 只覆盖真实交互边界。不要为每个页面机械添加客户端状态或 API 层。
小型项目的管理后台 同一 Next.js 应用中的受保护路由 管理页面与主产品共用域名、认证和业务服务;可使用 /admin 等清楚入口。每个后台读取和写入都在服务端检查权限,不能靠隐藏菜单。没有独立组织、部署或安全边界时,不建第二个后台项目、子域或 BFF。
界面基础与组件 Tailwind CSS + shadcn/ui 使用统一 token 和少量语义样式;按当前界面需要引入组件,组件代码归项目所有并可直接调整,不预装完整组件集或复制多套主题。
界面绑定的服务端操作 Server Action 调用业务服务 适合只由当前 Next.js 界面触发的 mutation;Server Action 负责输入与会话适配,不承载可复用业务规则。
对外或多客户端 HTTP API Next.js Route Handler;边界成熟后可独立 API 路由只负责可信身份、协议和响应,调用同一业务服务。只有独立部署、非 Web 客户端、WebSocket 或运行时约束成为事实时才拆出 Hono 等独立 API。
关系数据与在线迁移 PostgreSQL + Drizzle 或 Prisma ORM 二选一;Schema、迁移和连接放在数据库边界。提交生成迁移并审阅实际 SQL,不改写已应用迁移。
本地与生产封装 Docker 本地优先容器化 PostgreSQL 等有状态依赖,应用可直接用 pnpm 运行;生产构建不可变应用镜像。固定外部镜像版本或 digest,秘密配置不得进入构建上下文或镜像层。
跨实例缓存、限流、锁、队列或 Pub/Sub Redis 只有单进程内存或 PostgreSQL 不能正确、简单地满足已确认需求时引入。先写明数据归属、TTL/失效、重试与降级;未使用时不启动空 Redis 服务。
浏览器存在复杂的客户端服务端状态 TanStack Query 仅当客户端频繁刷新、乐观更新或跨组件复用远端状态带来实际收益时使用;简单读取优先使用 Next.js 的服务端数据流。
多应用确需共享契约或纯逻辑 pnpm workspace + 边界清晰的共享包 只有出现真实的第二个应用或独立包消费者时才建立;请求/响应 schema、仅编译期类型和无状态纯函数分开,不因目录整齐而拆包。
确有可靠后台工作 PostgreSQL 队列或 Redis 队列,按现有基础设施选择 仅当任务需要跨请求持续执行、调度或可靠重试时引入;先复用项目已有的可靠存储,不为一个简单异步动作同时增加 Redis 和专用 Worker 平台。
明确要求模型对话与受控工具 AI SDK + 服务端 OpenAI 兼容适配器 只为 Agent 产品建立一条模型工具循环;不在同一产品叠加 Mastra 或第二个运行时,除非已有实现无法满足明确需求。
明确需要成熟聊天展示 assistant-ui ExternalStoreRuntime 只替换对话视图与输入体验;会话、草稿、发送锁、私有附件、工具执行和持久化仍由应用控制。
用户上传或运行时文件/图片 OSS/S3 兼容对象存储 生产环境不写 Git 或应用本地目录。服务端先鉴权再签名、读取或处理;数据库保存对象键与归属等元数据,不把文件 URL 当作权限。
公网入口与低中断发布 反向代理 HTTPS + 同源 /api + 按需蓝绿候选 应用端口仅对私有网络开放;蓝绿仅在低中断切换有实际收益时采用。

Drizzle 与 Prisma 的选择

二者都能与 PostgreSQL 组成可靠的数据层,选择目标是让团队只维护一套 Schema、迁移和查询心智模型。

选择 更适合的情况 需要守住的边界
Drizzle(默认优先) 团队熟悉 SQL,希望类型安全同时保持查询与迁移透明,或需要精确控制 PostgreSQL 能力。 生成迁移后审阅 SQL;复杂查询留在数据库边界,不把 ORM 表结构直接当成业务 API。
Prisma 团队更看重声明式 Schema、生成 Client、Studio、成熟生态与快速建模,且其迁移和查询能力满足当前需求。 同样审阅生成 SQL;不要用 Client 便捷性绕过业务服务、授权、事务或在线迁移规则。

新项目默认选其中一个并贯彻到底。仅在正在执行有明确退出条件的 ORM 迁移时,才允许两者短期共存。

前端与后端的真实边界

浏览器只提交用户输入、受校验的对象引用、请求标识和明确许可;不接受客户端提供的用户 ID、历史正文、账号归属、工具结果、费用或完成证据。服务端是身份、会话、消息、工具执行和业务记录的权威来源。

按知识归属组织服务。例如计划、文件、账号或练习各自提供少量清晰操作,内部封装访问检查、锁、版本、事务和失败清理。HTTP API、Worker 与 Agent Tool 调用同一服务,不能由每个入口拼装“先查 owner、再加锁、再写入”的固定顺序。

Next.js 客户端应直接试用受影响的交互。保存、上传、操作卡片或对话中的动作必须通过 Server Action 或 Route Handler 到达真实业务服务,并以服务端结果渲染成功、冲突或错误。不要先搭“组件市场”“状态管理层”“性能中心”“统一缓存平台”再寻找用途。

仅在对话产品中的取舍

只有用户明确要求复杂、成熟的聊天输入和消息展示时,才可以采用 assistant-ui 的 ExternalStoreRuntime;它不是服务端运行时,也不应执行客户端 Tool。保留应用自身对下列事实的控制:

  • 服务端会话历史、用户草稿、附件上传和发送锁;
  • 提交快照、失败后的草稿恢复、真实网络取消和页面导航连续性;
  • 私有附件、业务结果和工具活动的自定义展示;
  • 输入法组合、只有附件的发送、键盘行为与焦点恢复。

升级此类聊天依赖时,验证输入法、取消、失败恢复、私有附件、工具结果、刷新后历史一致性和窄屏布局。包体积警告是测量信号而非自动拆包授权;先确认用户可感知的加载或交互问题。

数据、异步和性能

写操作使用请求 ID 或由服务端生成的稳定幂等键;唯一约束、事务和版本号表达可验证的不变量。重复提交、并发编辑、取消和响应丢失时,返回明确结果而不重复制造业务副作用。

跨数据库与文件存储的操作没有天然原子事务。数据库提交不确定时,先确认是否已有持久引用,再决定是否清理文件;无法确认时保留对象和诊断,不能以删除用户数据来“回滚”。

性能优化以证据开始:统计重复请求、查询范围、首屏或交互等待,以及按需存在的模型上下文规模和成本。优先移除重复请求、全量读取和无关上下文;缓存、并行、索引、队列或拆服务必须说明它解决的已测问题、数据归属和失效方式。不要预留通用性能模块。

需要单独决策的技术

以下技术可能适合特定产品,但不得因为参考项目存在就默认创建:短信身份服务、对象存储、语音/图片模型、公开联网检索、向量检索、长期记忆、任务续接、SEO 公开页面、蓝绿槽、Worker、微服务和第三方插件执行。其中对象存储在没有图片/文件功能时不创建;产品一旦包含用户上传或运行时文件,它就是替代 Git 和应用本地目录的必要持久化边界。

每项被选中时,在对应领域文档写明:当前解决的问题、服务端所有权和数据边界、环境配置来源、失败/重试/成本语义、实际验证和未验收部分。短信身份服务的具体做法见新通短信登录;需要 Agent 时见单 Agent 与受控工具。

产品进一步需要同源 BFF、公开 Agent API、跨端能力定义或可观测性时,补充阅读IELTS Buddy 的扩展工程经验。