# TVU 消费产品 · 项目结构通用规则

> 真源：`tvu-design-system/templates/consumer-product/PROJECT_STRUCTURE.md`
> 适用：所有消费 TVU 设计系统的产品仓库（MicroApps + 未来新项目）
> 标杆参考：`MicroApps/` 仓库布局

本规则定义 TVU 消费产品仓库的**根目录骨架**，确保多产品间结构一致、onboarding 快、AI 协作 cwd 假设稳定。

## 两种变体（Setup 时必选其一）

消费产品按是否承载代码分两种结构：

| 变体 | 适用场景 | 典型产品 |
|---|---|---|
| **A · Design + Code（默认）** | 既画 mockup 又跑代码的标准消费产品 | MicroApps、未来 SaaS 前端 |
| **B · Design-only（纯设计协作）** | 只放 UX 设计 / 需求 / 复盘 / Figma 链接，代码住别处 | TPC-Service（TVU Pack Control 设计仓） |

**两种变体共享**：`README.md` / `.gitignore` / `.claude/` / `docs/` 全套（5 子目录 + Marp slides 模板）
**只有变体 A 才有**：主应用目录（`vue-app/` 等）+ `package.json` / `vite.config.js` / `eslint.config.js` / `scripts/link-tvu-ds.mjs` / `.marprc.yml`（变体 B 如需 Marp 导出可后补）

**Setup 时 AI 必问用户**："你要建变体 A（Design + Code）还是 B（Design-only）？"用户拍板后，runbook 跳过对应变体不适用的步骤（详见 `SETUP_GUIDE.md` Step 0）。

**变体演化**：变体 B 后续若需加代码，**不强制变成 A**——保留 design-only 定位，代码住别处更清晰；只有用户明示"我要把代码也搬进来"才升级。

## 必备目录与文件（变体 A · Design + Code）

```
<consumer-product>/
├── README.md                       ← 项目介绍（产品定位 / 怎么 run / 怎么部署）
├── .gitignore                      ← 含 Marp dist / node_modules / .env / vue-app/dist 等（从 gitignore.fragment scaffold）
├── .claude/                        ← 项目级 Claude Code 配置（gitignored）
│   ├── skills/                     ← 6 个 symlink 到 tvu-design-system skills（由 setup-tvu-consumer 建）
│   └── settings.json               ← additionalDirectories 含 tvu-design-system 路径
├── docs/                           ← 文档体系（5 子文件夹标准布局）
│   ├── README.md                   ← docs 索引
│   ├── {PRODUCT}_PRODUCT_CONTEXT.md  ← 产品长青文档（产品定位 / IA / 客户场景）
│   ├── retrospects/                ← AI 协作复盘（含 Marp slides）
│   ├── handoffs/                   ← session 交接
│   ├── audits/                     ← F1 走查
│   ├── specs/                      ← 设计 spec / Figma prompt
│   └── decisions/                  ← ADR
└── <app-dir>/                      ← 主应用目录，详见下节
```

## 变体 B · Design-only（纯设计协作）

无主应用目录、无 vite 配置、无 `package.json`、无 `scripts/`。根目录骨架退化为：

```
<consumer-product>/
├── README.md                       ← 项目介绍 + 明示"不含代码 / 代码住别处"+ 关联 Figma 真源链接
├── .gitignore                      ← 从 gitignore.fragment scaffold（vue-app/dist 部分不会被命中也无害）
├── .claude/                        ← gitignored
│   └── settings.json
└── docs/                           ← 5 子目录布局，跟变体 A 完全相同
    ├── README.md                   ← docs 索引（提示"本项目省略 code-related 子结构"）
    ├── {PRODUCT}_PRODUCT_CONTEXT.md  ← 产品长青文档
    ├── retrospects/                ← 含 README + RETROSPECT_FORMAT + _template.slides.md
    ├── handoffs/.gitkeep
    ├── audits/.gitkeep
    ├── specs/.gitkeep
    └── decisions/.gitkeep
```

**为什么保留 `.gitignore` 即使没有 vue-app**：fragment 里 `vue-app/dist/` 这条对纯设计仓无害（命不中目录即 noop）；保留同一 fragment 避免 maintain 两份。

**典型用法**（来自 TPC-Service 2026-05-26 实证）：
- `docs/specs/YYYY-MM-DD-<feature>-spec.md` ← 每次迭代需求 + 对应 Figma URL + node-id 写在头部
- `docs/retrospects/` ← AI 协作复盘
- `docs/decisions/` ← 设计决策 ADR
- 产品代码 repo 路径登记在 `TPC_PRODUCT_CONTEXT.md`「关联资源」段

## 主应用目录约定（变体 A 专属）

**默认目录名**：`vue-app/`（Vue 3 + Vite 项目，最常见）
**允许**：`react-app/` / `web-app/` / `<custom>` — 但**只允许一个主应用目录**

```
vue-app/
├── README.md                       ← 应用专属说明（可选）
├── package.json                    ← 含 vite-plugin-singlefile 依赖
├── vite.config.js                  ← singlefile 配置（详见 setup-tvu-consumer SKILL.md Step 4）
├── eslint.config.js                ← ESLint 配置（含 TVU 规范层 eslint.config.fragment.mjs；接线模式按场景，见 SETUP_GUIDE Step 2.6）
├── index.html                      ← Vite 入口
├── src/                            ← 应用源码
├── public/                         ← 静态资源
├── dist/                           ← 构建产物（gitignored，部署 server 上 build）
└── node_modules/                   ← gitignored
```

## 部署约定（重要）

消费产品**默认部署到 ux_server**（`product-demo.tvustream.com`），借助 Caddy 静态托管。

**核心约束**：
- 必须用 `vite-plugin-singlefile` → 构建产物是**单一 `dist/index.html`**（无 `assets/` 子目录）
- 触发理由：deploy-hook 的 singlefile alias 机制依赖 `dist/` 不含 `assets/` 才会激活
- 详见 `~/Documents/ux_server/SETUP_PROGRESS.md` 的"开新项目"段

**禁止**：
- ❌ code-splitting / dynamic import（破坏 singlefile）
- ❌ 把 `dist/` commit 进 git（部署 server 自 build）
- ❌ 多个独立 Vite project（用 monorepo 或合并）

## 项目根目录的自由区

以下内容**允许放根目录**，不属于骨架：
- `<product>-*.html` — 静态 mockup demo（如 `microapps-console-demo.html`）
- `tmp/` — 本地 scratch，**必须 gitignore**
- `*.txt` 测试文件（如 `DEPLOY_TEST.txt`）— deploy 调试用，可入 git
- `LICENSE` / `CHANGELOG.md` — 标准开源元数据
- `.editorconfig` / `.prettierrc` — 代码风格配置

## 反模式（不要这样做）

| ❌ 反模式 | ✅ 正确做法 |
|---|---|
| 主应用直接放 root（无 `vue-app/` 子目录） | 主应用始终在子目录，root 留给 docs/ + 项目级元数据 |
| docs/ 平铺所有文档（无子分类） | 强制 5 子文件夹分类（retrospects / handoffs / audits / specs / decisions） |
| 复盘只有 `.md` 不配 `.slides.md` | 复盘默认双文件，Marp slides 给同事 + 领导分享 |
| 把 `.claude/` commit 进 git | 始终 gitignored（symlink 不跨机器有效，settings 含本地路径） |
| 多 vite project 共存 root | 单一主应用目录；多产品请拆 repo |
| 用 Vite 默认 multi-file 输出部署到 ux_server | 强制 singlefile（详见 setup-tvu-consumer Step 4） |

## 怎么验证项目符合本规则

`setup-tvu-consumer` skill 跑完后会输出结构检查报告。手动跑：

```bash
# 1. 必备目录都在？
test -d docs/retrospects && test -d docs/handoffs && test -d docs/audits && test -d docs/specs && test -d docs/decisions && echo "✅ docs 骨架完整"

# 2. .claude/ 配齐？
test -L .claude/skills/tvu-design-mockup && echo "✅ TVU skills symlinked"
test -f .claude/settings.json && echo "✅ settings.json 在"

# 3. vite singlefile？
grep -l "vite-plugin-singlefile" */vite.config.{js,ts} 2>/dev/null && echo "✅ singlefile 配置在"
```

## 演进策略

本规则改动 → 改 `tvu-design-system/templates/consumer-product/PROJECT_STRUCTURE.md` 真源 + 更新 `setup-tvu-consumer` SKILL.md 检查逻辑。

**已存在 consumer 不强制同步**——只在新 setup 时应用新规则。老项目若需迁移，由用户主动跑 setup-tvu-consumer 的"迁移模式"（待补 skill 选项）。
