交付 LiftCrew AI:我们构建 AI 驱动 iOS 健身应用的历程
SEYSO SERVICES INC 如何设计、开发并发布 LiftCrew AI 至 Apple App Store——从第一次 React Native 提交,到以 Claude 驱动的团体训练体验,支持实时同步、餐食照片分析及 StoreKit 2 订阅。
1
已发布的 iOS 应用
9
Supabase 数据表
4
种挑战模式
60
FPS 界面帧率
任务:AI 个性化团体健身训练
大多数健身应用针对单个用户优化。LiftCrew 的出发点不同:结伴训练效果更好,但朋友之间的力量基础很少相同。我们的联合创始人设想,四人小队在同一时刻做同一个动作、同一组训练,但每个人杠铃上的重量都适合自身情况。这个看似简单的想法成为产品的核心基础: 相同动作,个性化重量.
实现这一点,需要懂得编排训练计划的 AI 模型、让分布各地的小队同步行动的实时层,以及在大重量训练时自然到让人忘记界面存在的 iOS 体验,三者紧密协作。
为什么为 iOS 选择 React Native + Expo(以及为何仍有足够原生的体验)
我们选择了 React Native 0.81 ,采用新架构(Fabric + TurboModules),以及 Expo SDK 54 搭配 expo-router 6 实现基于文件的导航。这套技术栈让 iOS 和 Android 共享同一代码库,同时在关键体验处仍可调用原生 iOS 模块:原生 expo-apple-authentication 用于通过 Apple 登录,通过原生 StoreKit 2 对接 react-native-purchases (RevenueCat),通过以下模块访问 iOS 相册: expo-image-picker ,以及 Reanimated 4.3 用于 UI 线程上的60帧/秒动画。
最终,这款应用顺利通过 Apple 审核(App Store Connect ID 6762237223,Team C23ARGS845),遵循 Apple 人机界面指南,并通过 EAS 接收 JavaScript 包 OTA 更新,同时保留 iOS 用户真正能感知的体验。
AI:由 Claude 担任训练教练
小队开始训练时,AI 教练会生成当次训练计划。模型接收小队构成、各成员的1RM基准、近期训练记录、健身房器材以及当天训练目标,返回包含动作、组数/次数方案及每位成员建议重量的结构化 JSON 计划。
我们默认使用 Claude Haiku 4.5 以兼顾速度和成本,并在需要时升级至 Claude Sonnet 4 ,用于更复杂的训练编排及视觉任务(餐食照片分析)。关键是 API 密钥始终留在服务端:每次 AI 调用都经过 Vercel 无服务器代理,地址为 /api/generate-workout ,使用用户的 Supabase JWT 认证。应用包不含任何机密——唯一的 Anthropic 密钥存储于 Vercel 环境变量中。
在此基础上,我们加入了1小时客户端响应缓存(重新打开同一计划不消耗 token)、训练中途替换动作(模型根据相对强度重新计算替换后的重量),以及刻意缩短的重试限额,避免不稳定的网络阻碍用户训练。
无需自建后端的实时小队同步
小队训练是应用的社交核心。分布在三家健身房的四个人,需要感觉像在一起训练:有人完成一组,所有人都能看到;休息计时结束,所有人一起进入下一步;有人刷新个人纪录,整个小队都会看到庆祝彩纸。
我们没有自建专用实时服务,而是采用了 Supabase Realtime WebSocket 广播。每次完成训练组、切换动作或成员状态变化,都会向当前训练专属频道推送一个小事件。本地 Zustand 存储乐观应用更新;如果训练中断网,则回退到 AsyncStorage——训练优先,同步尽力而为。
个人纪录检测在客户端运行,使用 Epley 公式与各用户已存储的1RM比较。训练结束后,将每个动作的最高估算1RM写回个人档案,并广播到小队动态。并列纪录会展示所有共同获胜者,因为社交互动比排行榜更重要。
利用 Claude 视觉记录餐食照片
营养功能原本计划采用手动搜索食物的界面。第一个原型完成后,我们就放弃了——练腿后没人想输入“鸡胸肉,142克”。取而代之,用户拍下餐盘照片,Claude Sonnet 的视觉能力就会返回结构化 JSON 格式的热量和宏量营养素,直接计入当天总量。
其背后是采用 Mifflin-St Jeor 公式的 BMR/TDEE 计算器,用于设置用户目标;每日进度环会随餐食记录动态更新;5天滚动历史则作为 JSONB 列持久保存于用户 Supabase 档案中。退出登录和重装都不会丢失数据——这后来成为我们影响最大的一项决策。
小队挑战:把训练变成一个赛季
小队挑战让朋友们持续参与。应用支持四种计分方式—— 训练总量 (举起重量的总公斤数)、 训练次数 (完成的训练场次)、 个人纪录 (个人纪录数量),以及 连续训练 (连续训练天数)。每次训练结束后,已参与挑战会自动计分,并为整个小队更新排名。
计分引擎完全运行于 Supabase 函数和 Postgres 中,无需独立挑战服务。RLS 策略确保用户只能看到自己实际所属小队的挑战。这是一个朴素的经验:数据层做得好,就不需要太多服务。
难点:支付、试用与 Apple 审核
我们使用了 RevenueCat ,在 iOS 上对接原生 StoreKit 2,在 Android 上对接 Google Play Billing。权益由单个 pro 标记控制,产品为 liftcrew_pro_monthly_v2 (CA$4.99/月)和 liftcrew_pro_yearly_v4 (CA$39.99/年)。15天免费试用由 服务端强制执行 ,存放于 subscriptions 表中,并以以下字段为起点: auth.users.created_at ——因为客户端试用计时简直是在邀请用户伪造日期、通过重装滥用试用。
RevenueCat webhook 位于 /api/revenuecat-webhook ,将每次订阅事件同步回 Supabase,因此即使收据缓存过期,订阅失效用户在下次启动时也会受到访问限制。权益状态一旦改变,付费墙立即自动关闭。
Apple 审核提出了一项我们未预先规划的重要要求: 指南1.2 合规——涉及用户生成内容时,必须提供举报和屏蔽其他用户的方式。我们添加了 user_reports 表、连接请求屏蔽名单,以及 delete_own_account RPC,让用户可以彻底删除自己的账户。应用在下一次提交时通过审核。
用一段话说明架构
客户端采用 React Native 0.81 + Expo 54。Zustand 管理状态,持久化到 AsyncStorage 并同步至 Supabase JSONB 列,使应用重装后仍能恢复数据。Supabase Postgres 的九张表分别用于用户、训练、动作、小队连接、健身房、挑战、推送 token、订阅及举报,均采用 RLS。Supabase Realtime 支持实时小队训练。Vercel 无服务器函数用于 AI 代理、RevenueCat webhook、推送发送器,以及 Gmail 到 Linear 的支持代理。Claude 提供 AI,RevenueCat 处理支付,EAS Build 负责云端 iOS/Android 编译。字体采用 Bebas Neue 和 DM Sans,视觉使用青柠色 #d4ff5a 搭配背景色 #0d0d0f 形成整体风格。
我们会再次采用的做法,以及不会再犯的错误
- 会再次采用: 服务端 AI 密钥置于 JWT 认证代理之后。这一点不可妥协。
- 会再次采用: 用 JSONB 列承载不断演化的用户状态结构(设置、餐食、计划)。它们比数据库模式迁移迭代得更快。
- 会再次采用: RevenueCat。第一次需要核对退款时,webhook + StoreKit 2 的组合就体现了投入价值。
- 不会再做: 未从第一天起纳入 Apple 1.2 合规要求就上线。我们明知需要举报/屏蔽功能,理应在第一个版本中交付。
- 不会再做: 采用客户端试用计时——即使只是占位方案也不行。应先移到服务端。
您的 iOS 应用也需要这些能力?
LiftCrew AI 是 SEYSO SERVICES INC 设计并发布的多款 iOS 应用之一。如果您有 AI、健身、效率或 B2B 方面的创意,并希望找到能将草图变成 App Store 上线产品的合作伙伴,我们期待与您交流。原生 Swift、SwiftUI、React Native、Expo、AI 集成、App Store 优化,以及繁多的 Apple 合规细节,都是我们的工作。