openGym

Building the mobile app (iOS / Android)

openGym ships in two flavors from the same codebase:

  Self-hosted (this repo’s default) Mobile app (VITE_MOBILE=1)
Runs in any browser, against your own server natively on iPhone / Android (Capacitor shell)
Accounts passkey sign-in, one profile per person none — the phone is the account
Data synced to your server, readable on desktop stays on the device (file in the app’s private storage)
Reminders Web Push from your server native local notifications, no server involved
Exercise media served by your server (img/, gif/) loaded from the jsDelivr CDN

The mobile flavor never talks to a backend: no sign-in screen, no sync, no telemetry. State is mirrored from localStorage into opengym-state.json in the app’s private data directory on every change (iOS is allowed to evict WebView storage under pressure — the file mirror is the durable copy and is restored on launch). Backups go out through the OS share sheet instead of a browser download.

Prerequisites

Build & run

cd frontend
npm install
npm run build:mobile        # VITE_MOBILE build + `cap sync` into android/ and ios/

npx cap open android        # opens Android Studio → run on emulator or device
npx cap open ios            # opens Xcode (Mac only) → set your signing team, then run

npm run build:mobile bakes the CDN media base into the bundle and copies the web build into both native projects — re-run it after every web-code change before building natively.

Heads-up: after build:mobile, frontend/dist contains the mobile bundle. Run a plain npm run build again before deploying dist to a server.

App icons & splash screens

frontend/resources/icon.svg is the 1024×1024 source (the app’s dumbbell glyph on the app background). Generate all platform assets from it on a machine with the tooling:

cd frontend
npx @capacitor/assets generate --iconBackgroundColor '#0c0e12' --splashBackgroundColor '#0c0e12'

(If the generator won’t take the SVG directly, export it to resources/icon.png at 1024×1024 first — any image tool can do it.)

Distribution — deliberately no app stores

openGym’s mobile app is not on the Play Store or App Store, and that’s a choice: no store accounts, no store rules, no yearly fees between you and an open-source app.

Android — sideload the APK

The official signed APK is at opengym.duarte-santos.ch. Android asks you to allow installs from the browser the first time — that’s standard for any app outside the Play Store.

To build and sign your own:

cd frontend && npm run build:mobile
cd android && ./gradlew assembleRelease            # → app/build/outputs/apk/release/app-release-unsigned.apk

# one-time: create a keystore. KEEP IT — updates must be signed with the same key,
# or Android refuses to install the new version over the old one.
keytool -genkeypair -keystore my.keystore -alias opengym -keyalg RSA -validity 10950

# align + sign (zipalign/apksigner ship with the Android SDK build-tools)
zipalign -f -p 4 app-release-unsigned.apk aligned.apk
apksigner sign --ks my.keystore --ks-key-alias opengym --out openGym.apk aligned.apk

iPhone — what’s actually possible

Apple does not allow installing apps outside the App Store, so there is no .ipa download that would simply install. Your free options:

Release notes for maintainers