BikeControl (SwiftControl)
Use Zwift Click, Zwift Play, Shimano Di2, or any Bluetooth controller with MyWhoosh, Rouvy, Zwift, and more. Free to try on iOS, Android, Windows, and macOS.
トレーニングメニューを取り込み、セットごとに重量と回数を記録するアプリ
Translation pending
Sports & fitnessTypeScript · PLpgSQLGitHub @hetfiOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
Loading the full README. The saved excerpt is shown below.
スマートフォン向けトレーニング記録 PWA。ChatGPT でメニューを作成し、トレーニング中に記録、終わったら ChatGPT にエクスポート ― をシームレスに繋ぐアプリです。 • Node.js 20+(node --version で確認) • Supabase CLI または Supabase クラウドプロジェクト Security: SUPABASE_SERVICE_ROLE_KEY をクライアントバンドルに含めないでください。本アプリではすべてのデータアクセスに RLS を使用しているRead the full README ↗
スマートフォン向けトレーニング記録 PWA。ChatGPT でメニューを作成し、トレーニング中に記録、終わったら ChatGPT にエクスポート ― をシームレスに繋ぐアプリです。
| レイヤー | 技術 |
|---|---|
| フレームワーク | Next.js 16 (App Router) |
| 言語 | TypeScript |
| スタイリング | Tailwind CSS v4 |
| バックエンド | Supabase (PostgreSQL + Auth + RLS) |
| ローカル永続化 | IndexedDB (idb) |
| PWA | 手動 Service Worker |
| テスト | Vitest v5 + Testing Library |
src/
├── app/ # Next.js App Router ページ
│ ├── (app)/ # 認証後レイアウト
│ │ ├── home/ # ホーム(直近セッション一覧)
│ │ ├── import/ # メニューインポート
│ │ ├── session/[id]/ # トレーニング記録
│ │ │ └── complete/ # 完了画面
│ │ ├── history/ # 履歴
│ │ ├── exercises/ # 種目管理
│ │ └── settings/ # 設定
│ ├── login/ # ログイン
│ └── layout.tsx # ルートレイアウト(ToastProvider, PWA)
├── components/
│ ├── training/ # ExerciseCard, WeightRepsPicker, IntervalTimer, SetRow
│ ├── import/ # MenuImporter, MenuPreview
│ └── ui/ # Button, Card, Input, Toast, SaveStatus
├── domain/
│ └── types.ts # ドメイン型定義(Exercise, WorkoutSession, …)
├── lib/
│ ├── parser/ # [WORKOUT] テキストパーサ + テスト
│ ├── timer/ # インターバルタイマーロジック + テスト
│ ├── preset/ # 前回セッションプリセット + テスト
│ ├── export/ # ChatGPT エクスポート + テスト
│ ├── storage/ # IndexedDB ドラフト保存
│ └── supabase/ # client.ts / server.ts
├── proxy.ts # Next.js 16 auth proxy (旧 middleware)
└── repositories/ # DB アクセス層(UI から直接 Supabase を呼ばない)
├── workoutSessions.ts
├── workoutPlans.ts
├── restTimers.ts
├── exercises.ts
└── userSettings.ts
supabase/
├── migrations/001_initial.sql # スキーマ + RLS + トリガー
└── seed.sql # 開発用シードデータ
public/
├── sw.js # Service Worker
└── manifest.json # PWA マニフェスト
node --version で確認)npm install
.env.local を作成:
NEXT_PUBLIC_SUPABASE_URL=https://<your-project>.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=<your-anon-key>
# Service Role Key はクライアントコードに含めない。必要な場合は Server Actions / Route Handlers のみで使用。
Security:
SUPABASE_SERVICE_ROLE_KEYをクライアントバンドルに含めないでください。本アプリではすべてのデータアクセスに RLS を使用しているため Service Role Key は不要です。
Supabase CLI (ローカル開発):
supabase start
supabase db push
# 開発用シードデータを投入する場合:
supabase db reset
Supabase クラウド:
supabase/migrations/001_initial.sql の内容を貼り付けて実行supabase/seed.sql を実行npm run dev
http://localhost:3000 でアクセスできます。
# ユニットテストを実行(80 テスト)
npm test
# ウォッチモード
npm run test:watch
# カバレッジレポート
npm run test:coverage
テスト対象モジュール:
| モジュール | テストファイル |
|---|---|
Parser ([WORKOUT] テキスト解析) | src/lib/parser/parser.test.ts |
| Timer (インターバルタイマーロジック) | src/lib/timer/timer.test.ts |
| Preset (前回セッションプリセット) | src/lib/preset/preset.test.ts |
| Export (ChatGPT テキスト生成) | src/lib/export/export.test.ts |
# 型チェック
npm run typecheck
# プロダクションビルド
npm run build
# ビルド成果物をローカル確認
npm start
NEXT_PUBLIC_SUPABASE_URLNEXT_PUBLIC_SUPABASE_ANON_KEYVercel のサーバーレス関数は Edge Runtime を使用できます。
src/lib/supabase/server.tsは@supabase/ssrのcreateServerClientを使用しているため対応済みです。
ChatGPT で以下の形式のテキストを生成し、インポート画面に貼り付けます:
[WORKOUT]
name: 胸の日
day: 月曜日
ベンチプレス | sets: 4 | reps: 8-10 | rest: 90s
インクラインダンベルプレス | sets: 3 | reps: 10-12 | rest: 60s
[/WORKOUT]
パーサーは全角数字・日本語の「分」「秒」・mm:ss 形式に対応しています。
endsAt ISO タイムスタンプ)なのでバックグラウンド・画面OFF でも正確client_id で冪等アップサート(重複保存防止)完了画面で「ChatGPT にコピー」ボタンを押すと以下の形式でクリップボードにコピーされます:
[トレーニング記録]
日付: 2026-09-13
メニュー: 胸の日
ベンチプレス
セット1: 80kg × 8reps ✓
セット2: 80kg × 8reps ✓
[/トレーニング記録]
middleware.ts の export 名が proxy に変更 → src/proxy.tsparams / searchParams が Promise 型に → use(params) で unwrapcookies() が async に → await cookies()auth.uid() = user_id)src/repositories/ がデータアクセスを一元管理しているため、将来 MCP サーバー (src/mcp/) を追加する際はリポジトリ関数を再利用できます。パーサー (src/lib/parser) もフレームワーク非依存なので MCP ツールとして公開可能です。
オフライン時はキャッシュ済みページが表示されます(Service Worker による Stale-While-Revalidate)。
MIT