openGym README

The project's README from github.com/arvids-unavailable/openGym. As one markdown file: README.md.

openGym

A self-hosted gym & body-weight tracker you actually own.

Plan your week, run guided workouts, track every set and your body weight over time — on your phone, synced across devices, behind your own passkey login. No account on someone else's server, no subscription, no ads. Just docker compose up.


License: AGPL v3 Self-hosted PWA React Docker No tracking
GitHub last commit GitHub stars GitHub issues


Home
Home — today's workout & weight
Workout
Guided workout — animated demos & sets
Stats
Stats — heatmap, charts & PRs

🌐 opengym.duarte-santos.ch · ▶ Try the live demo

No signup, nothing to install — it runs entirely in your browser on example data.
There's no server behind the demo, so passkey sign-in, sync across devices and the admin dashboard only exist in a self-hosted instance.

Why

Most workout apps lock your data behind a login on their servers, nag you to upgrade, or disappear when the startup does. openGym is the opposite: it runs on your box, your data stays in a folder you control, and it's yours to fork. It still feels modern — installable as a home-screen app, passkey sign-in, offline support, sync across your phone and laptop.

Features

Quick start (self-host)

You need Docker with Compose.

git clone https://github.com/DuarteSantos8/openGym
cd openGym
cp .env.example .env
docker compose pull   # grab prebuilt images (amd64 + arm64) — skip to build from source instead
docker compose up -d

Open http://localhost:8080, tap Create profile, and you're in. First launch downloads the exercise media (~140 MB) once. Prefer building the images yourself instead of pulling from ghcr.io? Drop the pull step and run docker compose up -d --build — you don't need Node or a build step locally either way.

Want it reachable from your phone over the internet with passkeys? You'll need an HTTPS domain — a two-line change in .env. See docs/SELF_HOSTING.md.

Mobile app (no server at all)

The same codebase also builds a standalone mobile app (Capacitor): no account, no sync, no backend — everything stays on the phone, with native workout-day reminders and share-sheet backups. Self-hosting gets you multi-device sync and profiles for friends & family; the mobile app is the install-and-done flavor.

How it works

┌─────────────┐        ┌──────────────────────────────┐
│  Your phone │──HTTPS─▶│  web  (nginx)                │
│  / laptop   │        │   ├─ serves the built app    │
└─────────────┘        │   └─ proxies /api ──────────┐│
                       └──────────────────────────────┘│
                                                        ▼
                                        ┌──────────────────────────┐
                                        │  api  (Node + WebAuthn)  │
                                        │   └─ ./data (JSON files) │
                                        └──────────────────────────┘

Your data

Lives in ./data on your host: db.json (profiles + public passkeys), state-<user>.json (each user's plan, workouts, body weight, settings), and secret (the session-cookie key). Back up ./data and you've backed up everything. Passkey private keys never touch the server — they stay in your phone's secure hardware / your password manager.

Configuration

All via .env (see .env.example):

Variable What it is Default
RP_ID Hostname passkeys are bound to localhost
ORIGIN Full URL the app is served from http://localhost:8080
WEB_PORT Host port for the web UI 8080
RP_NAME Name shown in the passkey prompt openGym
ADMIN_UIDS User ids that get the admin dashboard (comma-separated) (none)
INVITE_ONLY Require an invite code to create a profile (off)

Push notification keys are generated on first run and saved to ./data/vapid.json — nothing to set.

Roadmap

Rough, community-driven — ideas and PRs welcome:

Tech

React 19 + Vite (React Router, Zustand) · Node (no framework) · nginx · Docker Compose · WebAuthn · exercise data from hasaneyldrm/exercises-dataset. No database server, no cloud dependencies — the frontend builds inside Docker, so self-hosting stays a one-command docker compose up.

The training logic — progression rules, 1RM estimation, how a logged session is read back — lives in pure functions under frontend/src/lib/ with tests next to them: npm test in frontend/. Vitest is a dev dependency; the app itself ships no runtime dependencies beyond React, the router and Zustand.

Community

Contributing

Issues and PRs welcome — see CONTRIBUTING.md. Good first issues: more starter plans, exercise-data languages, import from other trackers. A ⭐ helps more people find it.

openGym is free and stays free: AGPL, no subscription, no paid tier, nothing held back for sponsors. If it replaced a paid tracker for you and you want to chip in, the Sponsor button at the top of the page is there — a star, a bug report or a PR is worth just as much.

License

GNU AGPL v3.0 — free and open source. You can self-host, use, modify and share it; if you run a modified version as a network service, you must offer that version's source under the same license. Nobody can turn openGym into a closed, proprietary product.

Exercise images/GIFs are fetched from the upstream dataset and keep their own terms — see NOTICE.md.

openGym (arvids-unavailable/openGym)

progressive-web-app
Searching Database…

7.3K ·GitHub
What is this?A self-hosted gym and body-weight tracker you actually own: weekly plans, guided workouts, full set and weight logging, and cross-device sync behind your own passkey login — no third-party account, no subscription, no ads.
Is this a phone app or something I host on my own server?Both, from one codebase: a self-hosted web app you install to your home screen as a PWA (with sync and profiles), or a standalone Android APK with no server at all. There is deliberately no App Store build — on iPhone you use the self-hosted PWA from Safari.
How do I get it running?Install Docker with Compose and run 'docker compose up' — the frontend builds inside the container, so you need nothing else locally. First launch downloads about 140 MB of exercise media once, then you just create a profile.
Anything tricky about using it from my phone over the internet?Passkeys require everything on one HTTPS origin, so remote access means giving it a real domain — a two-line RPID/ORIGIN change in .env. Most login problems in the community turn out to be exactly that mismatch.
Where does my data end up?In a ./data folder on your own host, as plain JSON files — back up that folder and you've backed up everything. There is no telemetry, and passkey private keys never leave your phone's secure hardware or your password manager.
What happens during a guided workout?It knows what day it is and opens today's session, asks your body weight first, pre-fills your weights from last time, and runs a rest timer with PR detection. The screen stays awake while you train, and push notifications can fire rest alerts even with the app closed.
How does it decide what weight I should lift next?Each routine follows a progression rule you pick — linear, Greyskull LP, double progression through a rep range, or adding time — overridable per exercise. Missed reps never advance the load, stalls trigger a deload, and bodyweight exercises progress in reps, then in added sets.
Can I bring my history over from other tracker apps?Yes — importers cover FitNotes, Strong and Hevy, plus body weight from an Apple Health export. Names are matched against the exercise library and anything unrecognized becomes one of your own exercises, so nothing is dropped; one-tap JSON export gets everything back out.
Can I try it before self-hosting?Yes — the live demo at opengym.duarte-santos.ch runs entirely in your browser on example data, no signup. There is no server behind it, so passkey sign-in, cross-device sync and the admin dashboard only exist in a self-hosted instance.
Size
124.4 MB
Stars
7.3K
Updated
CommitAug 03
Age
2mo
Commits · 90 Days