筋トレと食事管理を1つにしたPWAを個人開発した【Next.js + Supabase + OpenAI】
あすけんで食事、Hevyで筋トレ…2つ使い分けるの面倒じゃない?
筋トレしてる人なら共感してもらえると思う。
食事管理はあすけんやカロミル。筋トレ記録はHevyやStrong。それぞれ良いアプリだけど、PFC(タンパク質・脂質・炭水化物)の摂取量とトレーニングボリュームの関係を見ようとすると、2つのアプリを行ったり来たりすることになる。
「今日タンパク質足りてないけど、トレーニングのボリュームはどうだっけ?」を1画面で見たい。
ないなら作ろうと思って作った。
Bodeli — 筋トレ × 食事を、ひとつに。
できること
食事記録 + AI栄養推定
食事内容をテキストで入力すると、OpenAI APIが日本食品標準成分表ベースでカロリー・PFCを自動推定する。「鶏むね肉のサラダ」と入力するだけで、手動で栄養素を調べる必要がない。
もちろん推定結果は手動で修正もできる。
筋トレ記録
種目・重量・レップス・セット数を記録。1RM(推定最大重量)を自動計算してくれるので、各種目の成長が追える。テンプレート機能で「胸・三頭の日」「脚の日」などよく使うメニューを保存しておける。
セット間にはレストタイマーも内蔵。
ダッシュボード
これがBodeliのコア。1日のカロリー収支、PFCバランス(プログレスバー)、トレーニングボリューム、週間トレンドチャートが全部1画面に収まっている。
食事とトレーニングを同じ画面で見れるから、「今日は脚の日でハードにやったけど、タンパク質まだ足りてない」みたいな判断がすぐできる。
AIフィードバック
1日の食事とトレーニングの記録を元に、AIがフィードバックを出す。「タンパク質をあと42g摂ると目標達成」「トレーニングも記録済みで、今日のボリュームは12,500kg」のように具体的な数値で教えてくれる。
技術スタック
| レイヤー | 技術 |
|---|---|
| フレームワーク | Next.js 16 (App Router) |
| 言語 | TypeScript |
| 認証・DB | Supabase (Auth + PostgreSQL) |
| AI | OpenAI API (gpt-4o-mini) |
| デプロイ | Vercel |
| CSS | Tailwind CSS v4 |
| チャート | Recharts |
| テスト | Vitest + Testing Library |
PWAとして動く
App Storeを通さず、ブラウザでアクセスするだけで使える。ホーム画面に追加すればネイティブアプリのような体験になる。
Service Workerでオフライン対応、Web App Manifestでアイコンとスプラッシュスクリーンを設定済み。
デザインへのこだわり
競合のフィットネスアプリを調査して、独自のデザインシステムを構築した。
- アンバーアクセント(#F59E0B): 競合はみんなブルーかグリーン。アンバーは「エネルギー、強度、結果」を連想させる
- Outfitフォント: 見出しと数値表示に使用。ジオメトリックでクリーン、数字が揃って読みやすい
- ダークモード: ジムでの視認性を考慮。目に優しいダークグレー(#111111)ベース
AI食事解析の仕組み
ユーザー入力: "鶏むね肉のサラダ"
↓
OpenAI API (gpt-4o-mini)
- 日本食品標準成分表ベースで推定
- 量が不明な場合は一般的な1人前で計算
↓
JSON: {"calories": 320, "protein_g": 38, "fat_g": 8, "carbs_g": 12}
↓
ダッシュボードに反映
gpt-4o-miniを使っているのでコストは1回あたり約0.1円以下。個人開発でも十分運用できる。
悪用防止のため、1日10回のレート制限とプロンプトインジェクション対策も入れている。
苦労したところ
日本語フォントのレンダリング
Noto Sans JPは日本語の読みやすさでは最強だけど、数値表示にはイマイチ。数字が等幅にならないので、PFCの数値がガタガタになる。
解決策として、見出しと数値にはOutfitフォント(tabular-nums)を使い、本文はNoto Sans JPという2フォント構成にした。next/font/googleで両方読み込んでCSS変数で切り替えている。
Supabaseの認証フロー
Supabaseのマジックリンク認証はPKCEフローで、redirect_toがSupabaseプロジェクトの設定値に固定される。ローカル開発時にlocalhost:3000にリダイレクトさせるには、Supabaseダッシュボードの「Redirect URLs」にlocalhost:3000を追加する必要がある。
テストユーザー募集中
友人に使ってもらいながら改善してきて、「これないと困る」と言ってもらえるようになった。
もっと多くの筋トレ民に使ってもらって、フィードバックをもらいたい。
Bodeli: https://bodeli.vercel.app
筋トレと食事管理を両方やっている人、ぜひ試してみてほしい。感想・バグ報告・機能リクエスト、何でも歓迎です。
Googleアカウントかメールアドレスですぐ始められます。


