NutriTrack — 我是如何使用 React、Supabase 和真实食品数据构建全栈营养追踪器的
I’m happy to translate the article for you, but I’ll need the full text of the post (the content you’d like translated). Could you please paste the article’s body here? Once I have the content, I’ll provide a faithful Simplified Chinese translation while preserving the original formatting, markdown syntax, and any code blocks or URLs.
介绍
我是一名来自巴西的自学开发者,仍在学习并构建我真正想使用的东西。学习了一段时间的网页开发后,我决定是时候创建一些比简单待办事项列表更有用的东西了。
如果你曾经认真尝试记录自己的营养摄入,你一定了解其中的痛点:像 MyFitnessPal 这样的流行应用将关键功能隐藏在付费墙后,或依赖于针对美国/欧洲产品的数据库,导致巴西食品缺失或数据不准确。
NutriTrack 是一个围绕巴西人实际饮食和购物方式设计的营养控制系统——但也足够灵活,能够在全球任何地方使用。
核心功能
个人食物库
在记录任何内容之前,您需要先建立个人食物库——即您经常食用的所有食物列表。可以把它看作是数字化的储藏室目录。
Open Food Facts 集成
无需手动输入营养表,只需搜索产品名称,应用程序会查询 Open Food Facts API,这是一套由众包构建的数据库,全球拥有超过 300 万种产品,其中巴西的目录也非常完整。
每日记录
- 从您的食物库中挑选食物。
- 选择餐次类型。
- 输入数量(克或您自行设定的单位)。
- 应用程序会立即计算热量、蛋白质、碳水化合物和脂肪。
实时汇总
页面顶部实时显示每日总计:总热量、总蛋白质,以及一个进度条,展示您距离个人目标的进度。
示例: 目标 = 2,500 kcal,已摄入 = 1,800 kcal → 进度条显示 72 %。
餐食计划(14 天网格)
调度页面展示两周的网格,您可以为未来的日期制定完整的餐食计划。
自定义营养目标
您可以自行设定目标(如热量、蛋白质),而不是使用默认值。每日计划页面会以目标的百分比显示进度,帮助您进行比例思考(例如 “热量已达 60 %,但蛋白质仅为 35 %”)。
附近商店功能
利用浏览器的 GPS、OpenStreetMap 数据以及 Overpass API,应用程序可以查找您所在位置附近的超市和药店——完全免费,无需 API 密钥。
技术选型
Supabase(主后端)
Supabase 被选中而不是 Firebase,因为它使用真实的 PostgreSQL,提供了完整的关系表、SQL 查询以及行级安全(Row‑Level Security,RLS)。慷慨的免费层和出色的开发者仪表盘使其成为显而易见的胜者。
数据库访问层 (db.js)
所有数据库交互的唯一真相来源。即使前端通过 user_id 进行过滤,真正的安全仍然依赖于数据库中的 RLS 策略。
-- Example RLS policy (PostgreSQL)
create policy "user_can_access_own_data"
on logs
for all
using (user_id = auth.uid());日志中的快照数值
当你在星期二记录“150 克鸡胸肉”时,应用会将营养数值 按当时的状态 保存(snap_calories、snap_protein、snap_carbs、snap_fat)。这些快照直接存储在日志行中,确保历史数据的准确性。
OAuth 流程
Supabase(以及大多数 OAuth 提供商)通过电子邮件关联账户。如果你的 Google 和 GitHub 账户使用相同的邮箱,它们会映射到同一个 user_id,从而在切换登录方式时不会失去访问权限。实现采用 PKCE 流程,避免了旧的 Implicit 流程。
附近商店实现
- 数据来源:通过 Overpass API 的 OpenStreetMap(众包数据,覆盖面广但偶有不准确)。
- 规范化问题:城市名称以不同的大小写出现(如
'City Two'、'city two'等)。如果不进行规范化,城市过滤会显示重复条目。通过在渲染前统一字符串大小写解决了该问题。
开源
NutriTrack 完全在 MIT 许可证下开源。仓库包括:
- 完整的 Supabase 数据库 SQL 架构。
- 包含必需环境变量的
.env.example文件。 - README 中的逐步设置说明。
实时演示: