github CodeWithCJ/SparkyFitness v1.10.0

2 hours ago

💙 Support SparkyFitness

If SparkyFitness has been useful to you & your family, please consider sponsoring on GitHub or supporting via Ko-fi. Your support helps cover recurring costs such as AI coding tools, development infrastructure, and Apple & Google Developer memberships to keep the project actively maintained.

Planning to buy an Android phone for app development and testing 📱 Your sponsorship helps cover the cost. Thank you for your support! 🙏


Important

💾 Upgrade Notice: Always remember to back up your database and environment before upgrading to a new version.

👍 Community Prioritization: Want to see a specific feature or fix in the next release? Add a 👍 reaction to open Issues to help us prioritize what to build next!


🚀 Key Highlights

  • Adaptive calorie budgets: Dynamic Goal and Percentage Earn-Back no longer add activity calories or optional BMR credit to an Adaptive target a second time. Remaining calories may be lower after upgrading because these duplicate credits are removed. Recorded activity remains visible, and Manual targets retain their existing earn-back behavior.
  • Use Testflight app for the latest App as the live PROD is usually outdated.

What's Changed

Features

  • feat(mobile): daily mood check-in reminders by @Bubbles840 in #3028
  • feat(symptoms): track impact over time next to severity by @DUC750 in #3031
  • feat(mobile): time-weighted daily heart rate average on Health Connect by @DUC750 in #3034
  • feat(mobile): read mindfulness sessions from Health Connect by @DUC750 in #3042
  • feat(server): compare any two tracked metrics (statistics + endpoint) by @Bubbles840 in #3058
  • feat(calories): separate daily activity from adaptive baseline by @Bl4nk24 in #3061
  • feat(mobile): show running cadence and stride for watch runs, the run summary and trends by @Jerrys-modz in #3069
  • feat(mobile): add photo attachments to Sparky chat by @romanchenkop in #3068
  • feat(routes): generate routes with a routing provider by @Jerrys-modz in #3071
  • feat(mobile): add Wear OS companion app and Android watch-connectivity bridge by @vcdx71 in #3052
  • feat(mobile): compare any two tracked metrics (Compare screen) by @Bubbles840 in #3076
  • feat(foods): support arithmetic in quantity inputs by @Bl4nk24 in #2935
  • feat(exercise): store workout effort from the watch and Apple Health by @Jerrys-modz in #3065
  • feat(mobile): route editor with satellite view, draggable points and per-stretch snapping by @Jerrys-modz in #3077
  • feat: set your own heart rate zones (max and resting heart rate, zone method) by @Jerrys-modz in #3078
  • feat(symptoms): show and record the effect on the day over an episode on the web by @DUC750 in #3073
  • feat: compare an outcome before and since a habit started by @Bubbles840 in #3084
  • feat(mobile): read mindfulness sessions from Apple Health by @Jerrys-modz in #3091
  • feat(watch): follow a saved route on Apple Watch by @Jerrys-modz in #3090
  • feat(ai): ask Compare questions from the chat and MCP (sparky_compare_metrics) by @Bubbles840 in #3089
  • feat(goals): support weekly weight change targets by @Bl4nk24 in #3067
  • feat(healthkit): attach overnight HRV and resting heart rate to sleep by @Jerrys-modz in #3100
  • feat(mobile): keep sets when replacing an exercise of the same type by @Jerrys-modz in #3102
  • feat(mobile): medication adherence overview, month calendar and dose log by @Jerrys-modz in #3103
  • feat(run-program): realign the rest of a plan to finish on the goal day by @Jerrys-modz in #3109
  • feat(ai): use user language preference for food photo estimates by @Bl4nk24 in #3115
  • feat(frontend): Compare tab on the Reports page (day and week) by @Bubbles840 in #3108
  • feat(exercise): stop a synced workout counting twice in the calorie balance by @Jerrys-modz in #3114
  • feat(mobile): run splits table with pace bars, elevation and heart rate by @Jerrys-modz in #3135
  • feat(routes): route options and route style by @Jerrys-modz in #3141
  • feat(goals): keep past days' calorie targets when calorie settings change by @SisyphusMD in #3106
  • feat(heart-rate): detailed heart rate reports with a range navigator by @CodeWithCJ in #3143
  • feat: weekly running distance goal and race countdown by @Jerrys-modz in #3144
  • feat(frontend): ask since-a-habit-started questions on the Compare tab by @Bubbles840 in #3116
  • feat(frontend): enter sodium as grams of salt in the food editor by @surfnterd in #3150
  • feat: guided running fitness tests that set training paces, outdoors or on a treadmill by @Jerrys-modz in #3154
  • feat: fitness, fatigue and form curve, readiness score, estimated VO2 max and running power (server, mobile and web) by @Jerrys-modz in #3155
  • feat(garmin): re-pull the last few days in the scheduled sync by @surfnterd in #3148
  • feat(server): admin setting to turn off the GitHub release check by @surfnterd in #3149
  • chore(deps): update dependencies within the release-age window by @CodeWithCJ in #3177
  • feat(food): compare alternative barcode sources by @Bl4nk24 in #3126
  • feat(watch): record a jump rope session from the wrist by @trash-panda-v91-beta in #3127
  • feat: add Intervals.icu provider for activities and wellness by @cailloux in #3139
  • feat(exercise): plate calculator with a plate inventory in Equipment by @Jerrys-modz in #3186
  • feat(mobile): add a custom measurement category manager by @Jerrys-modz in #3194
  • feat(watch): easier-to-read watch app, Medications with Skip, Up Next and exercise swap by @zelphir in #3191
  • feat(mobile): add an opt-in guided check-in by @zeusal in #3197
  • feat(mobile): pin the set to do now, quick exercise swap, and photo zoom by @zelphir in #3192
  • feat(server): make the graceful shutdown timeout configurable by @SisyphusMD in #3204
  • feat(running): Zone 2 base program with heart rate guidance by @Jerrys-modz in #3201
  • feat(mobile): pick any start date and time when logging a symptom epi… by @Jerrys-modz in #3222
  • fix(chat): split the usage footer into cached, uncached and output tokens by @SisyphusMD in #3225
  • feat(mobile): make the Android widgets resizable by @zeusal in #3228
  • feat(mobile): copy meals to family diaries by @Bl4nk24 in #3218
  • feat(helm): mount existing claims for the server's uploads and backup volumes by @SisyphusMD in #3233
  • feat(mobile): restyle the + menu as Quick Actions and let users arrange it by @Jerrys-modz in #3242
  • feat(mobile): refresh What's New with running, routes, check-in, strength and heart rate cards by @Jerrys-modz in #3247
  • feat(wearos): add Nutrition, Sleep Health, Medications, and Exercise tiles by @vcdx71 in #3250

Fixes

  • fix(mobile): request new HealthKit types on iOS without a permission version bump by @SisyphusMD in #2998
  • ci: run the real-database test files one at a time by @SisyphusMD in #3032
  • test(mobile): align test expectations with updated Polish and Spanish translations by @nalvazhvu in #3053
  • fix(server): detect a vanished holder of the startup schema lock by @SisyphusMD in #3035
  • test(server): keep chat, food photo and check-in tool tests off the real database by @SisyphusMD in #3038
  • fix(db): finish renaming duplicate custom categories before the uniqu… by @Jerrys-modz in #3044
  • fix(health-data): keep fields the user edited when a workout is re-sent by @DUC750 in #3030
  • fix(mobile): keep the granted metrics when Enable All misses a permission by @Bubbles840 in #3059
  • test(server): avoid timeout from dynamic auth import by @mulatta in #3066
  • fix(cycle): constrain cycle deletion flow clearing to bleed period by @nalvazhvu in #3057
  • fix(training-programs): make program copy match the workouts by @Jerrys-modz in #3070
  • fix(frontend): send stored values for workout fields the user left alone by @DUC750 in #3072
  • fix(providers): validate Open Food Facts base URL and improve outbound request handling by @CodeWithCJ in #3079
  • fix(external-providers): align select policy actor check with family delegation by @nalvazhvu in #3081
  • fix(oura): normalize redirect URI and support client callback forwarding by @nalvazhvu in #3085
  • fix(server): record each migration in the transaction that applied it by @SisyphusMD in #3086
  • fix(ai): optimize Ollama vision with think:false, 1280px image cap, and gemma4 default by @nalvazhvu in #3087
  • fix(ai): cap local vision images at 1280px and update Ollama default to gemma4 by @nalvazhvu in #3088
  • fix(server): hide database and system error text in 5xx responses by @SisyphusMD in #3093
  • fix(server): survive a database connection dropped while in use by @SisyphusMD in #3094
  • fix(docker): run the server under tini so stopping the container shuts it down gracefully by @SisyphusMD in #3095
  • fix(server): stop overlapping edits of a grouped workout from deadlocking by @SisyphusMD in #3096
  • fix(mobile): complete background Health Connect recovery by @Bl4nk24 in #3098
  • fix(mobile): initialize Health Connect in background sync and handle dead client reconnect for aggregations by @nalvazhvu in #3092
  • fix(docker): bump Node.js base images to 24.22.1 for CVE-2026-111497 by @nalvazhvu in #3111
  • fix(mobile): word a yes/no Compare difference as against the other days by @Bubbles840 in #3107
  • fix(exercise): re-estimate calories when sets are added to an entry by @Jerrys-modz in #3105
  • fix(garmin): parse strength workout sets and telemetry from FIT imports by @nalvazhvu in #3112
  • fix(garmin): prevent coordinate shifts in activity metrics and filter GPS outliers by @nalvazhvu in #3117
  • fix(caffeine): add relative dates to recent doses and clarify chart transitions by @nalvazhvu in #3122
  • fix(frontend): restore YAZIO repository link in provider create and edit forms by @nalvazhvu in #3123
  • fix(garmin): keep a pending MFA sign-in in a sealed token (a restart or second replica lost it, and a retried code was resent) by @SisyphusMD in #3119
  • fix(server): retry database connections through a restart (every request in the window answered 500) by @SisyphusMD in #3124
  • fix(server): hide database errors in hand-written 500 responses (33 route bodies still sent error.message) by @SisyphusMD in #3125
  • fix(garmin): treat Garmin's -1 step weight as no weight in workout definitions by @RealHirn in #3129
  • fix(server): wait for the database at startup (a server started before PostgreSQL exited and restarted with back-off) by @SisyphusMD in #3133
  • fix(server): answer 503, not 401, when the session can't be checked (a database restart signed mobile users out) by @SisyphusMD in #3138
  • fix(calories): show progress against the activity-adjusted food budget by @Bl4nk24 in #3140
  • fix(exercise-stats): report personal record and course times for the exact distance by @Jerrys-modz in #3145
  • fix(exercise): count the applied calories in chatbot totals and Reports by @Jerrys-modz in #3147
  • fix(goals): pick each day's calorie rules by date, not by the database's text sort by @SisyphusMD in #3156
  • fix(health-data): one Active Calories entry per user and day under concurrent imports by @SisyphusMD in #3158
  • fix(measurements): one Daily or Hourly custom measurement reading per slot under overlapping writes by @SisyphusMD in #3164
  • fix(heart-rate): show the person's own zones in the Heart Rate reports by @Jerrys-modz in #3165
  • fix(symptoms): keep every severity and impact reading of overlapping edits (both edits started from the same old timeline) by @SisyphusMD in #3168
  • fix(server): let responses finish when the server stops by @SisyphusMD in #3163
  • fix(exercise): fill a workout edit's omitted fields from the locked entry (an upload or edit landing mid-edit was overwritten) by @SisyphusMD in #3170
  • fix(exercise-entries): answer 404 for an unknown exercise_id (it surfaced as a 500) by @SisyphusMD in #3172
  • fix(frontend): truncate long names in medicine cabinet list by @stoamandl in #3183
  • fix(mobile): keep progress photo headers below the iOS status bar by @zeusal in #3190
  • fix(frontend): prevent layout shift when opening selects and dialogs by @stoamandl in #3195
  • fix(mobile): keep form screen headers below the iOS status bar by @SisyphusMD in #3200
  • fix(compare): honest since answers for slow-moving outcomes by @Bubbles840 in #3120
  • fix(sleep): count a night once when two sources record it by @Bubbles840 in #3180
  • fix(goals): apply each weekly goal plan only to its own dates by @SisyphusMD in #3198
  • fix: ask for the workout effort permission once by @Jerrys-modz in #3199
  • fix(server): finish running jobs and release sync claims on shutdown by @SisyphusMD in #3203
  • fix(helm): give the server a startupProbe so a long migration is not restarted by @SisyphusMD in #3206
  • fix(auth): reset the mfa-factors limit when its window ends by @SisyphusMD in #3207
  • fix(backup): build each backup in a private work directory and publish it whole (a crash or overlapping run left partial archives that retention counted as backups) by @SisyphusMD in #3208
  • fix(helm): create the external database Secret from values (the server referenced a Secret the chart never made) by @SisyphusMD in #3209
  • fix(server): stop provider syncs that lose their claim or stall by @SisyphusMD in #3213
  • fix(mcp): say create_food nutrients are per quantity × unit by @benjamin-m-holden in #3214
  • fix(backup): clear day-old .tmp work dirs when a backup starts by @SisyphusMD in #3215
  • fix(ai): log the exact external food the lookup returned by @SisyphusMD in #3220
  • perf(ai): cut Sparky chat token use by @SisyphusMD in #3224
  • fix(watch): stop long exercise names being cut off, and make the larger text setting cover the whole watch by @Jerrys-modz in #3226
  • fix(workout): remove exercise-level notes field from preset editor by @CodeWithCJ in #3227
  • fix(ai): save foods at the serving the lookup quoted by @SisyphusMD in #3221
  • fix(calories): use Garmin and Polar daily totals in Device Projection by @CodeWithCJ in #3231
  • fix(watch): honor haptics setting, use GoalPalette macro colors, localize Apple Watch strings by @Jerrys-modz in #3230
  • fix: save workout effort with a granted permission, and stop re-asking for routes by @Jerrys-modz in #3235
  • fix(server): apply RLS policies at startup only when they changed by @SisyphusMD in #3239
  • fix(sleep): keep a nap as its own sleep entry instead of merging it into the night by @CodeWithCJ in #3243
  • fix(auth): share IP rate-limit budgets across server instances by @SisyphusMD in #3245
  • fix(ai): require energy and all three macros before saving an Open Food Facts food by @SisyphusMD in #3249

Documentation

  • docs(readme): add README translations and an inline language bar by @zeusal in #3043
  • docs(install): update how long a lost server holds the startup lock by @SisyphusMD in #3097
  • docs: document the Apple Watch and Wear OS companion apps by @Jerrys-modz in #3118
  • Missing documentation by @lukyjay in #2660
  • docs(agents): add issue and enhancement planning skills, shared planning rules, and tool-neutral agent conventions by @CodeWithCJ in #3171
  • docs(mobile): add DESIGN.md describing the current mobile design system by @zeusal in #3182
  • docs(agent-docs): list only needed changes in PR review reports by @CodeWithCJ in #3212
  • docs(mobile): add watch apps section to DESIGN.md by @Jerrys-modz in #3219
  • docs: keep limits and job status in the database, not server memory by @SisyphusMD in #3238

Other Changes

  • chore(helm): update chart version to v1.9.0 by @github-actions[bot] in #3026
  • chore(umbrel): update app package to v1.9.0 by @github-actions[bot] in #3027
  • chore(i18n): sync translations from Weblate by @github-actions[bot] in #3051
  • chore: sync db_schema_backup.sql with migrations by @github-actions[bot] in #3054
  • chore: sync db_schema_backup.sql with migrations by @github-actions[bot] in #3055
  • chore: sync db_schema_backup.sql with migrations by @github-actions[bot] in #3062
  • chore: sync db_schema_backup.sql with migrations by @github-actions[bot] in #3074
  • chore: sync db_schema_backup.sql with migrations by @github-actions[bot] in #3075
  • chore: sync db_schema_backup.sql with migrations by @github-actions[bot] in #3080
  • chore: sync db_schema_backup.sql with migrations by @github-actions[bot] in #3082
  • chore: sync db_schema_backup.sql with migrations by @github-actions[bot] in #3101
  • chore: sync db_schema_backup.sql with migrations by @github-actions[bot] in #3146
  • chore: sync db_schema_backup.sql with migrations by @github-actions[bot] in #3151
  • chore: sync db_schema_backup.sql with migrations by @github-actions[bot] in #3152
  • chore: sync db_schema_backup.sql with migrations by @github-actions[bot] in #3153
  • chore: sync db_schema_backup.sql with migrations by @github-actions[bot] in #3162
  • chore: sync db_schema_backup.sql with migrations by @github-actions[bot] in #3169
  • chore: sync db_schema_backup.sql with migrations by @github-actions[bot] in #3173
  • chore(nix): update pnpm deps hashes by @github-actions[bot] in #3179
  • chore: sync db_schema_backup.sql with migrations by @github-actions[bot] in #3193
  • chore: sync db_schema_backup.sql with migrations by @github-actions[bot] in #3241
  • chore: sync db_schema_backup.sql with migrations by @github-actions[bot] in #3246
  • chore: sync db_schema_backup.sql with migrations by @github-actions[bot] in #3248
  • chore(i18n): sync translations from Weblate by @github-actions[bot] in #3251

New Contributors

Full Changelog: v1.9.0...1.10.0

Don't miss a new SparkyFitness release

NewReleases is sending notifications on new releases.