GitHub - mcalihe/grynd: A modern fitness tracker · GitHub
Skip to content
mcalihePublic

About

A modern fitness tracker

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

42 Commits

Folders and files

Repository files navigation

Grynd app icon

Grynd

The strength training log that keeps up with you.

Build your plans, log every set with a single tap and watch your progress grow.
Free and offline-first. No ads, no subscription, no account.

CI Latest release Platforms License: PolyForm Strict 1.0.0 Conventional Commits

Try it in your browser · Download for Android · Changelog · Roadmap


Plans with today's workout Logging sets during a workout with the rest timer running Workout history with the weekly overview Monthly statistics with volume chart and strength records

Why Grynd?

Most workout trackers are either cluttered, locked behind a subscription or both. Grynd does one thing: it gets out of your way between sets.

  • Faster than pen and paper. Last time's weights and reps are already filled in. Check the value, tap once, done. The rest timer starts by itself.
  • Works anywhere. Everything runs on your device. No signal in the basement gym? No problem.
  • Your data stays yours. No account, no tracking, no analytics. Export a backup file whenever you like.
  • Progress you can see. Personal records are detected automatically, and the history shows volume, strength per exercise, muscle groups and streaks.
  • Simple by design. A plan is one workout, a fixed list of exercises. Running a split? Create one plan per day. That's the whole concept.

Contents

Features · Get Grynd · Development · Architecture · Contributing · Releases and deployment · Documentation · Privacy · Acknowledgements · License

Features

Plans

  • Create plans with exercises, sets, rep range and rest time
  • Optional weekdays: today's plans show up first
  • Reorder exercises with drag and drop
  • 800+ exercises with images, search and filters by muscle group, movement and equipment

Workout

  • One exercise per page, swipe to move on
  • Values from your last workout prefilled, one tap per set
  • Change weight and reps with steppers or by swiping across the number
  • Rest timer with a notification, even when the app is in the background
  • Extra sets, duplicate sets, reorder exercises on the fly
  • Celebrations for completed sets, exercises and personal records

History

  • List, calendar and statistics views
  • Weekly, monthly and yearly volume, duration and sets
  • Estimated 1RM per exercise, muscle group split and streaks
  • Compare every workout with the previous one of the same plan

Settings

  • Light, dark or system theme
  • kg or lb (stored in kg, converted for display only)
  • English and German
  • JSON backup export and restore
  • Screen stays awake during a workout, haptics on native devices
More screenshots
Plan detail with weekdays and exercises Exercise picker with search and filters Calendar with training days and streak Workout detail with records and comparison to last time

Get Grynd

Grynd is in early development (0.x). Things work, but expect changes.

Platform How to get it
Web Open fit.michael-isler.com. Data is stored in your browser.
Android Download grynd-vX.Y.Z-debug.apk from the latest release and install it (how to).
iOS Coming via TestFlight. CI already builds the iOS project on every release.

App Store and Google Play listings will follow once signing is set up (see docs/release.md).

Development

Prerequisites

Quick start

git clone https://github.com/mcalihe/grynd.git
cd grynd
corepack enable
pnpm install
pnpm start

Open http://localhost:4200. In the browser the SQLite database runs on jeep-sqlite and is persisted in IndexedDB. Every shared component is shown in all its states at http://localhost:4200/dev/components (dev builds only).

Scripts

Command Description
pnpm start Dev server on port 4200
pnpm test Unit tests with Vitest (pnpm test:watch to watch)
pnpm e2e End-to-end tests with Playwright on a phone-sized viewport
pnpm lint ESLint (angular-eslint)
pnpm format Prettier (pnpm format:check in CI)
pnpm build Production build to dist/grynd/browser
pnpm exec cap sync Copy the build into the Android and iOS projects
pnpm catalog:import Rebuild the exercise catalog from free-exercise-db
pnpm assets:generate Regenerate app icons and splash screens from assets/

Before the first E2E run, install the browser once with pnpm exec playwright install chromium.

Running on a device

pnpm build
pnpm exec cap sync
pnpm exec cap open android   # or: pnpm exec cap open ios

Tech stack

Area Choice
Framework Angular (standalone components, signals, new control flow)
Native shell Capacitor for Android and iOS
UI Spartan UI (brain + helm) and Tailwind CSS v4
Icons Lucide via ng-icons
Animation Motion and canvas-confetti
Database SQLite via @capacitor-community/sqlite
i18n Transloco (English, German)
Testing Vitest and Playwright
Tooling pnpm, angular-eslint, Prettier, GitHub Actions, release-please

Project structure

src/app/
├── core/                 # data and business logic, no UI
│   ├── db/               # SQLite driver, migrations, repositories, catalog sync
│   ├── plans/            # plans and the plan editor draft
│   ├── workout/          # sessions, prefill, records, intervals, rest timer
│   ├── history/          # statistics and comparisons
│   ├── backup/           # JSON export and import
│   └── settings/ i18n/ services/ units/ utils/
├── features/             # routed pages: plans, workout, history, settings
└── shared/
    ├── ui/               # Spartan helm components
    ├── components/       # own components (set row, timer bar, charts, …)
    └── motion/           # animation presets and the celebration service
docs/                     # product plan, roadmap, decisions, design notes
e2e/                      # Playwright tests
scripts/                  # catalog import, screenshots, deployment
android/ ios/             # Capacitor native projects

Architecture

Grynd has no backend. All data lives in a local SQLite database, and every screen reads it through services that expose their state as Angular signals.

flowchart LR
  pages["Feature pages<br/>plans · workout · history · settings"]
  services["Services<br/>signal state, business rules"]
  repos["Repositories<br/>soft delete, timestamps"]
  driver["SqlDriver"]
  native[("SQLite<br/>Android · iOS")]
  web[("jeep-sqlite<br/>IndexedDB")]
  pages --> services --> repos --> driver
  driver --> native
  driver --> web
Loading

A few rules shape the code base:

  • A workout is a copy of its plan. Reordering or adding sets during a workout never changes the plan.
  • Sync-ready records. Every row has an app-generated UUIDv7 id, createdAt, updatedAt and deletedAt (soft delete), so a future sync needs no migration.
  • Time comes from timestamps. Everything is stored in UTC, and durations are derived from timestamps. The rest timer stores its end time, not a counter.
  • One unit internally. Weights are always stored in kg; lb exists only on screen.
  • Design tokens only. Colors, spacing and radii come from the Figma file via generated CSS variables. Components mirror their Figma names.

Business logic such as prefill, record detection (estimated 1RM by Epley), intervals and unsaved-changes detection is covered by unit tests. The main flow from plan to history is covered by an end-to-end test.

Contributing

Grynd is a personal project, but issues and ideas are welcome. Before you start on a pull request, please open an issue so we can agree on the approach. CONTRIBUTING.md explains the workflow and the contribution terms you accept by submitting a pull request; the short version:

  1. Read docs/plan.md for the product decisions behind a feature.
  2. Fork the repository, create a branch per change and keep commits small.
  3. Use only Spartan helm components, design tokens and Transloco keys (no hardcoded colors or text).
  4. Make sure pnpm format:check, pnpm lint, pnpm test and pnpm e2e pass.
  5. Give the pull request a Conventional Commits title, for example feat(workout): show the previous set while logging. PRs are squash-merged and the title becomes the changelog entry, so CI checks it.

Pull requests from branches of this repository get their own preview deployment, linked in the PR. Pull requests from forks don't, because they have no access to the deployment secrets.

Updating the README screenshots

With the dev server running (pnpm start), run:

node scripts/readme-screenshots.mjs

The script loads generated demo data, freezes the clock and writes light and dark screenshots to docs/readme/screenshots/.

Releases and deployment

Versioning is fully automated with release-please. Every merge to main updates a release PR; merging that PR tags the version, publishes a GitHub release with the changelog and attaches the Android APK.

Environment URL Updated on
Production fit.michael-isler.com Every release
Staging fit-preview.michael-isler.com/main Every merge to main
Preview fit-preview.michael-isler.com/pr-<number>/ Every pull request

Details on CI, native builds and signing are in docs/release.md.

Documentation

Product and design documents are written in German.

Document Content
docs/plan.md Product plan: scope, data model, business rules, screens
docs/roadmap.md Milestones and tasks
docs/decisions/ Short decision records
docs/design/component-map.md Figma components and screens mapped to code
docs/release.md Versioning, builds, deployment and store setup
docs/store/ Store listing and privacy policy drafts

Privacy

Grynd collects no data. There is no account, no analytics and no server that stores your workouts. Plans and workouts never leave your device unless you export a backup yourself. The full privacy policy draft is in docs/store/privacy.md.

Acknowledgements

License

Grynd is source-available, not open source. The code is public so you can read it, learn from it and contribute to it, under the PolyForm Strict License 1.0.0.

  • You may read the code, use it for personal and other noncommercial purposes and contribute through pull requests (contribution terms).
  • You may not distribute copies, publish changed versions, sell the app or its code, or use the name Grynd or the app icon for other apps.

Third-party components, such as the dependencies, fonts and exercise catalog, keep their own licenses. For any other use, please open an issue.


Made with ☕ in Switzerland

About

A modern fitness tracker

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages