openGym:一个自托管健身追踪器的工程密度

你用 Hevy 记录训练日志三年了。有一天 Hevy 宣布免费版只能保留 50 次训练记录,剩下的要付费。你导出 CSV,发现格式是 Hevy 专有的——字段名是 exercise_id_1234 而不是 bench_press,换到 Strong 里导入失败。你的三年训练数据被锁死在一个 app 里。

目录
  1. openGym:一个自托管健身追踪器的工程密度
  2. 当"你的数据"真的归你
  3. 1324 个练习的库不是数据,是基础设施
  4. 并发编辑的字段级合并
  5. Passkey 认证:没有密码的世界
  6. 进度算法:不只是记录,是教练
  7. 肌肉地图:三种模式
  8. 导入导出:数据迁移的诚意
  9. PWA:不是 app store 的 app
  10. 结构平衡:Poliquin 和 Thibaudeau 的力量训练理论

openGym:一个自托管健身追踪器的工程密度

项目:DuarteSantos8/openGym · JavaScript · 1494 stars/day

当"你的数据"真的归你

你用 Hevy 记录训练日志三年了。有一天 Hevy 宣布免费版只能保留 50 次训练记录,剩下的要付费。你导出 CSV,发现格式是 Hevy 专有的——字段名是 exercise_id_1234 而不是 bench_press,换到 Strong 里导入失败。你的三年训练数据被锁死在一个 app 里。

这不是个例。健身 app 的商业模式就是数据锁定——你的训练历史是筹码,你不付费就拿不走。openGym 的回应很直接:

No account on someone else's server, no subscription, no ads, no telemetry. One docker compose up and it's running.

一个 docker compose up,数据在你自己的硬盘上,导出是一个 JSON 文件。这不是一个健身 app,是一个关于数据主权的工程声明。

1324 个练习的库不是数据,是基础设施

openGym 内置了 1324 个练习,每个都有动画演示。可以按肌肉群在身体地图上浏览,按你拥有的器械过滤。

这个数字本身不稀奇——ExRx.net 有更多。稀奇的是这个库是 app 的一部分,不是 API 调用。大多数健身 app 的练习库存在云端,需要联网才能查。openGym 的练习库打包在本地,离线可用。

这意味着两件事: 1. 离线训练时(健身房没 WiFi 很常见)所有功能正常 2. 练习库可以被 fork 和修改——你不喜欢某个练习的动画?替换它

并发编辑的字段级合并

这是 openGym 最有意思的工程细节。

你在手机上记录训练,同时在笔记本电脑上查看上周的记录。两个设备同时编辑同一个训练记录。大多数 app 的做法是"最后写入胜出"(last-write-wins)——一个设备的编辑覆盖另一个。

openGym 做的是字段级合并:

Two devices editing at once merge field by field instead of overwriting each other.

这意味着如果你在手机上改了重量,在电脑上改了次数,两个改动都会保留。这不是简单的"合并"——它需要为每个字段维护版本信息,冲突时按字段而不是按记录解决。

这个设计在分布式系统里叫 CRDT(Conflict-free Replicated Data Type)的简化版。Notion、Figma、Linear 都做了类似的事情。openGym 把它用在一个健身追踪器上——这不是"够用就好",是工程标准比问题规模高一个数量级。

Passkey 认证:没有密码的世界

openGym 用 passkey 认证——Face ID / Touch ID / 指纹。没有密码,没有"忘记密码"邮件,没有短信验证码。

密码认证可以按实例开启(PASSWORD_SIGNIN=true),但默认关闭。新设备配对用一次性代码或 QR 码。

这是一个有意思的选择。Passkey 的用户体验比密码好——不用记,不会泄露。但 passkey 的实现门槛比密码高——需要 WebAuthn API、需要设备硬件支持、需要处理跨设备同步。openGym 选择了更难但更好的路。

对于自托管应用来说,passkey 还有一个额外好处:不需要邮件服务器。密码重置需要发邮件,自托管邮件服务器是噩梦。passkey 完全绕过了这个需求。

进度算法:不只是记录,是教练

openGym 不只是记录训练,还实现了几种力量训练的进阶算法:

  • 线性进阶:每次训练加固定重量。适合新手。
  • Greyskull LP:失败时减载,成功时加重量。适合中级训练者。
  • 双进阶:在一个次数范围内加次数,达到上限后加重量。适合中高级训练者。
  • 时间进阶:用于等长收缩训练(平板支撑等)。
每种进阶规则都会解释"为什么是这个数字"——目标重量不是凭空来的,是基于上周的表现计算的。失败时不会加重量,停滞时触发减载周。

这是"教练逻辑"的代码化。大多数健身 app 只记录数据,不给你建议。openGym 把训练计划的逻辑实现了——不只是"你上周卧推 80kg",是"你上周卧推 80kg×5,这周应该 82.5kg×5,如果做不到 5 个就回到 80kg"。

肌肉地图:三种模式

openGym 的肌肉地图有三个模式:

1. Volume mode:你的训练量去了哪里——哪个肌肉群练得最多 2. Recovery mode:什么还在恢复——刚练过的肌肉群标记为"恢复中" 3. Detrained mode:什么被忽略了——很久没练的肌肉群标记为" detrained"

这三种模式回答了三个不同的问题:你练了什么(过去)、你现在能练什么(现在)、你应该练什么(未来)。大多数 app 只回答第一个。第三种模式(detrained)特别有价值——它提醒你哪些肌肉群被忽略了,防止训练不平衡。

导入导出:数据迁移的诚意

openGym 支持从 FitNotes、Strong、Hevy 导入(CSV 或 API key),还能从 Apple Health 导入体重数据。导出是一个 JSON 文件,包含所有训练记录、体重、进度照片。

这个导入功能的存在本身就是一种态度:你的数据是你的,不是 app 的。大多数 app 让导入容易(为了获客),让导出困难(为了留存)。openGym 让两者都容易。

进度照片的处理也值得注意:

Location data is stripped on the device before upload.

照片的 GPS 数据在上传前在设备端被剥离。这是一个隐私细节——大多数 app 不会告诉你照片里有 GPS 信息,更不会主动剥离它。

PWA:不是 app store 的 app

openGym 是一个 PWA(Progressive Web App)。安装到手机主屏幕后,行为像原生 app——全屏、离线可用、推送通知。不需要 App Store 审核,不需要 Google Play 上架。

这个选择和"自托管"哲学一致。App Store 的审核流程是不可控的——你的 app 可能因为某个审核员的判断被拒。PWA 绕过了这个风险。代价是发现性差——用户不会在 App Store 搜到你的 app。

Android APK 也提供了,但核心体验是 PWA。

结构平衡:Poliquin 和 Thibaudeau 的力量训练理论

openGym 实现了"结构平衡"比率——这是力量训练教练 Charles Poliquin 和 Christian Thibaudeau 的理论。核心思想是:不同肌肉群的力量应该有特定比例。如果你的卧推远超过划船,肩部受伤风险增加。

具体比率包括:

  • Poliquin 标准:卧推:划船 = 1:1
  • Thibaudeau 标准:不同肌群的相对力量比例
  • ATG(Ass to Grass)深蹲标准
这些比率会根据你的训练数据自动计算,超出范围时标记。这是"教练逻辑"的又一个实例——不只是记录数据,是解读数据并给出可行动的建议。


openGym 不是一个革命性的项目。它没有用 AI,没有区块链,没有 Web3。它做的事情是:把一个被 SaaS 绑架的应用类别,用工程诚意重新做了一遍。

数据所有权、字段级合并、passkey 认证、离线优先、结构平衡算法——这些不是花哨的功能,是基础工程做对了。当 1494 颗星在一天内涌入时,它们投的不是"这个健身 app 好用",是"数据应该归我"。

暂无表态

想参与讨论或点赞?登录后使用完整功能

讨论回复(0)

暂无回复,登录后可参与讨论
合作

智谱 GLM-5 已上线

在智谱开放平台 BigModel.cn 打造 AI 应用。新一代旗舰模型 GLM-5 在推理、代码、智能体综合能力达到开源模型 SOTA。

领取 2000万 Tokens