The Unlicense

技术解读

以下内容由 GitRead 中文社区 编辑团队基于项目 README 与官方资料整理, 结合中文开发者的常见使用场景补充技术选型建议。具体以项目官方文档为准。

解构 free-exercise-db:把“公共领域”做进架构的健身数据集

项目背景与痛点

做健身类应用的人大多踩过同一个坑:运动数据的授权和标准化。ExRx.net 那套动作库公认专业,但商用授权是一笔不小的开销;自己雇私教逐条录入,成本高、周期长,还容易出错;从各种开源项目里东拼西凑,字段命名、肌肉分类、器械枚举对不上,最后往往变成一场数据清洗噩梦。

背后是一个典型的基础设施缺位问题。绝大多数健身产品真正要做的是训练计划编排、动作推荐、进度追踪,而非维护一份动作字典。但现实是,每个团队都在重复实现同一类基础功能,质量和授权状态还参差不齐。

yuhonas/free-exercise-db 的价值就在这。它把 800 多个动作整理成统一的 JSON 结构,配好示意图,用 Unlicense 直接放入公共领域——拿来就用,商用零摩擦。它不是又一个健身 App,而是一份可以被任何 App 依赖的底层数据契约。

核心技术揭秘

这个仓库最值得称道的,是它对“数据即真相”这句话的实际执行方式。它没有把数据塞进数据库,而是用文件系统组织:每个动作一个目录,目录里放 exercise.json 和对应图片。这种结构对 Git 极其友好——想新增动作,就新建目录、提 PR;想改字段,diff 干净得能一眼看完。

整个数据流分三层。底层是分散的源文件,中间是构建管线,上层提供两种分发形态:给机器消费的 JSON,以及给人消费的可搜索站点。

graph TD A[源数据<br/>exercises/ 每动作一个目录] --> B[构建管线] C[图片资源<br/>images/] --> B B --> D{"Schema 校验"} D -->|"失败"| E[CI 阻断构建] D -->|"通过"| F[扁平化合并<br/>dist/exercises.json] F --> G[拆分单条 JSON<br/>dist/exercises/*.json] F --> H[静态站点生成] H --> I[客户端搜索索引] I --> J[可搜索前端] G --> K[第三方 App 按需拉取]

构建管线承担了主要工作。它把分散的动作定义合并成一个扁平化的 exercises.json,这个文件只读、不做运行时处理,能一次性拉到客户端或服务端缓存。同时保留单条拆分版本——这对按需加载很关键,移动端完全没必要为了渲染一个动作详情页去下载几 MB 合集。

数据结构本身也值得推敲。每条记录除了 id、name,还带了 force(推/拉/静态)、level(初/中/高)、mechanic(复合/孤立)、equipment、primaryMuscles、secondaryMuscles、instructions、category、images。这套字段的核心设计目标是可推导性:有 primaryMuscles 和 equipment,就能做动作推荐;有 level 和 mechanic,就能做训练计划的安全约束;有 force,就能保证推拉平衡。数据的主要用途是供程序推导逻辑,而不是供人欣赏。

校验大概率走的是 JSON Schema 路线。源码在合并前逐条过 schema,字段缺失、枚举越界会在 CI 阶段直接报错,不会污染下游。这也是公共数据集的命门所在——一旦下游开始依赖,数据格式的稳定性比数据量更重要。

功能亮点与差异

跟同类方案比,free-exercise-db 的差异不体现在功能数量上,更多体现在约束的把握上。

授权干净。 Unlicense 意味着它本质上属于公共领域,商用、二次分发、改造都没有法律负担。看似激进,实则是数据基础设施最理性的做法——愿意被依赖,就必须先放弃变现冲动。

JSON 原生。 数据从一开始就为程序服务,而非为人类阅读整理的表格。字段命名统一、枚举值可控,任何语言里 json.load() 一下就能用。相比只给 CSV 或文档内表格的项目,差别很大。

架构对社区友好。 每个动作一个目录的组织方式,把“贡献一个新动作”的门槛降到最低:不需要懂构建脚本,照现成目录结构整理一份,改字段,补图,PR 就能成立。维护成本被分散到社区。

图文一体。 图片和 JSON 一起放在仓库里,第三方不需要对接图片 CDN 或另找图源,部署时把 dist/ 整体搬走就行。

应用场景与落地建议

最适合的场景:训练计划生成器、健身 App 的动作字典层、健身领域 AI 助手(RAG 的知识底座)、个人训练管理工具。

实际落地时,有几点需要留心。不要把 GitHub raw 当生产数据库,生产环境应把 exercises.json 拉回自建存储或对象存储,做本地缓存,避免依赖第三方可用性。注意图片体积,800 多张图全量下载对移动端不友好,建议按需拉取,或者做图床转存。字段是英文枚举,展示层得自己做本地化映射,force、level、category 这些值不能直接显示在界面上。数据覆盖范围有限,不能当作绝对准确的标准,800 多个动作覆盖了主流力量与体能训练,但器械和流派上仍有盲区,复杂业务需要扩展。

还有很多人踩过的坑:锁定版本。用 commit hash 或 fork 固定一份快照,不要直接跟主分支。公共数据集再稳定,也不该让构建结果随上游变动而变动。

综合评价

优点:

  • 授权彻底干净,商用零门槛
  • 字段面向程序推导设计,不为展示凑数
  • 仓库结构对 PR 极其友好,社区能低成本扩充数据
  • 同时提供全量和单条 JSON,消费端灵活
  • 图文一体,开箱即用

短板:

  • 数据规模中等,冷门动作和器械覆盖有限
  • 字段全英文枚举,中文本地化要自己做
  • 没有官方 SDK 或 API,得自己架一层
  • 图片质量与风格一致性参差,做 UI 需要筛选
  • 校验和构建依赖维护者,社区规模不大时迭代速度受限

一句话结论: 如果你在做健身类产品,且需要一个能合法商用的动作数据底座,它目前是性价比最高的选择之一。但你应该把它当作原材料使用,而非把它当作成品——真正的工作量,在本地化和业务逻辑那一层。

关于

GitHub 原始描述(英文)

Open Public Domain Exercise Dataset in JSON format, over 800 exercises with a browsable public searchable frontend

描述取自 GitHub 官方 API,保持仓库作者书写的原文。

简要分析

热度分
3199
价值分
1421
活跃状态
活跃

语言占比

CSS
HTML
JavaScript
Makefile
Vue

README

Free Exercise DB 💪   Test, Lint & Deploy Site to Github Pages License: Unlicense GitHub stars

Open Public Domain Exercise Dataset in JSON format, 800+ exercises with a browsable public searchable frontend

Why?

I started building another fitness related app and was looking for free/open source exercise lists and imagery I stumbled upon exercises.json which was amazing though the data wasn’t structured the way I wanted it and I also wanted a browsable/searchable frontend to the data inspired by this issue so I restructured the data and built a simple frontend to it :)

What do they look like?

All exercises are stored as seperate JSON documents and conform to the following JSON Schema eg.

{
  "id": "Alternate_Incline_Dumbbell_Curl",
  "name": "Alternate Incline Dumbbell Curl",
  "force": "pull",
  "level": "beginner",
  "mechanic": "isolation",
  "equipment": "dumbbell",
  "primaryMuscles": [
    "biceps"
  ],
  "secondaryMuscles": [
    "forearms"
  ],
  "instructions": [
    "Sit down on an incline bench with a dumbbell in each hand being held at arms length. Tip: Keep the elbows close to the torso.This will be your starting position.",
  ],
  "category": "strength",
  "images": [
    "Alternate_Incline_Dumbbell_Curl/0.jpg",
    "Alternate_Incline_Dumbbell_Curl/1.jpg"
  ]
}

See Alternate_Incline_Dumbbell_Curl.json

To further explore the data, you can use lite.datasette.io

How do I use them?

You can check the repo out and use the JSON files and images locally

Alternatively

You can leverage github’s hosting and access the single or combined exercises.json and prefix any of image path’s contained in the JSON with https://raw.githubusercontent.com/yuhonas/free-exercise-db/main/exercises/ to get a hosted version of the image eg. Air_Bike/0.jpg or leverage something like imagekit.io for dynamic image resizing which is utlized on the frontend example site

Build tasks

There are a number of helpful Makefile tasks that you can utilize

Linting

To lint all the JSON files against the schema.json use

make lint
Combining into a single JSON file

If you make changes to any of the exercises or add new ones, to recombine all single JSON files into a single JSON containing an array of objects using the following make task

make dist/exercises.json

Note: requires jq

Importing into PostgreSQL

To combine all JSON files into Newline Delimeted JSON suitable for import into PostgreSQL use the following make task

make dist/exercises.nd.json

Note: requires jq

See also Importing JSON into PostgreSQL using COPY

Browsable frontend

Screenshot of browsable frontend

There is a simple searchable/browsable frontend to the data written in Vue.js available at yuhonas.github.io/free-exercise-db all related code is in the site directory

Setup
npm install
Compile and Hot-Reload for Development
npm run dev
Compile and Minify for Production
npm run build
Run Unit Tests with Vitest
npm run test:unit
Run End-to-End Tests with Cypress
npm run test:e2e:dev

This runs the end-to-end tests against the Vite development server. It is much faster than the production build.

But it’s still recommended to test the production build with test:e2e before deploying (e.g. in CI environments):

npm run build
npm run test:e2e
Lint with ESLint
npm run lint

TODO

Incomplete fields

The following fields are incomplete in some JSON files and in such have had to allow null in schema.json

  • force
  • mechanic
  • equipment
Images

There are also a small number of duplicate images eg.

jdupes --summarize --recurse .

Scanning: 2620 files, 874 items (in 1 specified)
25 duplicate files (in 22 sets), occupying 809 KB

Contributors

Made with contrib.rocks.

Contributions are always welcome! Please read the contribution guidelines first.

Special Thanks 🙇

评论

暂无评论