ssestorad2 downloadsLog workouts, track recovery and get daily training and nutrition recommendations. Your data stays in plain Markdown notes.
English · Česky
A training log plugin for Obsidian: workout logging, recovery, recommendations for today, a weekly plan and a suggested daily intake. All data are plain Markdown notes in your vault – readable without the plugin and without any third-party service.
Status: version 0.3.1, in development. Calculations are covered by automated tests; only part of the features has been tried in Obsidian so far (see Not yet verified). The interface is in English and Czech.
Sample data, light theme. The interface is also available in Czech (screenshots in README.cs.md).
| Today | Weekly plan |
|---|---|
![]() |
![]() |
| Overview | Body | Logging a workout |
|---|---|---|
![]() |
![]() |
![]() |
Every workout, day, exercise, program or goal is one note with frontmatter (forma: workout, forma: day, …). The plugin reads and writes them only through the Obsidian API, needs no Dataview or other plugins and sends nothing off your device – the only exception is Strava, if you connect it yourself.
Default folders (always in English; vaults created by version 0.2 or older keep their Czech Forma/ folders):
Better Form/
Journal/ daily notes: sleep, check-in, HRV, weight, steps
Workouts/ one note = one workout
Plan/ one note = the plan for one week
Library/ exercises, workout templates, programs, supplements
Goals/ Health/ Equipment/ Tests/ Summaries/ Export/
Folder names can be changed in the settings. Existing notes are never renamed when you switch languages; the "Translate notes" button next to the language setting translates the built-in library (exercises, templates, programs) and the texts the plugin generated in your notes – texts you edited stay as they are. The plugin never rewrites your own text in notes – generated content goes only between the <!-- forma:start --> and <!-- forma:end --> markers. Deleting from the interface moves the note to the trash according to Obsidian's settings, never deletes it permanently.
The interface is in English and Czech. On first run the language follows Obsidian's (a supported language, otherwise English); change it any time in the plugin settings under "Language". The interface, recommendations, generated blocks in notes and the exercise, program and supplement library are all translated; whatever you wrote yourself stays as you wrote it. Your data – folders and library note names in a new vault – is always in English, whatever the interface language. Built-in exercises have their names in all languages as aliases, so links and history work in any combination of languages. Command names in the command palette change after restarting Obsidian.
The plugin isn't in the community plugin directory yet, so it's installed manually. You need Obsidian 1.8.7 or newer.
Manually (desktop and mobile):
main.js, manifest.json and styles.css from the latest release (or build the plugin yourself, see Development).<vault>/.obsidian/plugins/better-form/.With the BRAT plugin (updates are downloaded automatically): install BRAT from the directory, choose "Add beta plugin" in its settings and enter ssestorad/Better-Form.
After updating the plugin, add new exercises, programs and workout templates (push and pull for the gym and for bodyweight) with the "Add missing exercises, programs and templates to the library" command; existing notes are left unchanged.
| Tab | What it's for |
|---|---|
| Today | check-in, readiness, recommendations, today's plan, today's workouts, today's nutrition |
| Log | new workout, templates, runs to complete |
| Plan | the week day by day, summary and load outlook |
| Overview | summaries, charts, records, streaks and badges |
| Body | volume and recovery per muscle group, pain |
| Skills | calisthenics progressions |
| Programs | active programs, program library, max tests |
| Goals | goals and standards |
| Nutrition | suggested intake with the calculation breakdown, check against weight |
| Supplements | what I take, adherence, catalog |
| Settings | setup guide (profile, goal, mode, sports) and a link to all plugin settings |
All main actions are in the command palette too (Ctrl+P), for example "Log workout", "Morning check-in", "Weekly plan", "Plan a workout", "Max test", "Import run from file (GPX, TCX, FIT)", "Export workouts and daily data to CSV", "Back up folder to ZIP".
The From file button on the Today or Log tab, or in the settings. You can pick several files at once.
The date and time, distance, moving time, heart rate (if the file has it), elevation gain and fastest splits from 1 km to the marathon are read. The run appears in the "runs to complete" list, where you add RPE, run type and shoes. The same file a second time is skipped; a manually logged run on the same day with the same distance just gets the measured data added. Distance and elevation are calculated from GPS positions, so they can differ from the app's numbers by a few percent. FIT files from watches include heart rate.
Since June 2026 Strava only lets accounts with a paid subscription create an API application. If you have one, the plugin settings walk you through it step by step: create your own API application, paste the Client ID and Client Secret and connect your account. Sync only runs when you start it. Credentials stay in the plugin's data.json file in your vault.
English is the source language: interface texts and the built-in library are written in English in the code, and every other language is a translation in its own folder. To add one:
src/locales/cs/ to src/locales/<code>/ (for example de) and set code and label in its index.ts.ui.ts for the interface, exercises.ts, programs.ts, research.ts, supplements.ts, amino.ts and sources.ts for the library. Plural forms follow Intl.PluralRules for the language (one, few, many, other).src/locales/index.ts.npm test – the tests list every missing or mismatched translation for each registered language. I18N_DUMP=missing-{code}.json npm test writes the missing interface texts to a file.The language then appears in the settings and is picked automatically when Obsidian uses it.
www.strava.com): OAuth sign-in and downloading your activities. It only runs when you start it, and only after you enable it in the settings and enter your own API application details. On desktop the plugin briefly starts a local server on 127.0.0.1 during sign-in to receive Strava's response; on mobile you paste the code manually.forma: in the frontmatter. It changes only its own notes, and in them only the frontmatter and the generated block; your own notes are left alone.Every recommendation and every calculation shows its source and an evidence label:
A heuristic is never presented as research. The catalog contains over 350 verified sources; they are listed in SPEC.md, chapter 14 (in Czech).
Open items and plans are in SPEC.md, chapter 13.
The specification is in SPEC.md and the development rules in CLAUDE.md (both in Czech). You need Node.js and npm (CI runs on Node 24).
npm install
npm run dev # rebuilds on every change; with VAULT_PATH in .env.local it copies straight into the vault
npm run build # type check + production build
npm test # tests (Vitest)
npm run deploy # build + copy main.js, manifest.json, styles.css to <vault>/.obsidian/plugins/better-form/
To deploy, copy .env.local.example to .env.local and fill in VAULT_PATH. .env.local is never committed.
| Folder | Contents |
|---|---|
src/calc/, src/rules/ |
calculations and recommendation rules – pure functions without Obsidian dependencies, every formula has a test |
src/data/ |
reading and writing notes |
src/model/ |
note data model (frontmatter) |
src/evidence/ |
source catalog |
src/i18n/ |
translation: t() / tn() with plural forms and context, language selection |
src/locales/ |
one folder per language (key = English text or built-in content id) and the language registry |
src/seed/ |
exercise library, programs, templates, supplement catalog, research – English source with stable ids |
src/ui/ |
interface (Svelte 5) |
tests/ |
tests, including the data layer over an in-memory vault |
Every push to main runs tests, the type check and the build on GitHub Actions.
Releasing: bump the version in manifest.json and package.json, add "<version>": "<minAppVersion>" to versions.json, commit, and push a tag with the same number without a v (e.g. git tag 0.2.2 and git push public 0.2.2). The "Vydání" (release) workflow checks that the tag matches all three files, runs the tests and build and creates a release with main.js, manifest.json and styles.css.
MIT – see LICENSE.