What's new

Recent updates, improvements and new features. Newest first.

16 Jul 2026

Latest

Fixed two account/data-deletion crashes, records max-reps leaderboard

πŸ›

Deleting a food item still used in a recipe could throw a server error

Removing a food from your library while it was still an ingredient in a saved recipe could fail with a raw server error. It now shows a clear message asking you to remove it from the recipe first.

πŸ›

Account deletion could fail for anyone who had redeemed a promo code

Deleting your account (or the scheduled auto-delete after a cancellation) could fail with a server error if you had ever redeemed a promo code, because that record wasn't cleaned up before the rest of your account. Fixed β€” deletion now clears promo redemptions first.

πŸ†

Records β€” all-time top 5 for max reps

Personal Records now has an "All-Time Top 5 β€” Max Reps" leaderboard, ranking exercises by the most reps completed in a single set, alongside the existing 1RM, session-volume, and cardio-distance leaderboards.

15 Jul 2026

Records session-volume leaderboard, saved recipes in Quick Log, journal personal-best streak

πŸ†

Records β€” all-time top 5 for session volume

Personal Records now has an "All-Time Top 5 β€” Session Volume" leaderboard, ranking exercises by the most weight moved in a single session, alongside the existing 1RM and cardio-distance leaderboards.

πŸ₯—

Saved recipes in Quick Log

Recipes saved under Library β†’ Recipes now appear in the ⭐ Favourites tab when logging food, alongside favourite foods and saved meals β€” pick a recipe, adjust servings, and log it in one tap.

πŸ““

Journal β€” personal-best streak

The Journal history now shows a "PB:N" badge alongside your current logging streak once your longest-ever run beats it, matching the personal-best badge habits already show.

14 Jul 2026

Fixed a water-log date bug causing "Invalid Date" feed entries, cardio all-time leaderboard

πŸ›

A malformed water log date could show up as "Invalid Date" in your feed

Logging water with a non-standard date value (rather than the usual YYYY-MM-DD) was accepted but not normalized before saving, so it could create a second, hidden entry for the same day β€” corrupting that day's total and showing up as an "Invalid Date" row in your activity feed. Water logs now always normalize to the calendar day before saving.

πŸ†

Records β€” all-time top 5 for cardio

Personal Records now has an "All-Time Top 5 β€” Longest Distance" leaderboard for running, cycling, walking and swimming, mirroring the existing strength 1RM leaderboard.

13 Jul 2026

Fixed deleted workouts resurfacing after sync, hardened admin endpoints, medication 30-day adherence

πŸ›

Some deleted workouts could still resurface after a sync

The 12 Jul fix stopped newly-deleted workouts from leaving orphaned data behind, but didn't retroactively clean up older orphans from before the fix β€” those could still get silently regrouped into a brand new workout entry the next time sync ran. Sync no longer resurrects manually-logged workouts this way, and the leftover orphaned records have been cleaned up. Also removed an unused internal debug endpoint that had the same underlying issue.

πŸ›

Malformed requests could crash a few admin-only endpoints

A handful of admin and promo-code endpoints returned a blank server error instead of a clean message if a request body was malformed β€” not reachable through normal use of the app, but a robustness gap. Fixed, matching the same hardening applied elsewhere on 8 Jul.

πŸ’Š

Medications β€” 30-day adherence

The adherence badge on Regular medications now also shows a 30-day percentage alongside the 7-day count, e.g. "Vitamin D: 6/7 days Β· 84% (30d)" β€” matching the rolling 7/30-day compliance habits already show.

12 Jul 2026

Dashboard cache fix, deleted-workout data leak fix, cardio + medication records

πŸ›

Dashboard nutrition/habit summary could go stale

The "Today so far" summary on the dashboard recap card was cached in your browser for the whole day, so editing or deleting a food log, workout or habit after your first visit didn't update the numbers shown until the cache reset. It now quietly reconciles with the latest data in the background, at no extra AI cost.

πŸ›

Deleting a manual workout could leave data behind β€” and let it resurface later

Deleting a manual workout didn't clean up its underlying source data, which could later get silently regrouped into a brand new workout entry by the sync process β€” including data you'd already deleted. Deleting a workout now fully removes it. Also fixed: this endpoint was missing an ownership check present on similar endpoints elsewhere in the app.

πŸ…

Records β€” This Month's Cardio

The Records page now highlights any cardio personal best set this calendar month (longest distance, best pace, longest time, race bests) the same way strength records already do.

πŸ’Š

Medications β€” 7-day adherence

Regular medications now show how many of the last 7 days you've logged a dose, right above your medication history.

11 Jul 2026

Food logging and habit trigger crash fixes, AI usage admin panel

πŸ›

Food log crash on missing quantity

Logging a food item without a quantity crashed the request instead of showing a friendly error. Quantity is now always required, with a clear message if it's missing.

πŸ›

Food macros could get "stuck" on a reused name

The per-100g nutrition rate saved the first time you logged a food by name was being reused for every later log under that same name, ignoring whatever macros you entered afterwards. Logging a food now refreshes its stored macros from what you actually enter each time.

πŸ›

Habit auto-complete trigger crash on malformed input

Creating or editing a habit's auto-complete trigger with an unrecognised value crashed instead of returning a clear error β€” not reachable through normal use of the app, but a robustness gap. Fixed.

8 Jul 2026

API hardening, habit best-day insight, journal mood correlation

πŸ›

Malformed requests could crash the server

A number of API endpoints returned a blank server error instead of a clean message if a request body was malformed β€” not reachable through normal use of the app, but a robustness gap. Fixed across all affected endpoints.

πŸ“…

Habits β€” best day of the week

Open the edit (✏️) sheet on any habit and the 12-week heatmap now also shows which day of the week you're most likely to complete it, e.g. "Best day: Wed (86%)".

πŸ““

Journal β€” tag and mood correlation

The Month summary in Journal History now shows how your mood compares on days you used your most common tag versus days you didn't, once there's enough data in a month to make it meaningful.

7 Jul 2026

Journal streak, food log sanitisation fix

πŸ”₯

Journal streak

The Journal History header now shows a "πŸ”₯ N day streak" badge once you've logged two or more consecutive days, alongside your 7-day mood/energy/stress average.

πŸ›

Food log item names not sanitised

Logging food via Quick Log (search, photo, describe or PDF import) didn't strip HTML from item names the way editing an existing item already did, so raw markup could end up saved in your personal food library. Fixed β€” item names are now sanitised consistently everywhere.

6 Jul 2026

Habit history heatmap, hydration warning fix

πŸ“Š

Habit history heatmap

Open the edit (✏️) sheet on any habit to see a 12-week history heatmap β€” a quick visual of which days you hit it, missed it, or it wasn't scheduled.

πŸ›

Console warning on every page load

A harmless but noisy React hydration warning fired on every single page load, caused by the dark-mode/text-size script that runs before the page finishes loading. Silenced correctly rather than suppressed by hiding the underlying script.

5 Jul 2026

Records reorganised, rehab pain trend chart, integration data drawer

πŸ†

Records β€” this month + all-time top 5

The Records page now leads with a "This Month's Records" strip showing any PR set in the current calendar month, and an "All-Time Top 5" leaderboard ranked by estimated 1RM. The full searchable, sortable exercise list remains below under "All Records".

πŸ“ˆ

Rehab pain trend chart

When you have two or more Rehab sessions logged with pain levels, the Training tab now shows a line chart of pre- and post-session pain over the selected period, so you can see whether things are trending in the right direction.

πŸ”Œ

Integrations β€” see exactly what's been synced

Click the β–Ό on any connected integration to expand a drawer showing counts of what FitMesh has pulled from that source β€” workouts, step days, sleep nights, heart rate samples, weight logs β€” with quick links to jump to each view.

πŸ›

Manual workout logging didn't refresh the UI

Saving a new manual workout closed the modal but didn't refresh the Feed or Training list, so the new entry was invisible until a full page reload. Fixed.

πŸ›

Distance and steps wiped on manual workout edit

Editing a manually logged run or walk reset its distance and step count to blank, the same bug class previously fixed for rehab pain levels. Both fields now load and save correctly.

3 Jul 2026

Rehab split into Appointment and Training, pain level edit fix

✨

Rehab is now two activity types

Rehab Appointment logs a treatment session (physio, chiro, massage) with pain levels and notes but no exercise sets. Rehab Training logs a structured rehab exercise session with the full block/set editor, matching how strength training is logged. Existing Rehab entries are unaffected.

πŸ›

Editing a rehab workout no longer wipes its pain levels

Pre- and post-session pain levels were never included when a workout was loaded for editing, so saving any change to a rehab session β€” even just fixing the date β€” silently reset its pain levels to blank. Fixed: pain levels now load correctly into the edit form and are preserved on save.

2 Jul 2026

Android PWA feel, Strava compliance update, waitlist page

πŸ“±

Android PWA native feel hardening

Removed the blue tap flash on tappable elements (-webkit-tap-highlight-color), suppressed rubber-band overscroll so the app feels native in standalone mode, clamped input font sizes to 16 px to prevent iOS auto-zoom on focus, and added active press feedback to the bottom navigation bar.

πŸ”’

Strava view-only β€” excluded from AI and PT reports

Strava's June 2026 API terms prohibit using their data in AI or machine learning features. Your Strava activities are still visible in the feed and timeline, but Daily Inspiration, AI coaching context, and PT check-in reports are now built exclusively from your other connected sources. The Data Sources page has been updated with the current policy and recommends Polar as the primary integration. A bug where Strava workouts could leak into the Monday morning AI context has also been fixed.

✨

Beta waitlist page (/try)

A public sign-up page at /try lets anyone join the early access waitlist. Logged-in users see a one-click 'Add me to the list' button pre-filled with their account email. Duplicate sign-ups return a friendly message rather than an error.

1 Jul 2026

Rehab pain tracking, exercise set validation, tighter habit auto-complete

✨

Pain levels for rehab sessions

When logging a Rehab / Physio session, you can now record a pre-session and post-session pain level (1 = none β†’ 10 = severe). The picker uses colour coding: green for low pain, amber for moderate, red for high. Data is saved per session and will feed into pain trend charts in a future update.

πŸ›

Editing a rehab session no longer fails silently

The workout edit API was missing REHAB from its list of valid activity types, so saving edits to a rehab session returned a 400 error without explanation. Fixed.

πŸ›‘οΈ

Timed and distance exercise sets now validated server-side

Set duration is now capped at 86,400 seconds and distance at 200,000 m. Previously these were stored without bounds checks.

✨

Habits auto-tick on full history import

When you trigger a historical sync (Strava, Polar, Fitbit, Garmin), habits with matching activity triggers are now auto-completed retroactively across the full imported window β€” not just the last 7 days.

30 Jun 2026

Delete Now fix, sleep custom date range, workout list cleanup

πŸ›

Admin "Delete Now" fixed for promo users

Immediately deleting a user who had redeemed a promo code silently failed due to a missing foreign-key delete step. The deletion transaction now clears promo redemptions first, and an error message is shown if anything else goes wrong.

✨

Sleep view: custom date range

The Sleep tab now has a Custom option alongside the period presets. Select it to enter any from/to date range and hit Apply to load that window of sleep history.

πŸ›

Steps, water & sleep no longer appear in workout history

Passive tracking entries synced from devices (daily step counts, water logs, sleep sessions) were occasionally appearing in the workout list. These are now filtered out at the API level β€” only actual workout sessions appear.

πŸ›

Feed now shows actual workout titles

Workout cards in the activity feed were showing "Workout" instead of their actual title (e.g. "Upper Body Strength"). Fixed a type mismatch between the API response and UI component.

✨

Notes & location in expanded workout cards

When you expand a workout card in the feed, any notes you logged and the location label now appear below the stats. Previously these were invisible despite being saved.

πŸ›‘οΈ

HTML stripped from workout titles and locations

Workout titles and location labels now strip HTML tags before saving, closing the last XSS sanitisation gaps. Previously only notes were sanitised.

29 Jun 2026

New inspiration tones, sleep date picker, HTML sanitisation for names

✨

3 new Daily Inspiration tones

Pick from Stoic (wisdom & discipline), Science Nerd (data-driven analysis), or Comedian (funny & light-hearted) in the inspiration settings. Total: 6 β†’ 9 tones.

✨

Sleep view: date range picker

The Sleep tab now has period presets β€” 7 days, 2 weeks, 30 days, 3 months, or All time β€” so you can focus on recent trends or browse your full history.

πŸ›‘οΈ

HTML stripped from all name fields

Food item names, habit names, and medication names now strip HTML tags before saving β€” closing the last XSS gaps. Notes fields were already sanitised.

27 Jun 2026

Validation hardening: required mood, food item names, HTML sanitisation

πŸ›

Journal entries now require mood

Previously, journal entries could be created without a mood rating. Mood (1–5) is now required. Energy and stress remain optional.

πŸ›

Food log items require a name

Food log items without a foodItemId or recipeId must now include a name. Previously, missing names were silently defaulted to "Unknown".

πŸ›‘οΈ

HTML tags stripped from text inputs

All notes fields (journal, workouts, body measurements, medications) now strip HTML tags before saving, preventing stored XSS.

26 Jun 2026

Onboarding: journal, medications & promo codes; workout date validation

✨

Journal & Medications in onboarding

The onboarding flow now includes Journal and Medications as tracking preferences alongside Training, Habits, Sleep, Nutrition, and Steps. Selecting Journal or Medications also surfaces relevant habit suggestions.

✨

Promo code entry during onboarding

New users can now redeem a promo code during onboarding. A "Have a promo code?" link on the first screen expands an input field. Invalid codes show a clear error; valid codes unlock PRO immediately.

πŸ›

Workout date validation tightened

Manually logged workouts previously accepted dates up to 2 years in the future. Now consistent with all other endpoints β€” dates cannot be more than 1 day in the future.

25 Jun 2026

Water intake in feed & weekly stats, invalid JSON error handling

✨

Water intake in activity feed

The daily nutrition card in your activity feed now shows water intake alongside calories, protein, carbs, and fat. Days with water logged display the total in litres with a cyan highlight.

✨

Average daily water in weekly stats

The Training tab weekly stats bar now includes an "avg water/day" card showing your average daily water intake for the selected period.

✨

Water context in Daily Inspiration

The AI daily inspiration now sees your water intake for today and yesterday, so coaching recaps can comment on hydration alongside nutrition and training.

πŸ›

Invalid JSON no longer causes 500 errors

Sending a malformed request body to the workout, food log, or water endpoints previously returned a 500 server error. These routes now return a clear 400 "Invalid JSON" message.

24 Jun 2026

Journal search, weekly stats dashboard cards, medication validation

✨

Journal search

Search your journal entries by notes text or tags. A search bar below the calendar filters entries as you type, making it easy to find past entries about specific topics or tagged moods.

✨

Weekly stats: nutrition & wellbeing cards

The weekly stats bar on the Training tab now shows average daily calories, average daily protein, and average mood/energy/stress scores for the selected period. A quick snapshot of how training, nutrition, and wellbeing align.

πŸ›

Medication type validation

The medication API now rejects invalid medication types with a clear error instead of silently defaulting to ONE_OFF. Consistent with all other API validation.

22 Jun 2026

COMPLIANCE habit frequency, exercise name validation hardening, AI inspiration sync awareness

πŸ›

COMPLIANCE frequency now accepted for habits

The habit API validation was missing the COMPLIANCE frequency type, even though the database schema supported it. Habits with floor/target/stretch compliance tiers can now be created and edited as intended. Fixed in both POST and PATCH routes. (BUG-167)

πŸ›

Null exercise names no longer bypass workout validation

Sending an exercise with a null name in workout sets skipped the name validation entirely and saved to the database. The validator now treats null and undefined exercise names as empty strings, correctly rejecting them with "Exercise name cannot be empty". (BUG-168)

πŸ›

Daily Inspiration now waits for sync before generating

The AI recap was firing immediately on dashboard load, before the auto-sync had a chance to pull the latest data from connected apps. The inspiration card now waits for the dashboard sync to complete, so the AI sees your most recent workouts and habits before writing the recap.

21 Jun 2026

AI recipe generator, owner rate-limit bypass, AM/PM inspiration limits

✨

AI recipe generator

Describe a dish (e.g. "chicken stir fry for 2") and AI generates the full recipe β€” name, ingredients with macros, and step-by-step cooking method. Find it under Library β†’ Recipes β†’ + Create recipe β†’ ✨ Generate recipe. Uses the RECIPE_GENERATE quota (free: 3/day, PRO: 20/day).

πŸ”„

Daily Inspiration now uses AM/PM refresh limits

Instead of a flat daily limit, Daily Inspiration now allows 2 refreshes in the morning (midnight–noon UTC) and 3 in the afternoon/evening (noon–midnight UTC). The transparency page and How-To guide have been updated to reflect this.

⚑

Owner accounts bypass AI rate limits

The app owner's account is no longer subject to daily AI usage caps β€” all AI features are unlimited for accounts in the owner list.

15 Jun 2026

Fixed nutrition log showing yesterday's meals, tightened Walk habit auto-completion

πŸ›

"Today" in Nutrition no longer shows yesterday's logged meals

The nutrition log's date range was computed using the server's local time, which could shift the day boundary and pull the previous day's entries into "today" (and vice versa) depending on when in the day you checked. Date ranges for both the daily log and the history/reports view are now computed in UTC, matching how dates are stored β€” "today" now reliably shows only today's entries. (BUG-158)

πŸ›

Walking habits no longer auto-complete from passive step counts alone

Habits with a "Walking" trigger could be auto-marked complete just from a synced "Daily Steps" total, even on days with no actual walk logged. Daily step aggregates are now excluded from workout-based habit triggers β€” Walking (and other workout-type) habits only auto-complete from a real recorded activity. Step-count goals continue to work via dedicated "Steps" habit triggers. (BUG-159)

13 Jun 2026

Duplicate detection for repeated manual entries, PR recalculation fix, copy meals from any day

πŸ”

Duplicate warning now also catches two manual entries for the same session

The duplicate-warning check introduced on 12 Jun only compared a new manual workout against sessions synced from Strava, Hevy, Polar or similar. Logging the same session manually a second time slipped through. It now also flags when a new manual entry overlaps in time, duration and activity type with another manual entry you logged earlier, with the same "This looks like a duplicate β€” save it anyway?" prompt.

πŸ›

Recalculating personal records no longer leaves stale entries behind

"⚑ Recalculate from history" on the Achievements page previously only added new PRs and volume milestones β€” it never removed ones whose underlying workout had since been deleted or edited, so outdated records could linger indefinitely. Recalculating now clears your existing PRs and volume milestones first, then rebuilds them from your current workout history. (BUG-157)

✨

Copy meals from any past day

Nutrition logging now has a "πŸ“… Copy meals from another day…" option alongside "Copy yesterday's meals" β€” pick any past date from a calendar and copy that day's logged meals into today. Handy for repeating a meal plan from earlier in the week.

12 Jun 2026

Manual workout duplicate warning, clearer macro calculator errors

πŸ”

Manual workout logging now warns about likely duplicates

When you manually log a workout that overlaps in time, duration and activity type with a session already synced from Strava, Hevy, Polar or another source, FitMesh now shows a warning β€” "This looks like a duplicate of … β€” save it anyway?" β€” before saving. Confirm to log it anyway, or cancel to avoid double-counting.

πŸ›

Macro calculator now shows the real reason a save failed

Saving the macro calculator results previously showed a generic "2 of 2 writes failed" message if a value was out of range. It now shows the specific validation error for each part that failed (e.g. body measurements vs. nutrition targets), so you know exactly what to fix.

11 Jun 2026

Daily Inspiration formatting fix

πŸ›

Daily Inspiration recap no longer shows raw "#" heading characters

The AI-generated check-in message is displayed as plain text, but the model occasionally opened with a "# Heading" or wrapped phrases in **bold** markdown despite being told not to. That formatting now shows up literally as "#" or "**" in the recap. The API now strips markdown heading and emphasis syntax from the generated message before it's saved and displayed.

8 Jun 2026

Habit weekly compliance fix, Daily Inspiration persistence, security fix

βœ…

Weekly habit compliance percentage now correct

Habits set to Weekly or Times per week frequency were showing the wrong compliance percentage in the 7-day and 30-day badges β€” for example, ticking a weekly habit once in a week showed 14% instead of 100%. The calculation now correctly measures sessions completed vs. sessions required for the period, not days ticked vs. total days.

✨

Daily Inspiration setting now persists across devices and after clearing storage

If you enabled Daily Inspiration and then opened the app on a different device β€” or your browser cleared its local storage β€” the setting would reset to Off. The server-synced preference was being written to the wrong local storage key. It now correctly seeds the user-specific key that the component reads from, so your enabled/tone preference is restored from the server on any device.

πŸ”’

Food log delete security fix

The food log deletion endpoint now verifies that the log belongs to the authenticated user before deleting it. Previously an authenticated user who knew or guessed another log's ID could delete it. (BUG-155)

7 Jun 2026

Daily Steps habit trigger, exercise merge validation

πŸ‘£

New habit trigger: Daily Steps

Habits can now use a "Daily Steps" trigger type. When your synced daily step count (from Polar, Fitbit, or Google Fit) meets or exceeds the step target set on the habit (via Target Value β€” defaults to 10,000), the habit is automatically marked complete for that day. Set up a "hit 10k steps" habit and connect a step-tracking integration to take advantage. (REQ-154)

πŸ”’

Exercise merge validation hardening

The exercise name merge endpoint (used in the Training tab to consolidate duplicate exercise names) now validates that canonical and alias names cannot exceed 200 characters, each alias must be a string, and no more than 50 aliases can be submitted at once. Previously, arbitrary-length strings were accepted and non-string values caused a 500 error. (BUG-151, BUG-152)

πŸ›

Recovery endpoint invalid-date crash fixed

Passing a non-date string as the "from" or "to" parameter to the Recovery data endpoint now returns a clear 400 error instead of a 500 crash. (BUG-153)

6 Jun 2026

Daily steps in feed, password & email validation hardening

πŸ‘£

Daily steps now appear in the activity feed

If you have Fitbit, Polar, or Google Fit connected, your daily step counts now appear as compact πŸ‘£ step cards in the feed timeline β€” one per day, showing the total steps pulled from your device's daily aggregate. Step cards sit just below workout cards in the daily stack, giving you a historical view of your activity alongside workouts and habits. (REQ-150)

πŸ”’

Password change, PT email, and profile source length limits

Three additional validation gaps closed. The change-password form now caps the new password at 1,000 characters (consistent with signup) β€” previously an arbitrarily long password could trigger a slow bcrypt computation. The PT connection request form now rejects email addresses longer than 254 characters (RFC 5321 limit). The steps source preference field on the profile endpoint is now capped at 100 characters. (BUG-147, BUG-148, BUG-149)

5 Jun 2026

Copy day includes logged food, signup validation, bug report limits

πŸ“‹

"Copy entire day" now includes logged food, not just planned meals

The "⧉ Copy day" button in the Nutrition Planner tab now copies both meal plan entries and any food that was actually logged on the source day. Previously it only copied planned meals (MealPlan records) and silently dropped food log entries. The modal summary now shows the combined count (e.g. "2 plans + 1 logged meal") and the empty-state message is updated when a day has neither plans nor logged food. (REQ-145)

πŸ”’

Sign-up email format validation added

Creating a FitMesh account now validates that the email address contains an "@" and a domain (e.g. user@example.com). Previously any string was accepted β€” including strings with no "@" symbol. Emails longer than 254 characters (RFC 5321 limit) are also rejected. (BUG-142)

πŸ›

Bug report and PT notes length limits

The bug/feature report form now caps URL and notes at 2,000 characters, page title at 200 characters, and screenshot URL at 2,000 characters. PT trainer notes are capped at 10,000 characters. Previously all these fields were unbounded. (BUG-141, BUG-143)

4 Jun 2026

Strava API compliance, meal-plan validation hardening

πŸ”’

Strava data excluded from PT reports and AI features

FitMesh now complies fully with Strava's updated API terms (effective 1 Jun 2026). Workouts synced via Strava are no longer included in PT coaching reports or fed into AI-powered features (Daily Inspiration). These workouts remain visible to you in the Training tab and Feed as normal β€” only third-party sharing and AI use is restricted. Polar is recommended as the primary integration for full data access with no restrictions. (REQ-125)

πŸ—“οΈ

Meal plan validation: date bounds, mealType enum, label length, item quantity

The meal planning API (POST /api/food/plan) now fully validates input. Date must be 1970 or later and no more than 1 day in the future. mealType must be one of BREAKFAST, LUNCH, DINNER, SNACK, DRINK β€” invalid values now return a 400 with a plain-English message instead of a 500 crash. Plan labels are capped at 200 characters. Item quantities must be greater than 0 and no more than 10,000g. All the same rules apply when editing a plan (PUT /api/food/plan/[id]), with status validated against PLANNED, CONFIRMED, SKIPPED. (BUG-130, BUG-131, BUG-132, BUG-133)

3 Jun 2026

Regular vs one-off medications, habit history % display, validation hardening

πŸ’Š

Medications β€” Regular vs One-off type

Each medication log now carries a type: Regular (an ongoing medication taken routinely, e.g. blood pressure pills, vitamins) or One-off (taken as needed, e.g. Paracetamol for a headache). The log form has a clear ⚑ One-off / πŸ”„ Regular toggle with descriptive helper text. Your history is split into two sections β€” Regular medications at the top, One-off doses below β€” so you can see at a glance which are routine and which were situational. Each card shows a colour-coded badge. (REQ-126)

βœ…

Habits β€” completion % shown in activity feed

Habit cards in the activity feed now show a colour-coded completion percentage for partial days (e.g. "3 of 5 habits (60%)"). Amber for β‰₯75%, orange for β‰₯50%, grey below. All-done days still show "All habits done". (BUG-118)

πŸ”’

Validation hardening β€” compliance, label consistency

Habit complianceTarget (0–1) and complianceWindow (1–365 days) now reject negative and out-of-range values. Error message labels are now consistently capitalised across all endpoints: Steps, Distance (workouts), Calories, Protein, Carbs, Fat (food), Top size, Bottom size (body measurements), Date of birth (profile). (BUG-127, BUG-128)

2 Jun 2026

Generic medication tracking, saved-meals validation & recipe validation

πŸ’Š

Medications β€” now works for any drug, not just GLP-1s

The medication log now supports any medication β€” Paracetamol, Ibuprofen, Aspirin, vitamins, supplements, and prescription drugs, alongside the existing GLP-1 options. The autocomplete list has grown from 7 to 30+ common medications. Dosage units expanded from 4 to 9 (mg, ml, mcg, g, IU, tablets, capsules, drops, units). Side effects expanded from 11 to 16 quick-tags. A new "Your medications" panel at the top shows your recently logged medications as one-tap chips β€” click any to pre-fill the form instantly for a repeat dose. (REQ-117)

🍽️

Saved meals: name length capped, item quantity validated

Saved meal names are now capped at 200 characters (previously unlimited). Item quantities on saved meals must be greater than 0 and no more than 10,000g β€” negative and zero quantities are now rejected with a clear error. (BUG-119, BUG-120)

πŸ“–

Recipes: name length capped, servings must be β‰₯ 1

Recipe names are now capped at 200 characters. Servings must be a number of 1 or more β€” zero, negative, and non-numeric values are rejected. Applies to both recipe creation (POST) and editing (PUT). (BUG-121, BUG-122)

πŸ‹οΈ

Key lift names now capped at 200 characters

The key lifts configuration (used on the weekly report) now validates each entry: names must be non-empty strings and cannot exceed 200 characters β€” matching the cap already in place for exercise names on workout logs. (BUG-123)

πŸ”—

Integration suggestion form: length limits added

The "Suggest an integration" form now caps appName at 200 characters, reason at 1,000 characters, and email at 200 characters. Previously all fields were unbounded. (BUG-124)

1 Jun 2026

Consistent validation error messages across edit forms

πŸ’¬

Workout and habit edit forms now show plain-English errors

Editing a workout or habit via the PATCH endpoint was still surfacing raw API field names in validation errors ("durationMinutes must be a valid number", "avgHeartRate cannot exceed 250", "timesTarget must be a valid number"). These have been updated to match the human-readable labels already used by the creation forms: "Duration must be a valid number", "Average heart rate cannot exceed 250 bpm", "Times target must be a valid number", etc. (BUG-114, BUG-115)

πŸ₯—

Nutrition settings validation errors now name the field in plain English

When a nutrition target was invalid, the error said "calorieTarget must be a non-negative number" and "calorieTarget value is unrealistically high". These now read "Calorie target must be a non-negative number" and "Calorie target cannot exceed 100,000" β€” matching the style used across the rest of the app. Applies to Calorie, Protein, Carb, Fat and Water targets. (REQ-116)

31 May 2026

Validation hardening & new edit endpoints

🍽️

Food item names can no longer be saved as blank

Both the food log POST and the food item edit (PATCH) endpoints now reject empty or whitespace-only names with a clear "Food item name cannot be empty" error. Previously, submitting an empty name would silently write a blank entry to the database.

πŸ’Š

Medication edit: future dates now rejected

Editing a medication entry via the PATCH endpoint previously allowed setting the taken-at date far into the future (e.g. 2028). The PATCH handler now enforces the same tomorrow cap as the POST endpoint β€” takenAt cannot be more than 1 day in the future.

πŸ“

Correct a body measurement without deleting it

A new PATCH /api/body/measurements/{id} endpoint lets you update individual fields on an existing measurement entry (weight, height, body fat %, girth measurements, clothing sizes, notes). Previously, fixing a typo meant deleting and re-creating the row, which broke the chart trend line. The timestamp (recordedAt) stays locked β€” only field values can be changed.

πŸƒ

Edit distance and steps on saved cardio workouts

The workout edit endpoint now accepts distance (metres, 0–1,000,000) and steps (0–100,000). Previously these could only be set at creation time; editing a run after saving to correct the distance was not possible.

30 May 2026

Accent colours, notification dismiss, copy meals & friendlier errors

🎨

Choose your accent colour

Account β†’ Appearance now shows six colour swatches β€” Red (default), Violet, Blue, Teal, Amber, Pink. Picking one immediately recolours every button, ring, badge, and progress indicator across the whole app via a CSS variable swap. Your preference is saved locally so it persists between sessions.

πŸ””

Dismiss individual notifications and clear all

The notification bell now shows a βœ• on each notification so you can remove it with a single click, plus a "Clear all" button in the dropdown header to wipe the entire list at once. Both call a new DELETE /api/notifications endpoint and update the UI instantly.

πŸ“‹

Copy yesterday's meals

When today's food log is empty, a "πŸ“‹ Copy yesterday's meals" button now appears below the Add Food Entry button. Clicking it fetches all of yesterday's logged meals and recreates them for today β€” breakfast, lunch, dinner, snacks, and drinks β€” in one tap. Items copy with their full macros and library links intact.

πŸ’¬

Validation error messages are now human-readable

Form validation errors were showing raw camelCase API field names (e.g. "durationMinutes cannot exceed 1440", "avgHeartRate cannot exceed 250", "weightKg out of range (20–400)"). These are now replaced with plain English: "Duration cannot exceed 1,440 minutes", "Average heart rate cannot exceed 250 bpm", "Weight must be between 20 and 400 kg". Applies to workout logging, body measurements, and habit creation forms.

29 May 2026

Daily Inspiration upgrade β€” journal, weight trend & mood UI

πŸ““

Daily Inspiration now reads your journal

The AI recap was missing your journal data entirely. The daily inspiration prompt now includes yesterday's and today's mood, energy, stress scores, tags (e.g. Sick, Tired, Rest day), and free-text journal notes when present. If you logged that you were injured or feeling low, the AI will acknowledge it rather than cheerfully ignoring it.

βš–οΈ

Body weight trend in Daily Inspiration context

The AI recap now includes your most recent body weight and, if a previous measurement exists, whether you're trending up or down. The AI can weave fitness progress β€” "you're down 1.5 kg from your last check-in" β€” into the motivational message.

😊

Mood and energy chips in "Today so far"

When you've logged a journal entry today, the "Today so far" section on the Daily Inspiration card now shows your mood (πŸ˜” to πŸ˜„) and energy level alongside workouts, habits, and nutrition β€” giving a fuller wellbeing snapshot at a glance.

πŸ“Š

Wellbeing summary stats endpoint

A new GET /api/wellbeing/journal/summary endpoint returns 7-day and 30-day averages for mood, energy, and stress, plus the top 5 most-used tags in each window. Powers trend displays and can be used by future dashboard widgets.

May 2026

Input validation & stability fixes

πŸ’Š

Medication tracking

A new Medications tab is now live under Wellbeing. Log GLP-1 injections or any other medication with name, dosage, unit (mg / ml / units / mcg), and date. Rate appetite suppression on a 1–5 scale and tag common side effects (Nausea, Fatigue, Headache, Diarrhoea, Injection site reaction, and more). Free-text notes up to 500 characters. Autocomplete suggests Ozempic, Wegovy, Mounjaro, Saxenda, and other common medications. Full edit and delete from history. Data is stored per-user via a dedicated MedicationLog table.

πŸ›

Journal entries now save correctly

A schema migration had added the WellbeingEntry model but not regenerated the Prisma client, causing every journal POST to return HTTP 500 with "Cannot read properties of undefined (reading 'create')". The client is now up to date and journal entries save correctly.

πŸ““

Journal β€” daily wellbeing log

A new Journal tab is now live under Wellbeing. Log mood, energy and stress each day (rated 1–5), add quick tags (Sick, Tired, Stressed, Rest day, Travel, Period, Injury, Low energy), and write a free-text note up to 500 characters. Entries are dated so you can backfill past days. The history list lets you edit or delete any entry. All data is stored per-user and only visible to you. The API supports full CRUD β€” GET, POST, PATCH and DELETE β€” with the same input validation applied across FitMesh.

🚫

Blank exercise names now rejected

Manually logged workouts with an empty or whitespace-only exercise name (e.g. setting exercise to "" or " ") previously saved silently β€” the name was stored as a blank string. The validation in validateExerciseSets() now trims the name and rejects it if the result is empty, returning a clear 400 error: "Exercise name cannot be empty". Applies to both v1 (flat array) and v2 (blocks) workout formats.

🎯

Polar activity goal shown in Daily Inspiration

Daily Inspiration now includes your Polar activity goal completion percentage alongside workouts and habits. Non-workout movement β€” DIY, errands, walking between meetings β€” is now reflected in the AI recap, not just gym sessions. The activity percentage also appears as a chip in the "Today so far" card on the Habits tab.

⌨️

Food quantity and macro fields no longer block editing on mobile

Number inputs in the Edit Food Item modal were using type="number" with a minimum of 0, which caused Chrome and Safari to block deletion of the last digit β€” making it impossible to clear a field and type a new value. The fields now use text mode with a decimal keyboard, matching standard form UX.

πŸ”’

Food library: custom item macros now validated

Creating a custom food item in the food library previously accepted negative macro values, unrealistically large numbers (e.g. 999,999 calories), and non-numeric text that silently converted to 0. Macros are now validated on save: calories capped at 9,999 kcal, protein/carbs/fat each capped at 999g. Non-numeric values and negatives return a clear error.

πŸ‹οΈ

Exercise name and notes length limits added

Manually logged workout exercise names are now capped at 200 characters and workout notes at 1,000 characters. Previously both fields had no upper bound, which could cause DB bloat and rendering issues. Submitting values over the limit now returns a clear 400 error.

πŸ“…

Body measurement dates now validated

The recordedAt field for body measurements now rejects dates before 1970 and dates in the future. Previously any date was accepted, which allowed nonsensical entries (e.g. year 1900 or 2099) to pollute weight charts and progress graphs.

🚫

Food quantity of 0 is now rejected

Logging a food item with a quantity of 0g now returns a clear error β€” "quantity must be greater than 0" β€” instead of silently saving a zero-quantity entry. Zero-quantity entries had no nutritional value and only cluttered meal logs.

πŸ›‘οΈ

Body measurements rate-limited

The body measurements endpoint now enforces a rate limit of 20 entries per minute per user. Previously there was no limit, which allowed accidental or malicious bulk submissions to bloat the database and slow the body weight chart.

πŸ“·

Photo food log no longer shows a network error on bad images

When the AI could not process a photo (corrupt file, unsupported encoding, or a transient API error), the endpoint was returning an empty HTTP 500 with no body β€” which the app displayed as a generic "network error". The error is now caught and returns a clear message: "Photo could not be read. Please use a clear JPEG or PNG." Matches the error-handling pattern already used by the workout photo scan.

🏷️

Workout title capped at 500 characters

Manually logged workout titles are now limited to 500 characters on both creation (POST) and edit (PATCH). Previously, any length was accepted, which was inconsistent with the 200-character cap on habit names. Submitting a title over 500 characters now returns a clear 400 error.

βš–οΈ

Body measurements reject non-numeric text

Entering a text value (e.g. "eighty") in a body measurement field now returns a clear error β€” "weightKg must be a valid number" β€” instead of silently saving a blank entry. Previously the text was coerced to null and the entry was rejected only with the misleading "at least one measurement required" message.

🀝

PT invite code confirmation step

Generating a PT invite code on the Account page now requires a confirmation step. An amber warning box explains that the code is for your client to enter β€” not for entering your trainer's code. This prevents users from accidentally claiming the PT role when they meant to join as a client.

πŸ“‰

Negative calorie values no longer shown in Training tab

A pre-existing workout entry with a negative calorie value (βˆ’999 kcal) was being displayed as "βˆ’999 kcal" in the workout timeline and activity feed due to a truthiness check that passed for negative numbers. The display now only shows calorie values that are greater than zero.

πŸ›‘οΈ

API enum validation

Three endpoints (manual workout logging, food log, and habit creation) now return a clear 400 error instead of crashing when an unrecognised activity type, meal type, or habit frequency is submitted. The valid values are listed in the error message.

πŸ“‰

Nutrition target validation

Calorie, protein, carb, fat, and water targets in Nutrition Settings now reject negative values and unrealistically high numbers (above 100,000) rather than silently storing them.

πŸ”

Dashboard tab navigation fix

Opening the dashboard with a ?tab= URL (e.g. from a notification link) no longer causes a brief page freeze. The tab was being read during server-side rendering and causing a React hydration mismatch. It is now read after the page loads.

⏱️

Workout duration cannot be negative

Manually logged workouts now reject a negative duration (e.g. βˆ’30 minutes). The field previously accepted any number including negative values. It now returns a clear error if duration is below zero.

πŸ“

Workout field upper bounds

Manual workout entries now enforce sensible upper limits: duration cannot exceed 1,440 minutes (24 hours), calories cannot exceed 10,000 kcal, and heart rate fields cannot exceed 250 bpm. Values above these limits return a clear error.

🎯

Habit target values cannot be negative

Habit numeric targets (floor value, target value, stretch value, and times target) now reject negative numbers with a clear error. Previously, a negative target could be saved silently.

πŸ₯—

Food quantity cannot be negative

Food log entries now reject a negative quantity (e.g. βˆ’50g) with a clear 400 error. The how-to guide stated that negative values were rejected, but the server-side check was missing β€” this has been corrected.

πŸ‹οΈ

Exercise set reps and weight bounds

Manually logged strength workouts now validate individual set data. Reps cannot exceed 9,999 and weight cannot exceed 2,000 kg per set. Non-numeric or negative values in either field now return a clear error rather than being stored silently.

🍽️

Food item name length limit

Food item names are now capped at 500 characters. Previously, names of any length were accepted, which could cause layout issues in the food library and meal cards. Names over 500 characters now return a clear error.

βš–οΈ

Food quantity upper limit

Food log entries now reject quantities above 10,000g per item with a clear error. This prevents unrealistically large entries (e.g. 9,999g of oats) from inflating daily macro totals and cluttering the food library.

✏️

Editing a food item now validates quantity and macros

The edit-item flow (tapping ✏️ on a logged food row) now applies the same validation as logging new food. Non-numeric quantity returns a clear error instead of a server crash. Negative or over-limit quantities (above 10,000g), names over 500 characters, and negative macro values are all rejected with a descriptive message.

✏️

Editing a habit now validates name and target values

Editing a habit via the pencil icon now validates the same fields as habit creation. Name cannot be empty or exceed 200 characters. Floor, target, and stretch values must be valid numbers and cannot be negative. Frequency must be one of the accepted options. Previously, invalid edits could cause a server error or silently store corrupt data.

πŸ”’

Habit target values now have upper limits

Times-per-day/week targets (e.g. "drink water 8Γ— daily") are now capped at 100 completions. Floor, target, and stretch values are capped at 100,000 β€” covering step-count goals up to 100k. Values above these limits return a clear error.

πŸ₯—

Food item macro values now have upper limits

Per-item calorie values are now capped at 9,999 kcal and protein, carbs, and fat are each capped at 999g. These limits prevent obviously erroneous entries (e.g. 999,999 calories for a single item) from skewing daily totals. Non-numeric macro values also now return a clear error instead of being silently ignored.

πŸ“

Workout location label capped at 200 characters

The location label on a manually logged workout is now limited to 200 characters. Previously the field had no upper bound, which could cause layout overflow in workout cards and export files. Submitting a value over 200 characters now returns a clear 400 error.

πŸ“

Body measurement notes and clothing sizes now have length limits

The notes field on a body measurement is now capped at 500 characters and clothing size fields (top size, bottom size) are capped at 50 characters each. Previously all three had no upper bound. Values over the limit now return a clear 400 error.

πŸ“…

Food log dates are now validated

Food log entries now reject dates before 1970 and dates more than 1 day in the future. This brings the food log in line with the existing date validation on workouts and body measurements, preventing nonsensical back-dated or future-dated entries from appearing in the nutrition calendar.

πŸ“

Workout distance and steps now validated

Manually logged workouts now reject negative distance values and cap distance at 1,000,000 metres and steps at 100,000. Previously both fields had no bounds, which allowed nonsensical entries like a negative 5-metre run.

✏️

Editing food items: zero quantity now consistently rejected

Editing a logged food item to have a quantity of 0g now returns the same "quantity must be greater than 0" error as logging new food. Previously the edit path accepted zero, creating a silent inconsistency.

✏️

Editing food items: macro upper limits now enforced

Editing a logged food item now enforces the same per-item macro caps as logging new food: calories cannot exceed 9,999 kcal and protein, carbs, and fat each cannot exceed 999g. The edit path previously had no upper bounds on these fields.

😴

Sleep target on habits now validated

The sleep target field on a habit is now capped at 24 hours. Previously, any value was accepted including nonsensical values like 999 hours. Values above 24 now return a clear error on both habit creation and editing.

✏️

Editing habits now enforces the same upper limits as creation

Habit edits now enforce the same maximum values as creating a new habit: times-per-day/week targets cannot exceed 100 and numeric goal values cannot exceed 100,000. Previously these caps only applied when creating a habit, not when editing one.

πŸ’§

Water intake logging now validated

The water log endpoint now validates that ml is a finite number (non-numeric text previously caused a server error), caps intake at 10,000ml per day, and rejects dates before 1970 or more than 1 day in the future.

πŸ‹οΈ

Editing workouts now validates all fields

The workout edit path now enforces the same validation as creating a workout: location label cannot exceed 200 characters, date year must be between 1970 and the current year +2, and set data validates reps (≀ 9,999) and weight (≀ 2,000 kg).

🍽️

Calorie balance shown below the ring

The nutrition summary now shows a colour-coded balance pill below the calorie ring when you have a calorie target set β€” green when under, red when over. At a glance you can see "+200 kcal" or "βˆ’350 kcal" without doing the maths yourself.

πŸ‹οΈ

Exercise validation now covers block-format workouts

Reps (≀ 9,999), weight (≀ 2,000 kg), and exercise name (≀ 200 characters) limits were already documented but were silently skipped when exercises were sent in the block format used by the manual-entry modal (supersets, circuits). The validator now handles both the legacy flat format and the current block format. Boundary values are still accepted; over-limit values now return a clear 400 error.

✏️

Edit metadata on synced workouts

The Edit button is now shown for all workouts β€” not just manually logged ones. For workouts imported from Strava, Hevy, Polar, or other sources you can rename the workout, change the activity type, correct the date, add a location, or attach notes. Exercise sets remain read-only for synced workouts (those can only be edited at the source). Delete is still restricted to manual entries only.

May 2026

Fitbit integration & sync improvements

πŸ”΅

Fitbit connected

Fitbit is now a live integration. Connect from the Integrations tab and sync your workouts, daily steps, sleep stages, and weight log entries. Fitbit uses OAuth β€” you will be redirected to approve access.

⚑

Per-source sync

The sync button next to each integration now syncs only that source rather than triggering a full re-sync of everything. Faster, uses less API quota, and feels more responsive.

πŸ”„

Smarter deduplication

The dedup engine now re-processes recent unconfirmed workouts on each sync. If a Strava run and a Hevy session for the same workout arrived at different times, they will now correctly merge into one entry rather than staying as separate events.

May 2026

How-to page fixes

πŸ–±οΈ

Consistent click language

The how-to guide previously used "tap" in a few steps (barcode scanning, favourites) while the rest of the page used "click". All instructions now consistently use "click" throughout.

πŸ–ΌοΈ

Logo filename fix

The FitMesh logo files had a typo in their filename (FtiMesh instead of FitMesh) across all pages. The files and all references have been corrected sitewide.

April 2026

Food library, favourites & recipe builder

⭐

Personal food library

Every food you log via AI (Describe, Photo, or PDF import) is automatically saved to your personal library with the correct macros per 100g. Go to Library β†’ Foods to see everything, organised into Favourites, Recent, and All.

β˜…

Favourite foods & meals

Tap the β˜… star on any logged food row to save it as a favourite. Or use the "β˜… Save as meal" button at the bottom of any meal edit sheet to save an entire meal in one tap. Favourites appear at the top of the Favourites tab whenever you add food.

🍽️

Quick-log from favourites

The ⭐ Favourites tab in the add food modal now shows both your starred individual foods and saved meals. Starred foods show the default serving β€” tap to adjust quantity, then log in one tap. Saved meals log all items at once.

πŸ“–

Recipe builder

Go to Library β†’ Recipes β†’ + Create recipe. Describe the dish in plain text and AI parses it into a full ingredient list with macros. Adjust quantities per ingredient β€” macros rescale automatically. Set the number of servings and see per-serving totals before saving.

✏️

Edit logged food entries

Tap any logged meal card to open it, then tap ✏️ on an individual item to edit it inline. Change the name, quantity or any macro. Changing the quantity automatically rescales protein, carbs, fat and calories using the original per-gram ratio.

April 2026

Photo food logging & describe improvements

πŸ“·

Photo food logging

Tap πŸ“· Photo in the add food modal to take or upload a photo of your meal. AI identifies every item on the plate and estimates portions and macros. Tick what to keep and log in one tap. Uses 1 AI credit per photo (free: 3/day, PRO: 15/day).

⌨️

Keyboard mic & Wispr support

The Describe tab now works seamlessly with your phone keyboard's built-in microphone and dictation tools like Wispr. Just tap the mic icon on your keyboard and speak β€” no in-app microphone permission needed.

⚠️

Photo accuracy warning

When using photo logging, a note reminds you that visual estimates can vary and suggests switching to the Describe tab for more precise logging when accuracy matters.

March–April 2026

Polar integration & recovery tracking

πŸ”΅

Polar integration

Connect your Polar device or Flow account to sync workouts automatically. Go to the Integrations tab and connect Polar to get started.

😴

Recovery tab

A new Recovery section in the Training tab shows sleep, HRV, and readiness data from supported devices. Helps you track how well you are recovering between sessions.

March 2026

Account controls & data safety

πŸ”’

14-day deletion grace period

When you request account deletion, your account is scheduled for deletion in 14 days rather than deleted immediately. You can cancel from Account β†’ Delete account at any point during that window. A notification is sent with a link to download your data first.

πŸ“₯

Data export before deletion

The deletion notification includes a direct link to export your data so you can keep a copy before anything is removed.

πŸ’³

Billing portal fix

The Manage Billing button in Account now correctly detects whether you have a Stripe subscription. Gifted PRO accounts (no card on file) no longer see a broken button.

March 2026

Habits & compliance

🎯

Tiered compliance targets

Habits now support three tiers: a minimum floor (non-negotiable), a target (the actual goal) and a stretch goal. The weekly view shows which tier you hit each week rather than a simple pass/fail streak.

πŸ”’

Multiple completions per day

Habits like "take medication 3Γ— daily" or "drink water 8Γ— daily" now track count per day rather than a binary yes/no. Set a daily target and log each completion separately.

πŸ“Š

Compliance percentage view

Each habit now shows a rolling 7-day and 30-day compliance percentage alongside the streak. Useful for seeing whether you are consistently hitting a target, not just whether you're on a current run.

February 2026

Nutrition foundations

πŸ₯—

Describe food with AI

Type what you ate in plain English and AI breaks it into items with estimated macros. Works for complex meals, cooking from memory, or anything that isn't in a database.

πŸ“₯

Import from MyFitnessPal

Upload a PDF export from MyFitnessPal (or similar) and FitMesh reads every entry and previews it before import. Brings your history across without needing CSV access.

πŸ’§

Water tracking

Track daily water intake with a tap counter (250ml per tap). Syncs with water-based habits β€” hitting your daily target auto-completes any water habit you have set up.

πŸ“ˆ

Nutrition trends & charts

The Log tab shows daily calorie bars for the last 30 days, 7-day rolling macro averages, and a weekly summary card.