概览
一个功能完备的 Expo 与 React Native 启动模板,内置 Supabase、RevenueCat、应用服务和 EAS 分发流程。
Expo (React Native) 模板面向希望用一套 TypeScript 代码覆盖 iOS、 Android 和 Web 的团队。它内置 Expo Router 导航、Supabase 后端、 RevenueCat 购买流程、账号绑定权益、分析、崩溃上报、启动门禁、推送收件箱、 深度链接,以及一个可以在产品页面成型后删除的演示区。
模板提供的应用基础设施真实可用且已集成完毕。部分界面是 Example 或 Removable demo,发布前应替换成你的产品流程。
Expo 模板是跨平台移动端原版。Swift 和 Kotlin 模板从它移植而来,但原生栈已经
分化,所以本组文档只描述 ../soar-expo 的 TypeScript 源码。
配置模型
应用从 EXPO_PUBLIC_* 读取公开客户端配置,并通过 app.config.ts 生成构建
期原生配置。Supabase URL 和 anon key 是最先要设置的两个值,因为
lib/supabase.ts 会在模块加载时创建客户端,缺少任意一个都会抛错。其他
Provider 会检查自己的 key:缺失时 no-op、隐藏动作,或显示“未配置”反馈。
EXPO_PUBLIC_* 会被打进应用包。这里只能放可公开的客户端 key,比如
Supabase anon key、RevenueCat public SDK key、PostHog project key、Sentry
DSN。服务端 secret 应放在 Supabase Edge secrets 或 EAS secrets。
技术栈
| 层级 | 选择 |
|---|---|
| Runtime | React Native 0.81.5、React 19.1、Expo SDK 54 |
| 应用壳 | Expo Router 6,typed routes、route groups、modal screens、Metro static web 输出 |
| 原生姿态 | New Architecture enabled、Android edge-to-edge、竖屏 |
| 样式 | NativeWind 4、Tailwind CSS、React Native Reusables、@rn-primitives/*、CVA |
| 后端 | Supabase JS 2,通过 types/database.ts 类型化 |
| 数据缓存 | TanStack Query 5,AsyncStorage 持久化,NetInfo 在线状态 |
| 表单 | react-hook-form + zod schema |
| 会话存储 | 原生端 expo-secure-store + ChunkedSecureStore;Web 使用 localStorage |
| 购买 | RevenueCat react-native-purchases;应用权益读取 Supabase subscriptions |
| 分析 | PostHog React Native,typed event helper、identify/reset、feature flags |
| 崩溃上报 | Sentry React Native Expo plugin、导航集成、Expo update tags、sourcemaps |
| 本地化 | i18n-js + expo-localization,英文和简体中文 |
| 通知 | expo-notifications 权限流、本地 inbox、Expo push token 获取 |
| 设备服务 | expo-local-authentication、expo-haptics、expo-store-review、ATT |
| 媒体 | expo-image、expo-image-picker、expo-document-picker、expo-image-manipulator |
| 启动与更新 | Lottie splash asset、版本门禁、expo-updates、EAS Build/Submit |
功能状态
本 root 统一使用这些状态:
- Integrated — 已接入应用;配置对应 key 或服务后启用。
- Example — 可运行参考功能,通常要替换。
- Removable demo — 适合评估模板,可以删除。
- Native-only — 需要 iOS/Android 原生构建;Web 上 no-op 或降级。
- Device-only — 完整行为需要真机。
| 功能 | 状态 | 平台支持 | 说明 |
|---|---|---|---|
| 邮箱认证 | Integrated | iOS / Android / Web / Expo Go | Supabase 邮箱密码、注册 OTP、登录 OTP、找回/重置密码、改邮箱/密码 |
| Apple Sign-In | Native-only | iOS 原生构建 | expo-apple-authentication;Android 和 Web 不可用 |
| Google Sign-In | Native-only | iOS / Android 原生构建 | 可选原生模块;Web 不加载,需要 Google OAuth IDs |
| Profile | Example | iOS / Android / Web / Expo Go | 个人资料、头像上传、签名 URL、账号设置 |
| Todos | Example | iOS / Android / Web / Expo Go | Supabase CRUD,TanStack Query 分页和乐观缓存更新 |
| Upload sample | Example | iOS / Android / Web 视情况 | Document picker 到 sample-uploads/<user-id>/...,并写入 sample_uploads 表 |
| Subscriptions | Integrated | iOS / Android 原生构建 | RevenueCat purchase/restore;权益来源是 Supabase |
| Redeem code | Native-only | iOS / Android 原生构建 | iOS redemption sheet;Android 打开 Google Play redeem URL;Web 显示提示 |
| Push inbox 与权限 | Device-only | 原生真机最佳 | 本地 inbox、权限、Android channels、Expo push token;默认未接服务端发送 |
| Deep links | Integrated | iOS / Android / Web | Expo URL;配置 LINKING_DOMAIN 后支持 HTTPS links |
| Analytics | Integrated | iOS / Android / Web / Expo Go | PostHog screen tracking、typed events、identify/reset、feature flags |
| Crash reporting | Integrated | iOS / Android / Web / Expo Go | DSN 存在时启用 Sentry;Expo Go 禁用 native frame tracking |
| App gates | Integrated | iOS / Android / Web | Onboarding、法律同意、版本门禁、auth 自动关闭 |
| Biometric lock | Native-only | iOS / Android 真机 | 使用 expo-local-authentication;需要已录入生物识别 |
| Permissions primer | Integrated | iOS / Android / Web fallback | 通知、照片、相机、ATT;Web tracking fallback 返回 granted |
| Store review | Native-only | iOS / Android store-capable builds | Web fallback 为 no-op |
| Offline banner 与缓存 | Integrated | iOS / Android / Web | NetInfo 驱动 Query online state;AsyncStorage 持久化查询缓存 |
| Toast 与 haptics | Integrated | iOS / Android / Web fallback | 全局 ToastProvider;haptics 在原生端可用 |
| i18n | Integrated | iOS / Android / Web / Expo Go | 英文和简体中文,运行时语言状态 |
| Theming | Integrated | iOS / Android / Web / Expo Go | NativeWind color scheme、持久化偏好、iOS 风格颜色 token |
| Refer a friend | Example | iOS / Android / Web 视情况 | 通过生成的 app link 调用 Share sheet |
| Component gallery | Example | iOS / Android / Web / Expo Go | React Native Reusables 组件目录 |
| Showcase | Removable demo | iOS / Android / Web / Expo Go | 能力目录和演示链接,用于评估模板 |
| Animated splash | Integrated | iOS / Android / Web | Expo config 配置 splash asset;初始界面匹配 grouped background |
应用界面地图
应用从外到内这样组成:
- Root providers —
app/_layout.tsx挂载QueryProvider、AuthProvider、AnalyticsProvider、ConsentProvider、OnboardingProvider、EntitlementProvider、PurchasesProvider、I18nProvider、ThemePreferenceProvider、NotificationsProvider、BiometricProvider、ToastProvider、bottom sheets、portals 和 Sentry 导航追踪。 - Gate stack —
OnboardingGate、AuthGate、VersionGate、ConsentGate、BiometricGate包在 Expo RouterStack外。Auth 是 guest-first:多数页面可未登录浏览,需要登录的动作通过SignInGate拉起登录。 - Auth stack —
app/(auth)包含 login、sign-up、forgot-password、 reset-password。 - Main shell —
app/(tabs)有四个 tab:Home、Component、 Showcase、Me。抽屉暴露 Home、Component、Showcase、Todos、 Upload sample、Refer、Profile、Account Security、Notifications 和 Sign In。 - Pushed screens —
todos、profile、account-security、notifications、permissions、refer、upload-sample、legal/*、manage-subscription和 showcase detail routes。 - Modals —
paywall和redeem-code是 modal stack screens。
跨平台权益
付费权限绑定账号。RevenueCat 负责购买、恢复、offerings 和本地
CustomerInfo,但应用通过 useEntitlement().isEntitled 从共享 Supabase
subscriptions 表判断是否解锁。桌面模板的 Creem webhook 也写入同一张读模型,
所以权益可以跟随同一个 Supabase 用户跨平台生效。
唯一规则:RevenueCat 是购买机制,不是 gating 的真相来源。服务端行才是准绳。
