项目结构
了解 Expo 模板的目录与模块边界。
Expo 模板是一个功能完备的 Expo starter,所以目录更像完整 app
而不是组件库:app/ 放路由,components/ 放可复用 UI,lib/ 放服务模块,
Supabase 后端 artifacts 与客户端一起交付。
目录树
路由边界
app/_layout.tsx 负责全局 providers、gates、root Stack,并把 paywall
和 redeem-code 配成 modal。app/(auth)/ 是未登录 auth stack。
app/(tabs)/ 是主 shell,包含四个可见 tab:Home、Components、Showcase、Me。
其他 app/ 文件是 drawer、feature card、deep link 或 modal 打开的 pushed screens。
Expo Router 的特殊文件也是约定的一部分:
| 文件 | 作用 |
|---|---|
app/+html.tsx | pnpm web / static web output 的自定义 web document |
app/+not-found.tsx | typed-routes 的未知 URL fallback |
app/component/[slug].tsx | Component gallery 详情页 |
app/(tabs)/home-paywall.tsx | href: null 的隐藏 tab-context paywall 页面 |
app/(tabs)/home-redeem-code.tsx | href: null 的隐藏 tab-context redeem 页面 |
模块边界
| 区域 | 放在哪里 |
|---|---|
| Screen composition | app/<route>.tsx |
| Auth forms | components/auth/ |
| 可复用 primitives | components/ui/ |
| 跨 screen gates | components/*-gate.tsx;需要状态时放进 lib/*Provider |
| Server-state calls | lib/ 中的小模块,再由 screens/providers 使用 TanStack Query |
| 本地偏好 | lib/ 中的 provider module,底层使用 AsyncStorage、SecureStore 或 localStorage |
| i18n copy | lib/i18n/en.json 与 lib/i18n/zh.json |
| 仅 showcase 使用的 demo catalog | lib/showcase/ 与 app/showcase/ |
| Supabase schema/functions | supabase/migrations/ 与 supabase/functions/ |
| 生成的 DB 类型 | pnpm gen:types 生成的 types/database.ts |
lib/ 是事实上的 service layer。profile.ts、sample-uploads.ts、
referrals.ts、deep-links.ts、network.ts、app-update-config.ts 等文件
把 feature logic 留在 route component 外面。
添加功能
添加 lib/ module
把 Supabase calls、数据映射、retry helpers、URL building 放在
lib/your-feature.ts。如果使用 TanStack Query,在 lib/query.tsx 添加
queryKeys。
添加 screen 与导航
在 app/ 创建 route。只有当 route 需要被外部打开时,才在
app/(tabs)/_layout.tsx、Home cards 或 lib/deep-links.ts allow-list 中加入口。
添加 copy 与可复用 UI
产品文案同时写入两个 locale 文件。如果 UI 会被多个地方复用,抽到
components/ 或 components/ui/,不要从另一个 route import screen code。
