A clean, focused gym tracker for planning workouts, logging lifts, and seeing progress.
Features • Screenshots • Tech Stack • Getting Started • Structure • Building
OpenGym keeps workout tracking simple. Build training plans, log sets without breaking your flow, and see how your lifts develop over time. Your data stays available on your device, with optional account-based sync when you want it on more than one device.
OpenGym covers the essentials without turning every workout into a data-entry
session. Its interface uses calm surfaces, clear hierarchy, and small flashes of
color to make plans and progress easy to recognize. The personality is in the
details, including the familiar > OpenGym wordmark; the workout stays at the
center.
See the illustrated guide for offline logging, split workspaces, and workout progress.
Workout plans
|
Workout logging
|
Fast set entry
|
Weekly training
|
Exercise progress
|
Appearance and preferences
|
- Plan Management : Create, edit, copy, and delete custom workout plans
- 65+ Pre-built Exercises : Across 6 muscle categories (Chest, Back, Shoulders, Arms, Legs, Core) + custom exercise entry
- Set Logging : Track weight (kg/lbs), reps, RPE (1-10), and notes per set
- Week-Based Periodization : Organize sessions by week with auto-copy from previous week
- Auto-Save : Workouts save on every screen change
- PR Detection : Flags new personal records when you log a heavier weight
- Progression Suggestions : Double-progression logic recommends the next weight/reps
- Auto-Fill : Pre-fills weights from your last session for faster logging
- Workout Frequency Chart : Weekly bar chart showing your consistency (last 8 weeks)
- Exercise Progression Chart : Line chart tracking max weight over time per exercise
- Summary Stats : Total workouts, weekly count, PRs tracked
- Full History : Expandable session cards with edit/delete for past workouts
- Dark / Light / System Theme : Automatic or manual theming
- 12 Accent Colors : Choose a color that makes the app feel like yours
- Weight Units : Switch between kg and lbs on the fly
- High Refresh Rate : 90/120Hz display support
- Focused Visual Design : Clear information, quiet surfaces, and restrained plan-color details
- Supabase Backend : Email auth, Postgres tables, and row-level security scoped to your account
- Automatic Push/Pull : Changes sync on save and when the app returns to the foreground; edits made offline drain on reconnect
- Last-Write-Wins : Edits from two devices resolve to the later timestamp
- On-Device First : All records live in local Hive storage, so the app keeps working without a connection
- Sample Data : Load 5 sample plans with 15 sessions across 5 weeks to explore the app
- Export / Clear : Full control over your data
| Technology | Purpose |
|---|---|
| Flutter 3.5+ | Cross-platform UI framework |
| Dart 3.5+ | Programming language |
| Provider | State management (ChangeNotifier) |
| Hive | Local NoSQL database |
| Flutter canvas | Lightweight dashboard sparkline rendering |
| Google Fonts | App typography |
| SharedPreferences | Settings persistence |
| Supabase | Auth, Postgres, and RLS for cloud sync |
lib/
├── models/ → Hive data models (Split, Plan, Session, Exercise, Set)
├── providers/ → ChangeNotifier state management
├── repositories/ → Thin data-access layer
├── services/ → Business logic (HiveService, SyncService, PR Tracking)
├── screens/ → Page-level UI (Home, Workout, History, Stats, etc.)
├── widgets/ → Reusable components, grouped by screen
├── theme/ → Color, typography, spacing, and shape system
├── data/ → Exercise library (65+ exercises)
└── utils/ → Animations and helpers
- Flutter SDK 3.5 or later
- Dart SDK (included with Flutter)
- Android Studio, Xcode, or VS Code (for your target platform)
# Clone the repository
git clone https://github.com/AalishMS/OpenGym.git
cd OpenGym
# Install dependencies
flutter pub get
# Generate Hive adapters
flutter pub run build_runner build --delete-conflicting-outputs
# Run the app
flutter runflutter build apk --releaseAPK output: build/app/outputs/flutter-apk/app-release.apk
flutter build ios --releaseflutter build web --releaseOpenGym updates itself. Installed copies poll the GitHub Releases API, and when a newer build is published they offer to download and install it — no app store involved. Publishing is a tag push; GitHub Actions does the rest.
-
Bump
version:inpubspec.yaml. Always increment the+buildnumber — it becomes the AndroidversionCode, it is what the updater compares, and Android refuses to install an APK whose versionCode did not increase. A new version name with the same build number is an unpublishable release.version: 1.0.1+2
-
Commit
pubspec.yamlon its own, then tag withv+ the exact pubspec version and push:git add pubspec.yaml && git commit -m "chore: release 1.0.1+2" git tag v1.0.1+2 && git push && git push --tags
Don't use
git commit -am. It also commits the generated plugin registrants underlinux/,macos/, andwindows/, which pick up line-ending-only changes on every build.
.github/workflows/release.yml then verifies the tag matches pubspec (and fails
loudly if not), runs the tests, builds a single universal signed APK, checks it
is signed with the release key rather than the debug fallback, and publishes it
as a GitHub Release. Installed apps pick it up on their next check.
Two things will make a release invisible to the updater, so the workflow avoids
both: marking it as a draft or a prerelease (the /releases/latest
endpoint skips those), and attaching more than one .apk (which is why the
build is universal rather than --split-per-abi).
Signing keys are not in the repository. Generate a keystore once and keep it forever — every APK must be signed with the same key, or installed copies cannot update and the only way forward is uninstall-and-reinstall, which erases local data.
keytool -genkeypair -v -keystore android/app/opengym-release.jks -keyalg RSA -keysize 2048 -validity 10000 -alias opengymThen create android/key.properties (git-ignored) so local release builds sign:
storeFile=opengym-release.jks
storePassword=<your keystore password>
keyAlias=opengym
keyPassword=<your key password>Back the .jks file and its passwords up somewhere offline. Losing them ends
the update path for every installed copy.
For CI, add these four repository secrets under Settings → Secrets and variables → Actions:
| Secret | Value |
|---|---|
KEYSTORE_BASE64 |
base64 -w0 android/app/opengym-release.jks |
KEYSTORE_PASSWORD |
the keystore password |
KEY_ALIAS |
the key alias (opengym above) |
KEY_PASSWORD |
the key password |
android/key.properties, *.jks, and *.keystore are git-ignored. Never
commit them, and never paste the base64 anywhere but the secret field.
Builds distributed before this release were signed with the debug key and used a
different application ID (com.example.gymapp.offline). Android treats the new
release as a different app, so it installs alongside the old one and starts
empty. Migrating once:
- In the old app: Settings → EXPORT DATA, and keep the file somewhere safe.
- Install the new APK, then Settings → IMPORT DATA and pick that file.
- Uninstall the old app.
Do the export first. Uninstalling the old app deletes its local database.
gymapp-offline/
├── lib/
│ ├── main.dart # Startup: Hive, Supabase, providers
│ ├── app_shell.dart # Tab layout (Home / History / Stats / Settings)
│ ├── auth/ # AuthGate: login, recovery, account switching
│ ├── models/ # Hive models + generated *.g.dart adapters
│ ├── providers/ # ChangeNotifier state (splits, plans, sessions, settings, updates)
│ ├── repositories/ # Thin data-access wrappers
│ ├── services/ # Hive, sync, backup, PR tracking, presets, updates
│ ├── screens/ # Page-level UI
│ ├── widgets/ # Reusable UI, grouped by screen
│ │ ├── dashboard/ history/ home/ splits/ statistics/ workout/
│ ├── theme/ # Colour tones, typography, spacing, radii, breakpoints
│ ├── data/ # Exercise library, workout presets, plan colours
│ └── utils/ # Formatting, set history, split identity, routes
├── docs/ # Splits, presets research, manual verification
├── screenshots/ # README images
├── test/ # Unit and widget tests (helpers in test/support/)
└── web/ # PWA web assets
# Run all tests
flutter test
# Run a specific test file
flutter test test/statistics_analytics_test.dart
# Run tests matching a name
flutter test --name="session calculations"Distributed under the MIT License. See LICENSE for more information.
Built with Flutter









