Releases: TraceApps/lifttrace
Release list
v1.3.0-dev03
Third dev pre-release toward v1.3.0. High-priority fix, grab this over dev02 if you use the Android app.
Fixed
- Editing a set (weight, reps, or the completed checkbox) could revert a moment later, sometimes on every edit, especially under a slow or unstable connection. Root cause was a too-frequent background refresh serving a stale on-device cache over an edit that had already saved. See the CHANGELOG for the full technical breakdown.
If you hit the reverting-edits issue on dev02 or earlier, this is the fix, please try it and let me know how it holds up.
v1.3.0-dev02
Second dev pre-release toward v1.3.0. Grab this instead of v1.3.0-dev01 if you want the latest fixes, including two real data-integrity bugs.
Changed
- Statistics desktop rails now flow through i18n (#83).
Fixed
- Settings API Tokens intro guide-link text now flows through i18n (#84).
- Settings API Tokens expiry showed "just now" for its entire lifetime instead of counting down.
- Android sync crashed on pull after the #76 multi-session migration, plus a quieter cross-session tombstone leak (#82, diagnosed by @kgenerozov).
- Legacy (pre-uuid) program-day exercises duplicated on edit, and deletes never worked in templates at all (#85, reported by @iparout).
- Diary: starting a new workout right after Clear/Delete could flash then silently revert to the old session (#86, reported by @bauerbyter).
Security
- Swept open Dependabot alerts, including a
browserslistadvisory disclosed today. Already resolved on this branch, no change needed.
Full details in the CHANGELOG.
v1.3.0-dev01
First dev pre-release toward v1.3.0. Grab this instead of dev-latest if you want to pin a specific build for bug reports.
Added
- Multiple independent workout sessions per day (#76, requested by @yoyo-san). Log a stretching routine and a lifting session on the same date as two fully independent workouts, switchable via a session tab strip. Also fixes a real data-loss bug: loading a second template over a completed workout used to silently delete the first one with no confirmation.
- Exercise browser display density toggle (#74, requested by @josefelixh). Compact/comfortable view switch on the Exercises tab (desktop widths), next to the category filter chips.
- MCP server for external AI clients (#78, requested by @bursaar). Speaks the Model Context Protocol at
/api/mcp, off by default. See the MCP setup guide. - Statistics: overlay a second body measurement on the Body Weight chart.
Fixed
- Settings → Statistics "Lock Y-Axis to Zero" label rendering in English in every translated locale.
- Reordering exercises silently reverting after the debounced save landed.
- Superset weight/reps inputs collapsing to 0px wide on phone (#75, diagnosed by @backmind).
- Body Stats widget/sheet showing "not logged" for records that exist on the server (#80, diagnosed by @josefelixh).
Full details in the CHANGELOG.
Security
- Bumped
fast-uri,@xmldom/xmldom, andbrowserslist(root) plusqs(server) for open Dependabot alerts, via a non-forcingnpm audit fixwithin already-permitted lockfile ranges.npm auditreports 0 vulnerabilities on both root and server. (GitHub's Dependabot alert count on the repo still reflectsmain, which gets this fix on the next main release.)
v1.2.0
First minor release since v1.1.2. Bumped from the 1.1.3 patch line because the desktop wide-layout pass across the main routes is a much larger surface than a patch is meant to carry.
Highlights
- Desktop wide-layout pass across Diary, Statistics, Programs, Radio, Exercises, Settings, and ExercisePicker. Mobile layouts unchanged.
- Spanish + Italian translations, exposed in Settings → Language & Region.
- Trace chat renders markdown.
- Per-entry uuid + tombstone merge for the workout log — two devices editing the same day (or one device coming back online) merge per-exercise and per-set instead of one payload wholesale replacing the other.
- Server forward-proxy support via HTTP_PROXY / HTTPS_PROXY / NO_PROXY env vars.
- In-app updates got much bigger — PWA service-worker prompt, tab-focus re-check, configurable cadence, red dot on Settings nav.
- User-management data-integrity fixes — single-user data adoption for cardio + custom exercises, startup adoption for stranded rows on upgrade, disable/re-enable is a lossless round trip, delete-user now clears the cardio log.
- X-Forwarded-Proto honored for reset/invite links + email origin behind TLS-terminating reverse proxies.
- Android release builds trust user-installed CAs for self-hosters on a private-CA cert.
- Wave of small polish and i18n conversions from community PRs (thanks @backmind and @clifmo).
Full details in CHANGELOG.md.
Upgrading
Docker: pull :latest (or :v1.2.0) from GHCR (ghcr.io/traceapps/lifttrace) or Docker Hub (traceapps/lifttrace).
Android APK is attached to this release; the in-app updater will surface it on the next check.
Nothing config-breaking.
v1.2.0-dev01
First dev pre-release of the 1.2.0 minor. Bumped from the 1.1.3 patch line because the desktop wide-layout pass across Diary, Statistics, Programs, Radio, Exercises, and ExercisePicker is a much larger surface than a patch should carry. Also picks up Spanish + Italian translations, in-app updates, server forward-proxy support, several user-management data-integrity fixes, an Android duplicate-workout fix, and small polish from community PRs.
Added
- Desktop wide-layout pass across the main routes at
min-width: 1280px(Diary, Statistics, Programs library + detail, Radio, Exercises; ExercisePicker as a wide modal). Mobile layouts unchanged. - Spanish + Italian translations, exposed in Settings → Language & Region.
- In-app updates: SW-driven banner + OS notification for PWA, GitHub-release watcher for Android, configurable cadence in Settings, red dot on the Settings nav while pending.
- Forward-proxy support via
HTTP_PROXY/HTTPS_PROXY/NO_PROXYenv vars.
Fixed
- Data-integrity fixes around enabling / disabling user management (single-user data adoption, disable-preserves-data, delete-user clean-up, cardio-log + workout-tombstone reparenting), all in one transaction.
- Android: template loads no longer wipe the local workout row and cause the next re-add to duplicate. Server GETs filter soft-deleted workouts; PUT resurrects the row.
- Password-reset / invite / test-email links honor
X-Forwarded-Protobehind TLS-terminating reverse proxies. Ported from CookTrace PR #42, thanks @clifmo. - Android release builds trust user-installed CAs (self-hosters with private-CA certs) (#58, reported by @orpetor).
- Settings rail highlight pill no longer disappears when jumping into the Administration group (#68, diagnosed by @backmind).
- Diagnostics panel em-dash mojibake (#60, thanks @backmind).
- Double-
vversion prefix in Settings → About + desktop sidebar (#61, thanks @backmind).
Changed
- Settings → Units renamed to Settings → Language & Region with a globe icon (#62, thanks @backmind).
- Radio / NutriTrace Federation / Diagnostics / About / Workout / Users settings sections now flow through i18n; a handful of already-translated keys start doing work (#66, #67, thanks @backmind).
Security
- No new dependencies affect the security surface.
npm auditreports 0 vulnerabilities and there are no open Dependabot alerts.
Full changelog: CHANGELOG.md
v1.1.3-dev01
First dev pre-release of the 1.1.3 patch. Workout persistence fix (foreground no longer bloats programs with duplicate sets), Trace chat markdown rendering, catalog re-import history preservation, and clear-chat confirmation.
Added
- Trace chat renders markdown properly (#52, thanks @backmind). Lists, bold, tables, and code blocks in the coach's replies now render instead of showing raw asterisks and pipes. Assistant bubbles only; user messages stay plain text. Renderer loads lazily on first Trace open, so users who never open Trace pay no bundle cost.
Fixed
-
Every foreground of the app no longer adds a full extra layer of sets to your program's exercises. A combination of debounced save + lifecycle handlers (
visibilitychange/App.pause/pagehide) was re-firing the same save entry with freshly regenerated set uuids each time; the server-side per-uuid merge treated the fresh uuids as new sets and appended them onto the existing ones. Set counts now stay stable across foreground/background cycles.Existing workouts already inflated by this bug stay inflated. The fix stops the leak but doesn't clean up prior damage. Recover by opening the affected day, tapping Clear on the workout, and re-loading the template. Reload resurrects cleanly since uuids stay stable across the save now.
-
Exercise catalog clear + re-import no longer silently unlinks workout history (#49, diagnosed by @backmind). Both clear paths (built-in sources and imported catalogs) previously did a hard
DELETE, so the re-import minted new autoincrement ids while everyexercise_idinworkout_log/workout_templates/coach_prescriptionsJSON blobs still pointed at the deleted rows. Muscle Balance then bucketed every affected set as "other" and per-exercise Progress returned empty. Clearing now soft-deletes via the existingdeleted_atcolumn; the next matching re-import resurrects the row in place instead of minting a new one, preserving the id so historical references stay valid. -
Clearing the Trace chat now asks for confirmation (#50, thanks @backmind). A single tap on the header button previously wiped the entire conversation with no way back. Also fixes a z-index bug where the confirm dialog opened behind the Trace panel and looked like nothing happened.
-
Statistics summary cards and plate calculator no longer show units in capitals (#48, thanks @backmind). Follow-up to #42 now that the strings sit in i18n keys. Reads
MAX kg/TOTAL min/TARGET WEIGHT (kg)instead ofMAX KG/TOTAL MIN/TARGET WEIGHT (KG).kgis kilograms;KGis not a unit.
Security
- No new dependencies.
npm auditreports 0 vulnerabilities.
services:
lifttrace:
image: ghcr.io/traceapps/lifttrace:dev
# ...v1.1.2
Patch release. Ten user-visible bug fixes and the latest AI model presets. Community reports + fixes from @backmind on most of these.
Added
- Latest AI models in the picker. Claude Opus 5 and Claude Fable 5 join the existing Claude Opus 4.8; Sonnet 5 relabeled. Google Gemini 3.x and OpenAI GPT-5.6 added as presets. Existing saved selections keep working.
Fixed
- The Login and Profile pages no longer render raw i18n keys as UI copy (#33).
en.jsondeclared theloginandprofiletop-level sections twice;JSON.parsesilently keeps only the last (biometric-only) block, dropping 21 login keys and 34 profile keys at runtime. Both sections now hold every key in one block. Also renamed two Settings sidebartitleKeys that pointed at non-existent keys and were rendering raw: AI Assistant now resolves viasettings.trace.sectionand Backup & Restore viasettings.backup.section. Diagnosed by @backmind. - Re-importing an exercise catalog no longer duplicates every row (#34). Every seeder used
INSERT OR IGNOREagainst a table with no UNIQUE constraint, so importing free-db (873 rows), Wger, or ExerciseDB a second time silently doubled the whole library. A one-time boot migration merges duplicates (picks the lowest-id row as survivor, folds non-null user edits from duplicates onto it, rewritesexercise_idreferences inside the JSON blobs inworkout_log/workout_templates/coach_prescriptionsso past workouts + templates + coach prescriptions keep pointing at the right exercise, then deletes the duplicates), free-db now populatesexternal_id, and a partial UNIQUE index locks in the fix. Full-backup restore force-runs the dedupe pass so a backup taken during the bug can't resurrect duplicates. Diagnosed by @backmind. - The All range on Statistics no longer hides body measurements taken before your first workout (#36). The body-weight chart bounded its query by the earliest workout date, but weigh-ins are independent of whether you trained that day. The All range now starts from the same
2000-01-01floor the code already falls back to when there are no workouts. - Logging a cardio session with a distance or a heart rate no longer fails (#41). Both fields are
<input type="number">, so the bound value became a number once you typed in them andnullonce you cleared them; the save path called.trim()on them as if they were still the empty string the form starts with, and threw. Both fields now test for emptiness rather than assuming a string. - Quick-log cardio templates now show up (#43).
GET /api/cardio/templateswas registered belowGET /api/cardio/:date, and Express matches in registration order, so the request was answered by the date handler withtemplatesread as a date. Feature has now worked since it was added. Pinning two sessions of the same activity also no longer gives you two identical chips. - Pre-caching exercise media for offline use no longer fails with "Exercise not found" (#44).
GET /api/exercises/media-urlswas registered belowGET /api/exercises/:idand hit the id handler. Moved above. - Confirmation dialogs with two long button labels no longer overflow the dialog card (#39).
.btncarrieswhite-space: nowrap, so a flex item can never shrink below its one-line text width. Action row now wraps. - The body stats sheet no longer shows its units in capitals (#42). Field labels are uppercased by CSS, which took the unit along with the name and produced
WEIGHT (KG),WAIST (CM). Unit symbols are case-sensitive:kgis kilograms,KGis not a unit. The symbol now opts out of the transform. - Weight placeholders in the workout editor and the plate calculator now follow the kg/lb setting. Both hard-coded pound examples (
e.g. 135,e.g. 225) regardless of preference. - The rest field in the workout editor now reads
REST (s)instead ofREST (S).Sis siemens; seconds iss. - Pull-to-refresh no longer fires mid-page on editor screens. The gesture gated on
window.scrollY, but editor pages use their own scroll container. It now walks to the nearest actually-scrolling ancestor and gates on that.
services:
lifttrace:
image: ghcr.io/traceapps/lifttrace:latest
# …v1.1.1
Patch release. ntfy push-notification titles with non-ASCII characters no longer arrive mangled; Docker images now mirror to Docker Hub alongside GHCR; two open Dependabot alerts closed.
Changed
- Docker images now mirror to Docker Hub alongside GHCR. Pull from
traceapps/lifttrace:1.1.1on Docker Hub (hub.docker.com/r/traceapps/lifttrace) orghcr.io/traceapps/lifttrace:1.1.1on GHCR (the existing primary). Both registries are kept in lockstep. Publish list also trimmed to just:latestand:dev(dropped noisy:mainand per-commit:sha-*tags — semver-tagged pulls like:1.1.1/:1.1/:1are unaffected).
Fixed
- Push notification titles with non-ASCII characters no longer arrive mangled. The ntfy Title header carries HTTP header bytes only, so a workout name with an em-dash, accented character, or emoji (e.g. "Push — Chest Day") was being dropped or corrupted by the receiving client. Titles are now RFC 2047-encoded (
=?UTF-8?B?…?=) when they contain any non-ASCII byte, so the notification shade renders them correctly on every ntfy client.
Security
fast-uribumped to 3.1.5 (CVE-2026-18446, GHSA-7p8r-x3mc-p8w7, high). Host confusion via backslash authority introducer.brace-expansionbumped to 5.0.9 (GHSA-rgw5-rvv9-x895, high). DoS via unbounded intermediate arrays, bypassing the earlier CVE-2026-14257 mitigation.
services:
lifttrace:
image: ghcr.io/traceapps/lifttrace:1.1.1
# …v1.1.0
First minor release. User-facing polish: cardio session logging, library-level exercise load-type, in-app self-updater, full internationalization foundation, sync UX overhaul.
⚠ Upgrade requires re-signing in (Android)
The Android app-identifier change (app.lifttrace.local, see the CHANGELOG "Changed" section) orphans the WebView's cached auth cookie. Server-connected Android users will need to re-enter their server URL and sign back in once after upgrading. Standalone Android users lose theme / accent / display prefs but keep all workout, program, and exercise data (that lives in local SQLite, unaffected). PWA and browser users are not affected.
Added
- Cardio session logging (#23). Opt-in via Settings → Workout → Track Cardio (off by default so pure lifters aren't cluttered). Log a session with activity, duration, optional distance / avg HR / notes; a new Cardio metric on Statistics tracks weekly minutes with an optional target line. All cardio is excluded from volume, PRs, and rest-timer firing so it never corrupts the lifting side. Manual entry only by design; device sync (Fitbit / Garmin / Health Connect) lives in NutriTrace via federation and is not planned for LiftTrace.
- Pin cardio sessions as quick-log templates. Tap the pin on any cardio session to save it as a one-tap template; pinned templates render as chips at the top of the Cardio card so the next "same-as-yesterday" run / bike / row is a single tap instead of re-filling the form. Templates carry activity, duration, distance, HR, and notes forward. Matches NutriTrace's Activities quick-log flow.
- Library-level
load_typeon exercises (#24). New Load type field in the Exercise Editor (Unset / Bilateral / Per side / Alternating) so the setting travels with the exercise instead of being buried per-workout-instance. Batch-imported catalogs (Strong / Hevy / FitNotes / Jefit CSV) can now be fixed up per-exercise once instead of having to re-select per session. Statistics, muscle-group volume, per-exercise progress, share cards, and CSV export all resolve through a new four-tier chain: per-instance override → library value → per-user Diary preference → 'bilateral'. Historical volume numbers for imported unilateral / alternating exercises will change on first render; that's the fix. - In-app updates. New Settings → Updates panel checks GitHub Releases for a newer version and, on Android, downloads the signed APK and hands off to the system installer via FileProvider. One primary button drives the whole flow (Check Now → Download & Install → Downloading X%). Skip This Version link when an update's available. Collapsible "What's new" panel renders the release notes inline. Silent shade notification when the OS notification permission is granted; top-of-app banner as fallback. Opt-in Stable or Dev channels.
- Pull-to-refresh sync (Android). In native server mode, swipe down from the top of any page to trigger a manual sync. Matches NutriTrace's behavior for family consistency.
- Smart connection banner. When sync fails, the banner explains what actually went wrong (no network vs cellular-only vs server unreachable vs HTTP error) with a Retry button, instead of a generic "sync error". Structured classification via
describeConnectionIssuemirrors NT. - Cloud icon in hamburger menu goes red on server disconnect. Previously never lit up; now driven by a real reachability probe + browser online/offline events + server-side classifier, matching NT's behavior.
- Optional email on the "Create Admin Account" form. Shows up only when SMTP is configured via environment variables. Stored on the admin's user record for password-reset and invite emails later.
- Accent-tinted browser chrome. The browser tab bar / address strip picks up your current accent color via
<meta name="theme-color">. Favicon stays the branded LiftTrace mark.
Changed
- Full i18n retrofit across the app. Every hardcoded UI string extracted into
src/i18n/en.jsonand read viasvelte-i18n. Covers Settings (all sections), Diary + WorkoutEditor + WorkoutSummary + SupersetCard + ExerciseCard + SmartLog, Coaching + Programs + ProgramDetail + TemplateSpecRow, Exercises + ExerciseDetail + ExerciseEditor + ExerciseInfo, Statistics charts + MuscleRecovery, Radio (station library + dialogs), Profile, Login, NativeSetup, Trace AI, and shared UI (TimePicker). ~500 new keys, Weblate-ready. Chicago-style title case for labels/buttons/headings, sentence case for body prose / errors / placeholders / toasts. - Bitwarden / password managers now show a real app identifier instead of "localhost" (Android). LiftTrace identifies itself as
app.lifttrace.local, which reads clearly in autofill dialogs and in your saved-credentials list. - SMTP "Username" field relabeled to "Email or Username". Most SMTP providers want the full email as the username; label change removes the guesswork.
Fixed
- Server-connection banner no longer covers the phone's notification bar. The red "server unreachable" banner used to sit edge-to-edge at viewport top:0, which on Android meant it slid up over the status bar / clock / hamburger. Now floats as a rounded card below the status bar and the app's compact header, matching NutriTrace.
- Exercise picker sheet on Statistics rendered off-screen for some browsers (#25). The Statistics → Exercise Progress picker had its own inline bottom-sheet CSS that had drifted from the shared Sheet component the rest of the app uses; on Vivaldi's persistent-web-app mode the divergent viewport-height + safe-area math pushed the sheet body below the visible area. Consolidated onto the shared Sheet.
- App icon no longer shows a white halo. Icon PNGs had ~15px of solid white padding baked into their corners. Corners now clear cleanly. Icon URLs cache-busted with the app version so shipped icon fixes take effect without users needing to clear their browser cache.
- Create Admin form layout aligned with NT/CT (parity with NT #122). Two-column layout replaces the prior stacked single-column layout.
Security
adm-zipbumped to 0.6.0 (GHSA-xcpc-8h2w-3j85).brace-expansionbumped to 5.0.7 (CVE-2026-13149, high).body-parserbumped (CVE-2026-12590).fast-uribumped (transitive CVE fix).
services:
lifttrace:
image: ghcr.io/traceapps/lifttrace:1.1.0
# …v1.1.0-dev09
Heads-up before installing: this build fixes the in-app Updates panel's Server section, which was reporting the wrong running-server version and mixing Stable / Dev channel results. Redeploy your server (docker compose pull && docker compose up -d) so the Updates page's Server section renders correctly.
Fixed
-
Server-status endpoint reported wrong running version on Docker images built before this release. The runtime was reading
server/package.json(stale at1.0.2on LT) instead of the client's rootpackage.jsonwhere the real dev version lives. Dockerfile now copies the rootpackage.jsoninto the runtime image soversion-source.jsresolves to the correct current version. Server-sideserver/package.jsonalso bumped to1.1.0-dev09for local-development consistency. -
Server-status dev-channel filter dropped every versioned dev release. Server-side regex required a dot before the number (
-dev.N) but the actual dev tags have no dot (-devNN). Both formats now accepted, matching the client-side regex.