00 / 00

项目架构

了解这套模板的文件结构,知道你的代码应该放在哪里

顶层目录是干什么的

这套模板是一个 monorepo(单一代码仓库,一个 git 仓库里放了多个项目)。打开项目根目录,你会看到:

01mvp/
├── products/
│   ├── 01mvp/
│   │   ├── apps/web/       # 01MVP Web 站点
│   │   └── packages/       # 01MVP 产品内复用能力
│   └── onesay/
│       ├── apps/web/       # OneSay Web 站点
│       ├── apps/desktop/   # OneSay 桌面端
│       ├── apps/mobile/    # OneSay 移动端
│       └── packages/       # OneSay 产品内复用能力
├── packages/               # 跨产品共享包
│   ├── ui/                 # Web UI 原语
│   ├── email/              # 邮件 provider 和模板
│   ├── logger/             # 结构化日志
│   ├── config/             # 共享 env schema
│   └── ...                 # 其他跨产品能力
├── tools/             # 开发工具和脚本

简单理解products/<product>/apps = 具体端,products/<product>/packages = 该产品内部复用能力,根目录 packages = 多个产品都能复用的通用零件。

为什么用 products 结构

如果你持续做 Web coding,很快就不会只有一个 app。你可能会同时维护产品官网、后台、移动端、桌面端、实验项目、模板项目和若干内部工具。把它们拆成很多 GitHub 仓库,看起来边界清楚,但通用能力会不断复制:UI 原语、登录、配置、日志、邮件、存储、AI workflow、Agent Skills、代码规范和部署经验都会散落在不同仓库里。

这套结构把所有项目放在一个长期维护的 monorepo 里:

  • products/<product> 承载一个具体产品,产品内可以继续拆 apps/*packages/*
  • 根目录 packages/* 只放跨产品通用能力,保持产品无关。
  • 根目录 .agents、Skills、工具链和规范由整个仓库共享。
  • 每个产品有自己的 config、API、DB、auth 和前端入口,默认不会影响其它产品。

这样你可以在一个仓库里持续积累自己的工程系统:新产品复用成熟能力,老产品保留隔离边界,AI 编码工具也能读到同一套规则和上下文。

我的代码应该放在哪?

你的情况放这里
页面路由products/01mvp/apps/web/src/routes/
页面级组合组件products/01mvp/apps/web/src/pages/
业务功能组件products/01mvp/apps/web/src/features/
只在 web 应用使用的工具逻辑products/01mvp/apps/web/src/lib/products/01mvp/apps/web/src/server/
这个功能只属于 01MVP,但多个 01MVP app/package 会用products/01mvp/packages/ 下对应的包里
这个功能多个产品都要用根目录 packages/ 下对应的包里
shadcn/ui 组件(按钮、弹窗等)用命令加到 packages/ui/不要手改

shadcn/ui 是什么? 一个预制 UI 组件库,提供了按钮、输入框、对话框等 80+ 种零件。通过命令 vpx shadcn@latest add <组件名> 来添加。

包(Package)是怎么工作的

每个 packages/products/<product>/packages/ 下的文件夹是一个独立的包(package)。关键规则:

  1. 每个包有自己的 package.json
  2. workspace:* 引用内部包 — 意思是"就用本仓库的版本,别去网上下载"
  3. 入口文件是 src/index.ts — 包对外提供的功能从这里导出
  4. 产品包可以引用同产品包和根共享包 — 比如 @01mvp/api 可以引用 @01mvp/db@01mvp/auth@repo/email
  5. 根共享包不要引用产品包@repo/email@repo/ui@repo/logger 这类包必须保持产品无关

Product Package 和 Global Package 怎么分

放置位置适合内容例子
products/01mvp/packages/*只属于 01MVP,但会被 01MVP 多个端或模块复用apiauthdbconfigpayment
products/onesay/packages/*只属于 OneSay,但会被 OneSay 多个端或模块复用apiauthdbconfigclient
packages/*多个产品都可复用,不能带产品业务假设emailuiloggerstorageconfig

以 email 为例:发信 provider、模板渲染、发送结果类型放在 packages/email;某个产品要发什么邮件、邮件发给谁、使用什么默认发件人,放在产品自己的 apiauthconfig 包里。

UI 组件三层结构

packages/ui/         ← 第一层:shadcn 原装组件
    ↓                   只通过命令添加,不要手动改
products/01mvp/apps/web/src/features/  ← 第二层:业务功能组件
    ↓                   登录、导航、反馈等可复用页面能力
products/01mvp/apps/web/src/pages/     ← 第三层:页面级组合

一句话:通用 UI 原语留在 packages/ui,业务模块放 features,页面拼装放 pages 或具体 route。

关键规则速查

记住这几条,能避免大部分结构性错误。

  • ✅ 改网站功能 → 去 products/01mvp/apps/web/src/
  • ✅ 改产品内共用逻辑 → 去 products/01mvp/packages/
  • ✅ 改跨产品共用逻辑 → 去根目录 packages/
  • ✅ 改 API → 优先改 products/01mvp/packages/api/src/routers,Hono 特殊路由放 products/01mvp/apps/web/src/server
  • ✅ 改数据库结构 → 改 products/01mvp/packages/db/src/schema,在 products/01mvp 下跑 vpr db:generatevpr db:migrate
  • ✅ 加共享环境变量 → 改 packages/config;加产品默认值或覆盖 → 改 products/01mvp/packages/config
  • ❌ 不要手动改 packages/ui/ 里的组件
  • ❌ 不要把单网站代码放到 packages/
  • ❌ 不要把密钥密码写到 packages/

下一步

这篇文档有问题?