GymOS is a personal fitness tracking PWA built around one real workflow:
Train first. Paste the raw gym note. Let the app structure, normalise, analyse, and prepare the coaching handoff.
It is not trying to replace Apple Watch, Hevy, Strong, or MyFitnessPal. GymOS is a post-session fitness data system for turning messy workout notes into structured training intelligence.
Live app: https://gym-os-tau.vercel.app
Repository: https://github.com/dvp2004/GymOS
GymOS helps track:
- body weight, optional waist size, and sleep
- raw workout notes pasted after training
- treadmill/cardio distance, duration, and incline
- strength exercises, load, sets, and reps
- nutrition notes and low-friction meal tags
- exercise progression, PRs, and repeated movement history
- 8-week consistency patterns
- end-of-day ChatGPT coach reports
The app is designed for one real training workflow: logging shorthand notes during or after the gym, then pasting them into GymOS at the end of the day.
- Pick the date.
- Paste the raw workout note.
- Preview the parsed result.
- Check parser warnings.
- Apply the workout to that date.
- Add food/body notes.
- Save the log.
- Copy the coach report into ChatGPT.
Example raw workout note:
Weight: - kgs
Treadmill:
B. 0.75km, 10:00, incline=6.0
Squats: 0lbs, 3, 12
Reverse Lunge: 0lbs, 3, 12
Leg curl (Glutes & Hamstrings): 20lbs, 3, 12
Leg extension (Quadriceps): 30lbs, 3, 12
Standing calf Raise: 0lbs, 3, 12
Plank: , 3, 30 secondsGymOS parses this into structured data:
- workout type
- body weight
- treadmill distance, duration, and incline
- normalised exercise names
- load
- unit
- sets
- reps
- parser warnings for suspicious entries
GymOS is built around raw note ingestion rather than live workout tracking.
It can parse notes such as:
Machine Front lat-pulldown (Tricep, Bicep, Lats): 85lbs, 3, 12
Machine Chest Press (Deltoids, Traps & Triceps): 45lbs, 3, 12
Machine Shoulder Press (Deltoids, Traps & Triceps): 30lbs, 3, 12
Machine Triceps Pushdown (Triceps): 20lbs, 3, 12
Machine Seated Row (teres major): 65lbs, 3, 12
Machine Bicep-curl: 20lbs, 3, 12The parser normalises messy exercise names, stores the raw note in the day’s notes, and flags suspicious values before saving.
Before applying the workout to the selected date, GymOS can preview the parsed result.
The parser can flag issues such as:
- suspicious reps, such as
1w - missing sets
- missing machine/cable load
- unknown exercise names
- treadmill distance without duration
- unavailable body weight
This prevents bad data entering the dataset silently.
Messy input names are mapped to clean movement names.
| Raw input | Normalised |
|---|---|
Machine Chest Press (Deltoids, Traps & Triceps) |
Machine chest press |
Machine Front lat-pulldown (Tricep, Bicep, Lats) |
Front lat-pulldown |
Machine Bicep-curl |
Bicep curl |
Standing calf Raise |
Standing calf raise |
Leg curl (Glutes & Hamstrings) |
Leg curl |
This keeps trends and progression analysis clean.
GymOS classifies training days using strict movement detection:
| Classification | Meaning |
|---|---|
Upper |
only upper-body strength exercises detected |
Lower |
only lower-body/core strength exercises detected |
Mix |
both upper and lower strength exercises detected |
Cardio |
cardio only, with no strength work |
Rest |
no workout data |
Cardio does not override strength. If treadmill is logged after an upper-body session, the day remains Upper.
The app defaults to this weekly structure:
| Day | Default |
|---|---|
| Monday | Upper |
| Tuesday | Lower |
| Wednesday | Upper |
| Thursday | Lower |
| Friday | Upper |
| Saturday | Rest |
| Sunday | Rest |
The default can be changed manually for a specific day.
GymOS includes:
- 7-day and 14-day weight averages
- cardio distance and duration trends
- 8-week training heatmap
- 56-day consistency score
- data coverage cards
- exercise progression board
- volume leaders
- split balance
- exercise deep-dive
- hover/tap chart tooltips
GymOS tracks repeated exercises and shows:
- first logged performance
- latest performance
- best performance
- session count
- PR badges
NEWmovement badgesMatches bestUp vs lastBelow last- exercise momentum
Best performance prioritises load first, then reps and sets. For example:
65 lbs × 3 × 12 > 55 lbs × 3 × 15This avoids inflated high-rep volume being treated as better than a heavier lift.
Food logging is intentionally lightweight.
Instead of calorie counting, GymOS supports meal notes and tags such as:
- High protein
- Low protein
- Heavy carbs
- Light meal
- Restaurant
- Pre-workout
- Post-workout
- Late meal
- Hydration poor
These tags are stored for future analysis and coach reports.
GymOS does not currently run an in-app LLM chat.
Instead, it generates a structured end-of-day report that can be copied into an existing ChatGPT fitness chat.
The report includes:
- today’s full log
- recent trend summary
- workout comparison
- exercise-level comparisons
- cardio trend
- nutrition tag summary
- recent logs
- specific questions for feedback
This is deliberate. It avoids exposing API keys in the frontend and keeps the existing ChatGPT coaching workflow intact.
GymOS is built as a Progressive Web App and can be added to the iPhone Home Screen.
On iPhone:
- Open the live app in Safari.
- Tap Share.
- Tap Add to Home Screen.
- Use it like a native app.
GymOS stores data in Supabase Postgres when signed in.
Main tables:
| Table | Purpose |
|---|---|
daily_logs |
one row per date |
exercise_entries |
exercises linked to a daily log |
meal_entries |
meals linked to a daily log |
The app also uses browser localStorage as a local fallback/cache.
Row Level Security policies restrict users to their own rows.
In Supabase:
Supabase → Table EditorOpen:
daily_logs
exercise_entries
meal_entriesTo view a joined dataset, run this in Supabase SQL Editor:
select
dl.id,
dl.user_id,
dl.log_date,
dl.weight_kg,
dl.waist_size_cm,
dl.sleep_hours,
dl.workout_type,
dl.gym_time,
dl.pre_workout,
dl.treadmill_distance_km,
dl.treadmill_minutes,
dl.treadmill_incline,
dl.notes,
dl.created_at,
dl.updated_at,
coalesce(
json_agg(
distinct jsonb_build_object(
'exercise_name', ee.exercise_name,
'weight', ee.weight,
'unit', ee.unit,
'sets', ee.sets,
'reps', ee.reps,
'completed_sets', ee.completed_sets,
'position', ee.position
)
) filter (where ee.id is not null),
'[]'
) as exercises,
coalesce(
json_agg(
distinct jsonb_build_object(
'label', me.label,
'description', me.description,
'protein_score', me.protein_score,
'tags', me.tags,
'position', me.position
)
) filter (where me.id is not null),
'[]'
) as meals
from public.daily_logs dl
left join public.exercise_entries ee
on ee.daily_log_id = dl.id
left join public.meal_entries me
on me.daily_log_id = dl.id
group by dl.id
order by dl.log_date desc;- React
- TypeScript
- Vite
- Supabase Auth
- Supabase Postgres
- Supabase Row Level Security
- Vercel
- PWA manifest/service worker
- Vitest parser tests
Install dependencies:
npm installRun locally:
npm run devBuild:
npm run buildRun parser tests:
npm run test:parserCreate a local .env file:
VITE_SUPABASE_URL=https://your-project-ref.supabase.co
VITE_SUPABASE_ANON_KEY=your-public-anon-key
VITE_EXISTING_CHATGPT_COACH_URL=https://chatgpt.com/your-existing-chat-urlFor Vercel, add the same variables in:
Vercel → Project → Settings → Environment VariablesNever commit .env.
- Create a Supabase project.
- Open SQL Editor.
- Run the schema in
supabase/schema.sql. - Enable Authentication.
- Add Google OAuth if desired.
- Copy the Supabase project URL and anon key into
.env. - Add the same environment variables in Vercel.
- Redeploy.
To enable Google sign-in:
- Supabase → Authentication → Providers → Google.
- Copy the Supabase callback URL.
- Google Cloud Console → create OAuth Client ID → Web application.
- Add local and production origins:
http://localhost:5173https://gym-os-tau.vercel.app
- Add the Supabase callback URL as an authorised redirect URI.
- Paste the Google Client ID and Client Secret into Supabase.
- Enable the provider.
- Supabase → Authentication → URL Configuration → add the local and production redirect URLs.
GymOS only needs identity sign-in. It does not need Gmail scopes.
Open:
Trends → Import old logsPaste or upload a JSON array.
date is the only required field. All other fields can be blank.
Example:
[
{
"date": "2026-04-08",
"weightKg": "92",
"waistSizeCm": "",
"sleepHours": "",
"workoutType": "Upper",
"gymTime": "10:15-11:45",
"preWorkout": "2 bananas + latte",
"treadmillDistanceKm": "1.00",
"treadmillMinutes": "11:58",
"treadmillIncline": "6.0",
"notes": "Felt tired after gym",
"exercises": [],
"meals": []
}
]Missing values such as -, n/a, blank strings, and em dashes are imported as unavailable, not zero.
GymOS includes regression tests for the raw workout parser.
The tests cover:
- upper-day parsing
- lower-day parsing
- pure cardio classification
- mixed upper/lower classification
- cardio not overriding strength classification
- suspicious reps typos
- exercise alias normalisation
Run:
npm run test:parserAny real parser failure should become a new test case.
Screenshots are stored in:
docs/screenshots/Current screenshots:
01-today-dashboard.png
02-workout-parser-preview.png
03-trends-heatmap-chart.png
03-trends-heatmap-chart2.png
04-exercise-deep-dive.png
05-coach-handoff.png
06-mobile-pwa.jpegIf the repository is public, use screenshots with dummy data or blur personal values.
Do not commit:
.env
real Supabase credentials
personal ChatGPT conversation URLs
real private health/fitness exportsThe .env file must stay local and in Vercel environment variables only.
GymOS is not a live workout timer.
Apple Watch handles live session tracking. GymOS handles:
raw note → parser → structured data → trends → coach handoffThe next serious product upgrade is inline correction in the parsed preview, so suspicious values can be fixed before applying the workout to the day.
Short-term:
- inline correction inside parsed preview
- CSV export
- better parser coverage for messy real-world note formats
- coach report quality improvements
Medium-term:
- nutrition/sleep correlation analysis once enough tagged data exists
- admin/data tab for raw dataset inspection
- optional native OpenAI coach through a backend function
Not planned right now:
- live workout timer
- full calorie counting
- replacing Apple Watch
- replacing ChatGPT conversation history






