※本記事は2025年12月1日に社内向けに公開した内容を一部修正したものとなります。
私は基本的にジムには行かない所謂「自宅トレーニー」として日々トレーニングを行っています。これまでは以下のようなスプレッドシートを作成してメニューを組み立て、リンクの動画や画像を参照しながらトレーニングを行っていました。
一日で鍛える部位ごとにメニューを色分けしており、その日やる種目に"〇"を付けることでトレーニングの合計所要時間を算出される仕組みにしています。
なぜ既存のトレーニングアプリを使わずこんなことをしているのかというと、理由は以下の通りです。
- なかやまきんに君が勧める「分割法」のローテーションを守りたい
(同じトレーニングを毎回繰り返していると筋肉が丈夫になり筋繊維が破壊されにくくなってしまうため、日々違う刺激を筋肉に与えることで超回復を狙いたい)
- 参考にしているトレーニングメニューが、Youtubeや書籍等、複数にわたるので1つにまとめて参照できるようにしたい
また、種目名だけ見てもやり方を思い出せないことが多々あるのでビジュアルを含めて管理したい - 1日のトレーニングにかかる時間を事前に把握しておきたい
(本来オールアウトするまでトレーニングをやり切るべきですが、私はそこまでガチではないので時間を決めて続けています)
アプリを作ろうと思ったきっかけ
一般的にトレーニングをしている人は、日々トレーニング記録をつけているかと思いますが、私は面倒なのでやっていません。
そのため、トレーニング直前に前回どの部位をやったかを思い出さないといけないという一手間が入ります。
(これまではyoutubeの視聴履歴等で振り返っていました。)
また、始める前にメニューを組み立てる必要があり、これらを自動化してしまうことでこの不便さを解消しようと思いました。
要件定義・基本設計
まず、実現したいアプリのイメージを文章化し、生成AIと壁打ちしながら仕様を決めていきます。
11月にリリースされたGemini3.0のベンチマークがGPT-5を越えていると言われているため、Geminiを使ってみました。
Gemini3.0の概要については参議院議員でAIエンジニアの安野貴博氏が解説しているのでこちらをご覧ください。
Geminiに最初に投入したプロンプトは以下のとおり。
あなたは優秀なアプリケーションエンジニアです。
筋トレのメニューを考えなくても当日やる種目を提示してくれるアプリを作りたいのですが、以下に記載する情報に足りない部分を補足して、要件を固めてください。
- 「メイン画面」には「本日のメニュー」「種目一覧」「ローテーション登録」のボタンが表示されます。
また、画面左上にハンバーガーメニューがあり、開くと上記項目のボタンが表示されます。
- 「ローテーション登録」の内容
- 筋肉の部位ごとのトレーニングを決まったローテーションで行えるようなリストを作成する画面です。
- トレーニングを実施する部位を選択して入力欄に登録します。1つの入力欄が1日のうちにトレーニングを実施する部位で、1つの入力欄には複数登録できます。
- 1週間でローテーションを回すことを考慮して、7つの入力欄を表示してください。7つ全て埋めなくても問題ありません。リストを1巡すると1日目の部位に戻ります。
- 選択できる部位は「背中」「上腕二頭筋」「腕」「肩」「上腕三頭筋」「下半身」です。
- 例えば以下のようにリストを作成することができます。
- 1日目:背中、上腕二頭筋
- 2日目:休み
- 3日目:腕、肩、上腕三頭筋
- 4日目:休み
- 5日目:下半身
- 6日目:休み
- 「種目一覧」の内容
- この後記載する「種目詳細」に登録された種目の一覧を表示する画面です。
- 表示される項目は以下のとおりです。いずれも「種目詳細」で登録した種目の項目です。
- 種目名
- 部位(1)
- 「種目詳細」の内容
- トレーニング種目の詳細を登録・参照する画面です。
- 登録できる項目は以下のとおりです。
- 種目名:トレーニングメニューの種目の名前。任意の文字列。
- 部位(1):「ローテーション登録」で選択可能な部位。
- 部位(2):より詳細な部位。任意の文字列。
- 実施頻度:以下のいずれかを選択します。
- 必須:部位(1)のトレーニングを実施する日は必ず実施する。
- ローテーション:部位(1)の種目の中から「本日のメニュー」に選ばれる。
- 重さ:ダンベルの重量(kg)を入力する。「0」を入力すると「自重」と表示される。
- RM:最大反復回数。数値。
- SET:セット数。数値。
- 時間:種目の所要時間。
- 説明:種目の説明。
- イメージ:画像(png、jpgなど)または動画(youtubeの埋め込み)を登録できる。
- 「本日のメニュー」の内容
- 当日に実施するトレーニングメニューが表示されます。
- 表示内容は以下の通りです。
- 当日の日付
- 部位:「ローテーション登録」で登録したリストから、前日実施したトレーニングの次の入力欄に登録されている部位を表示します。
初めて実施する場合は1つ目の入力欄に登録されている部位を表示します。
- 合計時間:当日実施する全種目の合計時間。
- 選択された種目のリスト:クリックすると「種目詳細」を表示することができる。リストの表示項目は以下のとおり。
- 種目名
- 部位(1)
- 画面はレスポンシブにしてください。
- DBはmysqlを使用します。
Geminiと対話しながら最終的にできた要件定義は以下のとおりです。
# 筋トレメニュー自動提案アプリ 要件定義書
## 1. プロダクト概要
ユーザーが事前に設定した「部位ローテーション」と「種目データベース」に基づき、**「今日やるべきメニュー」を自動的に提示する**アプリケーション。 意思決定のコストを下げ、迷わずトレーニングを開始・記録できることを目的とする。
---
## 2. 画面構成・遷移
**画面一覧:**
1. **メイン画面(ホーム)**
2. **ローテーション登録画面**
3. **種目一覧画面
4. **種目詳細画面(登録・編集)**
5. **本日のメニュー画面**
6. **履歴一覧画面**
**共通UI:**
- **ハンバーガーメニュー(左上):** 全画面共通でアクセス可能。
- メニュー項目:「本日のメニュー」「種目一覧」「ローテーション登録」「履歴一覧」
---
## 3. 機能要件詳細
### 3.1. メイン画面(ホーム)
アプリのハブとなる画面。
- **ボタン配置:** 以下の機能へ遷移する大きなボタンを配置。
1. **本日のメニュー:** 今日のトレーニングを実施する。
2. **履歴一覧:** 過去の実施記録を見る。
3. **種目一覧:** 種目の管理を行う。
4. **ローテーション登録:** スケジュールサイクルの設定を行う。
### 3.2. ローテーション登録
トレーニングを実施する部位のサイクルを定義する画面。
- **サイクル設定:**
- 「Day 1」〜「Day 7」までの7つの枠(入力欄)を表示。
- **サイクルロジック:** 曜日固定ではなく、**実施するごとに順番に進む「サイクル型」**を採用(Day 7の次はDay 1に戻る)。
- **部位登録:**
- 各Dayに対して、実施する「部位」を複数選択して登録可能。
- 選択肢(固定マスタ):`背中` `上腕二頭筋` `腕` `肩` `上腕三頭筋` `下半身`
- ※ 何も登録しないDayは「休息日」として扱われる。
### 3.3. 種目一覧
登録済み種目のリストを表示する画面。
- **表示項目:**
- 種目名
- 部位(1)
- **アクション:**
- リストをクリックすると「種目詳細(編集)」へ遷移。
- 「新規登録」ボタンから「種目詳細(新規)」へ遷移。
### 3.4. 種目詳細(登録・編集)
トレーニング種目の詳細スペックを定義する画面。
- **入力項目:**
- **種目名:** 任意の文字列。
- **部位(1):** マスタ(背中、肩など)から選択。
- **部位(2):** 詳細部位(例:「上部」「リア」など)。任意の文字列だが、**過去に入力されたテキストをサジェスト(候補表示)する**機能を実装。
- **実施頻度:**
- `必須`:その部位の日には必ずメニューに含まれる。
- `ローテーション`:その部位の日において、他のローテーション種目と入れ替わりで選出される。
- **重さ:** 数値(kg)。「0」入力時は「自重」と表示。
- **RM(最大反復回数):** 数値。
- **SET(セット数):** 数値。
- **時間:** 所要時間(分)。
- **説明:** テキストエリア。
- **イメージ:** 画像アップロード または YouTube URL埋め込み。
### 3.5. 本日のメニュー(最重要機能)
ロジックに基づき生成された当日のメニューを表示し、実施を記録する画面。
- **表示内容:**
1. **現在の日付**
2. **今日の部位:** 現在のサイクル番号(Day X)に紐づく部位名を表示。
3. **合計時間:** リストアップされた種目の合計所要時間。
4. **種目リスト:** 自動生成された種目カード一覧。
- クリックで詳細確認が可能。
- **メニュー生成ロジック(アルゴリズム):**
1. **部位特定:** ユーザーの現在のサイクル進捗(例:Day 3)を取得し、対象部位(例:肩、腕)を特定する。
2. **種目抽出:**
- 対象部位に紐づく種目のうち、頻度が`必須`のものは全て表示。
- 頻度が`ローテーション`のものは、**「ラウンドロビン方式」**(最終実施日時 `last_performed_at` が古い順)で一定数選出する。
3. **休息日の場合:** 対象部位がないDayの場合、「今日は休息日です」と表示する。
- **アクション:**
- **「完了して記録する」ボタン:**
- 表示されているメニューを「実施履歴」としてDBに保存。
- サイクルの進捗(Day番号)を1つ進める(7なら1へ)。
- **「スキップ(休息)」ボタン:**
- トレーニングを行わずに次のDayへ進めたい場合に使用(サイクルの進捗のみを1つ進める)。
### 3.6. 履歴一覧
過去のトレーニング実績を確認する画面。
- **表示内容:** 日付、実施した部位、実施した主な種目名のリスト。
---
## 4. 技術・データ要件
### 4.1. システム構成
- **フロントエンド:** レスポンシブWebデザイン(スマホ利用前提のUI設計)。
- **データベース:** MySQL。
### 4.2. データ構造(ER図案)
主要なテーブルとカラム定義。
1. **users** (ユーザー)
- `id`, `current_cycle_day` (現在のDay番号: 1-7)
2. **body_parts** (部位マスタ)
- `id`, `name` (背中, 上腕二頭筋...)
3. **rotations** (ローテーション設定)
- `id`, `user_id`, `day_number` (1-7), `body_part_id`
4. **exercises** (種目マスタ)
- `id`, `user_id`, `name`, `part1_id`, `part2_name`, `frequency_type`, `weight`, `rm`, `sets`, `time`, `image_url`
5. **workout_logs** (実施履歴)
- `id`, `user_id`, `date`, `exercise_id`, `created_at`
---
## 5. UI/UXの特記事項
- **入力の簡略化:** 数値入力(重さ・RM・セット数)は、スマホで操作しやすいUI(大きなタップ領域、またはステッパー)を採用する。
- **視認性:** トレーニング中にスマホを床に置いたり遠目に置いたりすることを想定し、種目名や回数は大きめのフォントサイズを採用する。
Geminiはワイヤーフレームも作ってくれましたが、アスキーアートチックなものが提示されたのでここでは割愛します。
また、nano banana proでワイヤーフレームを生成しようとしましたが、かなり時間がかかっていたので途中で中断しました。
開発
開発はClaude Codeで行いました。
Claude Codeの使い方は公式のClaude Code Docsを参照ください。
上記で作成した要件定義をそのままCLAUDE.mdに記載して、プロンプトで以下の指示を出します。
この際、要件定義に記載していなかったDockarを使用する要望を追加しました。
Dockerを使用した「筋トレメニュー自動提案アプリ」を作成してください。
CLAUDE.mdとは
Claude Codeが実行時に自動的に読み込む設定ファイルで、プロジェクトの文脈をAIに伝える役割を持ちます。
アーキテクチャの説明、コーディング規約、よく使うコマンドなど、プロジェクトで必要な情報をすべて記載しておくことができ、
一度書けば毎回の説明が不要になるためプロジェクトにおいては必須のファイルになります。
CLAUDE.mdはカレントディレクトリから/に向かって再起的に検索し、見つけたものを全て読み込みます。
サブディレクトリにあるCLAUDE.mdもそのディレクトリのファイルを扱う時に参照されるため、モジュール毎に異なる設定を持たせることもできます。
Claude Codeにいきなりアプリを作らせるのではなくCLAUDE.mdをしっかりつくり込んで作成することで、1度の指示でかなりの完成度のアウトプットの生成が期待できます。
Claude codeはVS CodeなどのIDEの拡張機能としても提供されています。
コードの作成後は動作確認をしながら、以下のように細かい修正を加えていきます。
コーディングが一区切りついたらCLAUDE.mdをアップデートします。
ここまでの内容をCLAUDE.mdに反映してください。
本番環境へのデプロイ
事前に以下の環境をアプリ用に用意しておきました。
- インスタンス
- Ubuntu (Ver.20.04)
- DNSサービス登録済みのドメイン
- hogehoge.net ※社名が特定できてしまうのでダミーのドメインに変更しました
Claude Codeで以下のプロンプトを入力することで、本番環境用の環境変数ファイル(サンプル)やデプロイ手順書まで用意してくれます。
基本的には用意された手順書に記載の通りにやればリリースまでたどり着けそうです。
「筋トレメニュー自動提案アプリ」をリモートのサーバにデプロイしたいです。
環境変数等、本番環境用のパラメータを用意したうえで、デプロイの手順を教えてください。
実際にはLets'encryptによるSSL証明書の発行がうまくいかなかったり(原因はiptablesの通信拒否設定)、Dockerがうまく起動しなかったり(原因はモジュール不足)といった躓きがありましたが、その都度Claude Codeと対話しながら解消していき、想定通りに稼働するところまで漕ぎつけました。
リリースしたアプリは以下になります。
画面イメージ
GUIの生成AIツールでも要件を満たすためのコードの作成は可能ですが、Claude Condeはディレクトリの作成やモジュールのダウンロード等も含めてすぐに動かせる状態まで環境を構築し、更に動作テストも自動化され、必要に応じてその場でコードの修正まで行ってくれることに感動しました。
生成AIが普及し始めたころから言われていますが、開発スキルではなくアイデアを持っている人が勝てる時代に突入してしまったということを身をもって実感しています。
弊社環境でClaude Codeを利用するハードル
組織でClaude Codeを使用する場合「Enterpriseプラン」または「Teamプラン」を使用することになります。
料金はこちらを参照ください。
また、Claudeのデータ利用ポリシーは以下に記載されています。
コンシューマー向けプラン(Free, Pro, Max)においてはClaudeのモデル改善のためにデータ利用を許可するかどうかを選択することが可能です。
商用ユーザ向けプラン(Team, Enterprise等)においては、プロンプトがトレーニングに使用されることはありません。
Claude Codeが特定のディレクトリの構成を読み取るので、セキュリティ担当部署がその挙動をどう捉えるかが導入可否のポイントになるのではないかと思いますが、この点は開発専用端末を個別に用意する等といった対応で回避できるかと思います。