wanguliux85 downloadsA flexible workout tracker: customize workout types, log fields, derived stats, muscle heatmaps, and training plans.
An Obsidian workout-tracking plugin built on "ultimate flexibility." It imposes no training system on you — you define the workout types, log any data you want, and run arbitrary derived calculations on your log fields. Training plans, muscle management, and muscle heatmaps are all configurable to fit your own style. Everything is rendered as code blocks, with the rendering and data layers cleanly decoupled. Data lives as plain text (CSV / JSON) inside your vault, directly queryable by tools like Dataview.
Core proposition: No "fixed fields," no "standard exercise library," no "official templates." The plugin only provides an endlessly customizable skeleton — how you use it is entirely up to you.
Plugin ID:
workout-block| Minimum Obsidian version:1.12.7| License: MIT | Languages: 中文 / English
Most training apps hard-code fields, exercises, and plans, forcing you to adapt to them. This plugin does the opposite — it gives the "definition power" back to you:
| What you decide | How you decide | Docs / Code |
|---|---|---|
| Which workout types exist | Build freely — e.g. add or remove "Strength / Cardio / Bodyweight / Agility / Climbing" at will | Logging §5 |
| What fields each type logs | Any number, any combination (number / duration / text / select) — no system constraints | Same |
| Field units | Weight auto-converts kg/lb, or free-text units (reps / km / floors / laps…) | Same |
| Derived data from log fields | Configure "data stats" just like workout types — guided builder or expression sum(reps*weight) |
Stats design |
| How training plans are laid out | Custom target volume per exercise and per set; run on specific dates or weekly weekdays | Plan design |
| How muscles are managed | Any granularity: one muscle can map to 1 or N anatomy paths | Muscle design |
| What the heatmap draws | Per-muscle metric / time window / color tiers on a medical-grade anatomy figure | Same |
The modules below go into detail.
Workout types (e.g. "Strength," "Cardio," "Bodyweight") are only seed defaults. You can create any type and configure the fields it contains. The system does not assume "a type must have certain fields" — the count, control, and unit of fields are entirely your call.
number (numeric) / duration (h·m·s, stored as seconds) / text / select (dropdown with custom options).fields).Custom example: Create an "Agility" type with fields sets (number) + distance (number, unit "km") + rest between sets (select: 30s / 60s / 90s). For strength, you could have just weight + reps. No limits.
The smallest log granularity is "one set" (e.g. "Bench press 60kg × 8 reps" = one CSV row). The fields you fill in are entirely determined by the selected workout type, so you can log as many kinds of data as you have defined types and fields.
fields column, decoupling table structure from type definitions — adding types / fields never breaks historical logs.
The built-in "total sets" is just one ordinary, pre-seeded stat. You can delete it and define your own derived metrics.
sum / sum-of-products Σ(a×b) / average·max·min / count count — just click to pick.sum(reps * weight), avg(weight), max(weight), etc.eval / Function, uses a function whitelist + field references + arithmetic, validates syntax and legality before saving, and blocks illegal formulas.
A training plan isn't boxed in by a template; it's a fully configurable plan instance:
workout-plan code blocks as sources and merge exercises in one click; also supports manually adding items outside the scheme, and adding/removing any training set individually.workout-plan code block is itself a training scheme — no extra entity needed.
The relationship between muscles and the body SVG is a configurable mapping of 1 muscle → N SVG paths, with granularity set by you:
Renders full-body muscle load based on complete front / back human anatomy SVGs (medical anatomical naming, from flutter-body-atlas, CC BY 4.0):
metric / range params) → global default; each muscle can individually set "what metric, over what window."The plugin takes over rendering of four fenced code-block types — just write them in your notes; rendering and data layers are fully separated:
| Code block | View |
|---|---|
workout-log |
Single-exercise history table + grouped aggregate stats |
workout-day |
That day's training overview (exercises / stat values / primary·aux muscles / scheme) |
workout-plan |
Training-plan completion panel (tick per set) |
workout-heatmap |
Full-body muscle-load heatmap (front/back switch) |
registerCodeBlock, no changes to existing logic needed.rerenderBlocksForExercise), avoiding full reloads; only language switch / external file edits trigger a global refresh.Add a beta plugin, and enter this repository's URL.main.js and manifest.json from Releases or the repo root.<vault>/.obsidian/plugins/workout-block/.On first launch, default workout types, muscles, and stats are written automatically — the heatmap works out of the box, no manual init needed.
After enabling the plugin:
Ctrl/Cmd + P) and search "Log a set" to enter a training entry.workout-log code block in a note (see below).The plugin takes over rendering of the four fenced code-block types below — just write them in your notes.
workout-log — Training Log Table (history by exercise)Shows training logs with interactive "log / edit / delete" actions; grouped-above shows that group's aggregate stats.
| Param | Description | Default |
|---|---|---|
exercise |
Show only the specified exercise (by name) | show all |
limit / number |
Max rows to show | 50 |
day |
Show only records from the last N days | — |
group_by |
date (by day) / week (year-week) |
date |
sort |
desc / asc |
desc |
show_add |
Whether to show the top "add record" button | true |
```workout-log
exercise: Squat
limit: 20
```
workout-day — That Day's Training OverviewSummarizes "what was trained" by day; columns: exercise / stat value / primary muscles / auxiliary muscles / training scheme.
| Param | Description |
|---|---|
day: 2026-07-12 |
Query a specific date |
day: today |
Show today (live data, rolls with the date) |
no day |
Also shows today, and provides a "pin to today" button that writes the date back |
```workout-day
day: 2026-07-12
```
Renders the full-body muscle figure, colored by training volume. Above the code block is a front / back switch; the color tiers (default 4: blue / green / orange / red) — tier count, each tier's color and threshold — are all customizable per muscle in "Muscle management."
| Param | Description | Default |
|---|---|---|
metric |
Reference a stats config (e.g. "reps") | global default (reps) |
range |
7d / 30d / 90d / all / date range |
global default (7d) |
```workout-heatmap
metric: reps
range: 7d
```
workout-plan — Training Plan Completion PanelTracks completion progress of a training scheme, ticking off sets one by one.
| Param | Description |
|---|---|
plan: Plan Name |
Specify which scheme to show; if omitted, shows a "select plan" dropdown that writes the name back to the code block on selection |
```workout-plan
plan: Push Day A
```
In Settings (Ctrl/Cmd + , → Workout Block) you can configure:
| File | Content |
|---|---|
workout_logs.csv |
All training logs (plain CSV, easy Dataview querying) |
workout-config.json |
Config: workout types, exercises, muscles and their SVG mappings, stats, training plans |
Both datasets live inside the vault (data directory changeable in settings), both plain text, ready for Git or a quick backup.
# Install dependencies
npm install
# Dev mode (watch changes, unminified)
npm run dev
# Production build (outputs root main.js)
npm run build
# Run tests
npm test
# Test coverage
npm run test:coverage
The build artifact is the root main.js, which together with manifest.json makes the plugin runnable.
MIT — free to use, modify, and distribute. The repo root includes a LICENSE file (full MIT text) so GitHub auto-detects the license.
The bundled muscle SVG illustrations come from third parties, under CC BY 4.0 (author Ryan Graves) and BSD-3-Clause (flutter-body-atlas, Kit G). Attribution and license details are in THIRD-PARTY-NOTICES.