# Client Bootstrap（技术计划）

## 1. 计划目标

基于 `spec.md` 的约束，落地一套可执行的客户端工程初始化方案，保证：

- 开发者可本地启动与联调
- dev/prod 环境区分清晰
- i18n 支持 CN/EN/ES/PT/TC 并支持动态切换
- 目录结构标准化，可持续扩展
- EAS Build iOS 打包流程可执行

## 2. 默认技术决策（本计划采用）

- **Node.js**：建议 **20.x LTS**（最低 **18.x LTS**）
- **包管理器**：pnpm（建议 **9.x**，最低 **8.x**）
- **路由**：优先采用 `expo-router`（使用 `app/` 目录）
  - 若项目已使用 React Navigation，则保留 `src/navigation/` + `src/screens/` 的方案（见“可替代方案”）
- **i18n**：`i18next` + `react-i18next` + `expo-localization`
- **环境变量**：`.env.dev` / `.env.prod` + `EXPO_PUBLIC_` 前缀
- **网络层**：统一封装 `src/services/`（Axios 或 Fetch 二选一，先按 Axios 预留结构）
- **状态管理**：Zustand（与现有 `spec.md` 一致）

## 3. 目录与模块规划

### 3.1 顶层目录（目标态）

- `app/`：路由入口（expo-router）
- `src/`：业务代码
  - `src/features/`：按功能域拆分（push/widget/cards）
  - `src/services/`：API 封装
  - `src/store/`：状态管理
  - `src/i18n/`：多语言资源与初始化
  - `src/components/`、`src/hooks/`、`src/utils/`、`src/constants/`、`src/types/`
- `assets/`：静态资源
- `app.json` 或 `app.config.ts`：Expo 配置与环境区分入口
- `eas.json`：EAS 配置（如启用）

### 3.2 关键模块拆分

- **i18n 模块**（`src/i18n/`）
  - `index.ts`：初始化（默认语言、回退语言、资源注册、与系统语言对齐）
  - `locales/*.json`：`zh-CN/en/es/pt/zh-TW` 五份资源
  - （可选）`types.ts`：语言码类型与 key 约束
- **Push 模块**（`src/features/push/`）
  - 权限申请
  - Token 获取与上报（接口对齐点在联调阶段确认）
- **Widget 模块**（`src/features/widget/`）
  - 数据读取与缓存策略（先定义接口与缓存层，再落地 iOS 扩展实现）
- **Cards 模块**（`src/features/cards/`）
  - 卡片滑动交互组件与数据模型

## 4. 环境区分与配置计划

### 4.1 环境变量与模板

- 提供 `.env.example`（至少包含 `EXPO_PUBLIC_API_BASE_URL`、`EXPO_PUBLIC_ENV`）
- 本地开发使用 `.env.dev`，生产构建使用 `.env.prod`
- README 明确：
  - 真机联调时 `localhost` 替换为局域网 IP
  - 环境变量不入库

### 4.2 Bundle ID 与构建标识

- dev：`com.damer.mindfulness.dev`
- prod：`com.damer.mindfulness`
- 在 `eas.json` 中按 profile 区分环境变量注入与 bundle id（当工程文件落地后执行）

## 5. 多语言（i18n）落地计划

### 5.1 语言码与策略

- 支持：`zh-CN` / `en` / `es` / `pt` / `zh-TW`
- 默认：优先使用用户当前**设备语言**（在支持列表内时生效）
- 回退：设备语言不在支持列表时，回退到 `zh-CN`（或团队指定的默认语言）

### 5.2 动态切换与持久化

- 提供“语言设置”入口（后续 UI 落地），允许用户手动切换语言
- 切换语言后写入本地存储（例如 AsyncStorage）
- App 启动时语言选择优先级：
  - ① 用户设置（若存在）
  - ② 设备语言（在支持列表内）
  - ③ 默认回退（`zh-CN` 或团队指定默认）

### 5.3 文案规范

- key 点分层：`common.*`、`push.*`、`cards.*`、`widget.*`
- 插值：`{{name}}` 等形式统一
- 禁止代码内拼接长句（降低翻译成本）

## 6. 推送与小组件（一期能力）计划

### 6.1 推送

- 客户端：权限 -> token -> 上报
- 后端：保存 token -> 定时任务 -> 推送内容配置
- 联调产出：token 上报接口、字段、鉴权、错误码约定（后续任务阶段细化）

### 6.2 小组件

- 先定义“数据模型 + 缓存策略 + 刷新策略”的规范
- 明确限制：刷新频率受 iOS 系统控制，文档中强调体验目标为“尽力而为”

## 7. 执行步骤（落地顺序）

1. **补齐客户端 README**：确保启动/环境/i18n/目录/EAS 指引完整（已完成基础版本）
2. **初始化 Expo 工程（如尚未提交）**：生成 `package.json`、`app.json/app.config.*`、`assets/` 等
3. **建立标准目录结构**：创建 `app/`、`src/` 与各子目录
4. **接入 i18n 基座**：完成语言码、资源文件、初始化与切换策略
5. **接入环境变量读取**：确保 dev/prod 可影响 API Base URL
6. **预留 push/widget/cards 的模块骨架**：先放类型与接口占位，等待业务实现
7. **EAS 配置与 iOS 构建跑通**：编写 `eas.json` 并验证 development profile 构建链路

## 8. 可替代方案（不影响目标的变体）

- **路由不使用 expo-router**：使用 React Navigation
  - 目录：`src/navigation/` + `src/screens/`
  - 仍保留 `src/features/`、`src/services/`、`src/i18n/` 等不变
- **网络层使用 Fetch**：保持 `src/services/` 统一封装，替换实现即可

## 9. 风险与回滚策略

- **真机联调失败**：优先排查局域网 IP、代理/防火墙、后端端口映射；必要时使用内网穿透
- **推送配置复杂**：先在 dev profile 跑通 token->推送最小闭环，再扩展定时策略
- **小组件刷新不稳定**：在 UI/产品层面接受系统限制，并通过缓存提升体验

