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.
A local-first exercise logging app with guided recommendations, a library, and history review.
Sports & fitnessTypeScript · CSSGitHub @fuji3to4OnlineOwner 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
The maker's introduction consists of the line above. Read the repository README for more details. Repository README ↗
Loading the full README.
Read the full README ↗A local-first exercise and wellness tracking PWA. Record how you feel, body measurements, exercise, and video watches throughout the day, then review them in your history.
| Framework | Next.js 15 (App Router, static export) |
| UI | React 19, shadcn/ui (Radix primitives), Tailwind CSS |
| Charts | Recharts |
| Local storage | IndexedDB (Dexie.js) |
| Optional sync | Google Sheets API, Google Drive API (OAuth 2.0) |
| PWA | next-pwa |
| Tests | Vitest, Testing Library |
| Deployment | GitHub Pages (GitHub Actions) |
npm install
npm run dev
Open http://localhost:3000.
Google sync is optional. Without a client ID the app works locally, but Google sign-in is unavailable.
In Google Cloud Console, create or select a project.
Under APIs & Services → Library, enable both of these APIs:
| API | Used for |
|---|---|
| Google Sheets API | Creating the "ExerLog Data" spreadsheet and reading/writing all records |
| Google Drive API | Finding the spreadsheet, and the "ExerLog Photos" folder and photo files |
If the Sheets API is disabled, sync fails with "Failed to create spreadsheet".
Configure the OAuth consent screen. The app requests the drive.file and userinfo.email scopes. While the app is in testing, add each Google account that will sign in as a test user.
Under APIs & Services → Credentials, create an OAuth 2.0 Client ID of type Web application, and add the authorized JavaScript origins (for example http://localhost:3000 and https://fuji3to4.github.io). No redirect URI is needed.
Copy .env.example to .env.local and set the client ID:
NEXT_PUBLIC_GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.com
Restart npm run dev after changing it. The value is embedded at build time.
For the GitHub Pages deployment, add the same value as the repository secret NEXT_PUBLIC_GOOGLE_CLIENT_ID (used by .github/workflows/deploy.yml).
npm run build
npm run test
MEASUREMENT_ITEMS in src/features/measurements/measurement-items.ts with id, labelKey, unit, decimals, min, max, and showInGraph. The id must not collide with id, date, recordedAt, note, or updatedAt.labelKey to src/features/i18n/messages/en.ts and ja.ts.The input field, history, graph, CSV export, and spreadsheet column follow from these changes.
The built-in catalog is generated from public/exercises.csv at build time. If that file is missing, the app uses src/features/catalog/exercise-catalog.default.ts. Generation runs automatically before development, build, and test commands. Do not edit the generated src/features/catalog/exercise-catalog.ts by hand; update public/exercises.csv instead.
App data is stored locally in your browser's IndexedDB. Google Sheets sync is optional: data is sent to Google only after you sign in and connect sync. Exported CSV files are downloaded to your device.
ExerLogは、運動とコンディションを記録するローカルファーストのPWAです。日々の体調、身体測定、運動、動画の視聴を記録し、履歴から振り返ることができます。
| フレームワーク | Next.js 15 (App Router、静的エクスポート) |
| UI | React 19、shadcn/ui (Radix primitives)、Tailwind CSS |
| グラフ | Recharts |
| ローカルストレージ | IndexedDB (Dexie.js) |
| 任意の同期 | Google Sheets API、Google Drive API (OAuth 2.0) |
| PWA | next-pwa |
| テスト | Vitest、Testing Library |
| デプロイ | GitHub Pages (GitHub Actions) |
npm install
npm run dev
http://localhost:3000 を開いてください。
Google同期は任意です。クライアントIDを設定しなくてもアプリはローカルで動作しますが、Googleサインインは使えません。
Google Cloud Console でプロジェクトを作成または選択します。
APIとサービス → ライブラリ で、次の2つの API を両方有効にします。
| API | 用途 |
|---|---|
| Google Sheets API | 「ExerLog Data」スプレッドシートの作成、全データの読み書き |
| Google Drive API | スプレッドシートの検索、「ExerLog Photos」フォルダと写真ファイル |
Sheets API が無効だと、同期時に「Failed to create spreadsheet」になります。
OAuth 同意画面を設定します。アプリが要求するスコープは drive.file と userinfo.email です。テスト中の場合は、サインインする Google アカウントをテストユーザーに追加してください。
APIとサービス → 認証情報 で、種類「ウェブ アプリケーション」の OAuth 2.0 クライアント ID を作成し、承認済みの JavaScript 生成元(例: http://localhost:3000、https://fuji3to4.github.io)を追加します。リダイレクト URI は不要です。
.env.example を .env.local にコピーし、クライアントIDを設定します。
NEXT_PUBLIC_GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.com
値はビルド時に埋め込まれるため、変更後は npm run dev を再起動してください。
GitHub Pages へのデプロイでは、同じ値をリポジトリのシークレット NEXT_PUBLIC_GOOGLE_CLIENT_ID に登録します(.github/workflows/deploy.yml で使用)。
npm run build
npm run test
src/features/measurements/measurement-items.ts の MEASUREMENT_ITEMS に、id・labelKey・unit・decimals・min・max・showInGraph を設定した項目を追加します。id は id・date・recordedAt・note・updatedAt と重複させないでください。src/features/i18n/messages/en.ts と ja.ts に labelKey の表示名を追加します。入力項目・履歴・グラフ・CSV・スプレッドシートの列は、これらの変更に連動します。
組み込みカタログはビルド時に public/exercises.csv から生成されます。このファイルがない場合は src/features/catalog/exercise-catalog.default.ts が使われます。生成処理は開発・ビルド・テストの各コマンドの前に自動実行されます。生成物の src/features/catalog/exercise-catalog.ts は直接編集せず、public/exercises.csv を変更してください。
アプリのデータはブラウザーのIndexedDBに保存されます。Google Sheets同期は任意です。サインインして同期を接続した場合にのみ、Googleへデータが送信されます。CSVエクスポートは端末にダウンロードされます。