My Gym My Way
Free home-gym workouts built from the equipment you own. No paywall, no account, no tracking.
翻譯準備中
尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證正在載入完整 README。 以下為已儲存的摘錄。
A full-stack workout logging application with cloud storage (Supabase/Postgres) and optional native mobile builds (Capacitor).
• Frontend: React 18 + TypeScript + Vite
• Backend: Node.js + Express + TypeScript
• Database: PostgreSQL via Supabase
• Auth: Supabase Auth (JWT verified server-side on all API routes)
• Native: Capacitor (iOS/Android) with local SQLite for offline use
• Node.js 18 or later
• npm 9 or later
• A Supabase project (free tier works fine)
This installs dependencies for both the client and server workspaces via npm workspaces.檢視完整 README ↗A full-stack workout logging application with cloud storage (Supabase/Postgres) and optional native mobile builds (Capacitor).
git clone https://github.com/your-username/workout-logger.git
cd workout-logger
npm install
This installs dependencies for both the client and server workspaces via npm workspaces.
Copy the root env example and fill in your Supabase credentials:
cp .env.example .env
Edit .env:
DATABASE_URL=postgresql://postgres:[password]@db.[project-ref].supabase.co:5432/postgres
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_ANON_KEY=your-anon-key
PORT=3001
CLIENT_ORIGIN=http://localhost:5173
Copy the client env example:
cp client/.env.example client/.env
Edit client/.env:
VITE_SUPABASE_URL=https://your-project.supabase.co
VITE_SUPABASE_ANON_KEY=your-anon-key
VITE_API_URL=http://localhost:3001
Apply the schema to your Supabase Postgres database:
cd server && npm run migrate
This runs all SQL files in server/src/db/migrations/ in order, tracking applied migrations in a schema_migrations table.
Start both the backend and frontend together:
npm run dev
Or run them separately:
npm run server # Express API on http://localhost:3001
npm run client # Vite dev server on http://localhost:5173
In your Supabase dashboard: Authentication > Providers > Email — ensure it is enabled. For local development you may want to disable email confirmation under Authentication > Settings.
RLS policies are defined in supabase/migrations/. Run these in the Supabase SQL Editor if you want RLS enforced at the database level (optional — the Express API enforces user scoping via JWT on every query).
workout-logger/
├── package.json # Workspace root — runs both client and server
├── .env.example # Server environment variables template
│
├── server/
│ ├── package.json
│ ├── tsconfig.json
│ └── src/
│ ├── index.ts # Express app entry point + global error handler
│ ├── db/
│ │ ├── postgres.ts # Pool init and connection
│ │ ├── migrate.ts # Migration runner (npm run migrate)
│ │ └── migrations/
│ │ ├── 001_initial_schema.sql
│ │ ├── 002_seed_exercises.sql
│ │ ├── 003_templates.sql
│ │ └── 004_workout_exercise_metadata.sql
│ ├── middleware/
│ │ ├── auth.ts # JWT verification via Supabase, attaches req.userId
│ │ └── asyncHandler.ts # Wraps async handlers, forwards errors to Express
│ └── routes/
│ ├── workouts.ts # CRUD for workouts, workout_exercises, and metadata
│ ├── exercises.ts # CRUD for exercises
│ ├── sets.ts # CRUD for sets
│ └── templates.ts # Workout templates (save, apply, delete)
│
├── client/
│ ├── package.json
│ ├── capacitor.config.ts # Capacitor native build config
│ ├── tsconfig.json
│ ├── vite.config.ts
│ ├── index.html
│ ├── .env.example
│ └── src/
│ ├── main.tsx
│ ├── App.tsx # Router, auth state, UnitsProvider
│ ├── index.css # Global dark theme styles
│ ├── lib/
│ │ ├── api.ts # API layer — Supabase direct (web) or SQLite (native)
│ │ ├── auth.ts # Supabase auth helpers
│ │ ├── supabase.ts # Supabase client instance
│ │ ├── sqlite.ts # Capacitor SQLite init (native only)
│ │ ├── migrations.ts # Native SQLite migration runner
│ │ ├── sync.ts # Supabase sync helpers (native only)
│ │ └── audio.ts # Web Audio API tone generator for tempo timer
│ ├── hooks/
│ │ ├── useTempoTimer.ts # Tempo phase cycling and countdown logic
│ │ ├── useDialog.ts # Promise-based in-app confirm/prompt dialogs
│ │ └── useNetwork.ts # Online/offline detection
│ ├── contexts/
│ │ └── UnitsContext.tsx # Metric/imperial preference (localStorage)
│ ├── components/
│ │ ├── Nav.tsx # Top navigation bar
│ │ ├── Dialog.tsx # In-app modal (replaces window.confirm/prompt)
│ │ ├── ExercisePicker.tsx
│ │ ├── TemplatePicker.tsx
│ │ ├── SetRow.tsx # Inline editable set row
│ │ └── OfflineBanner.tsx
│ └── pages/
│ ├── Login.tsx
│ ├── Dashboard.tsx # Overview, recent workouts, stats
│ ├── WorkoutHistory.tsx # Full workout list
│ ├── NewWorkout.tsx # Create a new workout session
│ ├── WorkoutDetail.tsx # Log exercises, sets, and tempo timer
│ ├── ExerciseLibrary.tsx # Browse and create custom exercises
│ ├── Templates.tsx # Workout templates
│ ├── Charts.tsx # Historical progress charts
│ └── Settings.tsx # Metric/imperial toggle
│
└── supabase/
└── migrations/ # Postgres schema + RLS policies (for Supabase SQL Editor)
All endpoints (except /api/health) require a Authorization: Bearer <token> header. Requests are scoped to the authenticated user — no user can access another user's data.
| Method | Path | Description |
|---|---|---|
| GET | /api/health | Health check |
| GET | /api/workouts | List workouts for the authenticated user |
| GET | /api/workouts/:id | Get workout with exercises and sets |
| POST | /api/workouts | Create a new workout |
| PUT | /api/workouts/:id | Update a workout |
| DELETE | /api/workouts/:id | Delete a workout |
| POST | /api/workouts/:id/exercises | Add an exercise to a workout |
| DELETE | /api/workouts/exercises/:weId | Remove an exercise from a workout |
| PATCH | /api/workouts/exercises/:weId/metadata | Update exercise metadata (e.g. tempo) |
| GET | /api/exercises | List global + user's custom exercises |
| POST | /api/exercises | Create a custom exercise |
| PUT | /api/exercises/:id | Update a custom exercise |
| DELETE | /api/exercises/:id | Delete a custom exercise |
| GET | /api/sets?workout_exercise_id= | List sets for a workout exercise |
| POST | /api/sets | Log a new set |
| PUT | /api/sets/:id | Update a set |
| DELETE | /api/sets/:id | Delete a set |
| GET | /api/templates | List workout templates |
| POST | /api/templates/from-workout/:workoutId | Save a workout as a template |
| POST | /api/templates/:id/apply | Create a workout from a template |
| DELETE | /api/templates/:id |
cd client
npm run build
npx cap sync
npx cap open ios # or android
On native, the app uses a local SQLite database instead of the Express API. Migrations run automatically on first launch.
npm run build
This compiles the server TypeScript to server/dist/ and builds the client to client/dist/.
To run the compiled server:
cd server && node dist/index.js
| Delete a template |