openGym

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](https://img.shields.io/badge/license-AGPL--3.0-a3e635?style=flat-square)](LICENSE) ![Self-hosted](https://img.shields.io/badge/self--hosted-%F0%9F%8F%A0-60a5fa?style=flat-square) ![PWA](https://img.shields.io/badge/PWA-installable-a78bfa?style=flat-square) ![React](https://img.shields.io/badge/React-19-38bdf8?style=flat-square&logo=react&logoColor=white) ![Docker](https://img.shields.io/badge/Docker-compose-2496ED?style=flat-square&logo=docker&logoColor=white) ![No tracking](https://img.shields.io/badge/telemetry-none-f472b6?style=flat-square)
![GitHub last commit](https://img.shields.io/github/last-commit/DuarteSantos8/openGym?style=flat-square) [![GitHub stars](https://img.shields.io/github/stars/DuarteSantos8/openGym?style=flat-square)](https://github.com/DuarteSantos8/openGym/stargazers) [![GitHub issues](https://img.shields.io/github/issues/DuarteSantos8/openGym?style=flat-square)](https://github.com/DuarteSantos8/openGym/issues)


Home
Home β€” today's workout & weight
Workout
Guided workout β€” animated demos & sets
Stats
Stats β€” heatmap, charts & PRs
### [🌐 opengym.duarte-santos.ch](https://opengym.duarte-santos.ch) Β· [β–Ά Try the live demo](https://duartesantos8.github.io/openGym/) 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.