Store a per-user weekly workout target (1-14) in a new FitnessGoal model.
Compute consecutive-week streak from WorkoutSession history via a new
/api/fitness/goal endpoint. Display streak as a 4th lifetime card on the
stats page with an inline goal editor modal.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Use SvelteKit param matchers for bilingual URL routing (e.g. /fitness/stats
and /fitness/statistik). Add centralized i18n module with translation
dictionary, language detection from URL, and path conversion utilities.
Translate all UI text across pages, components, and navigation.
- Replace floating action button with a subdued + icon in the templates
header row next to the Schedule button
- Use --primary-contrast (white/nord0) instead of hardcoded white for
text on primary-colored backgrounds so dark mode has proper contrast
- Respect data-theme="light"/"dark" attrs in addition to prefers-color-scheme
Users can define a custom order of templates (e.g., Push → Pull → Legs).
Based on the last completed session, the next workout in rotation is
recommended via a prominent banner and the floating action button.
- New WorkoutSchedule MongoDB model (per-user template order)
- GET/PUT /api/fitness/schedule API endpoints
- Schedule editor modal with reorder and add/remove
- Action button starts next scheduled workout when schedule exists
When finishing a template-based workout, compares completed sets against
the source template. If weights, reps, or set counts differ, shows a
visual diff with old→new values and a button to update the template,
letting templates grow with the user's strength progression.
- Validate exerciseId instead of name (templates use exerciseId, not name)
- Remove mandatory reps minimum from template sets
- Allow exercises with empty sets in schema and API validation
The authorization hook already calls locals.auth() which can set cookies.
Layout server loads calling auth() again caused a race where cookies.set()
fired after the response started streaming. Now the hook stashes the session
on locals.session and all layouts reuse it.
Decouple name input from live sync by using a local variable that only
commits to workout state on blur/Enter. Remote name updates are applied
only when the input is not focused, preventing the sync layer from
overwriting in-progress edits.
- SessionCard SVG: cosine-corrected coordinates with proper aspect ratio (xMidYMid meet)
- SessionCard: use --color-primary for track/distance/pace, add Gauge icon for pace
- History detail: theme-reactive pace chart colors via MutationObserver + matchMedia
- History detail: add Gauge icon, accent color for distance/pace stats, remove "avg" label
- Move GPS remove button from info view to edit screen
- Add Leaflet map preview to edit screen
- Remove data points count from GPS indicators
Disable initial animation on all Chart.js charts (FitnessChart and
cospend BarChart) while keeping transition animations for interactions.
Add linear regression trendline with ±1σ uncertainty bands to exercise
charts (Est. 1RM, Max Weight, Total Volume).
Add GPX file upload for cardio exercises in workout history. Parses
GPX track points and stores them in the session. Shows route map
(Leaflet), pace-over-distance chart (Chart.js), and per-km splits
table with color-coded fast/slow pacing. Auto-fills distance and
duration on single-set exercises. Disables Chart.js animations.
Show summary screen after finishing a workout instead of immediately
redirecting. Displays duration, tonnage, distance, per-exercise stats
(pace, e1RM, top weight), and detected PRs compared to previous session.
Redesign rest timer as inline bar with linear decay placed after completed set.
Add set removal (X button), @ separator column for RPE, and N/A for missing
previous values. Enable editing past workouts (date, duration, exercises, sets)
from the history detail page.
- Add metrics system (weight/reps/rpe/distance/duration) per exercise type
so cardio exercises show distance+duration instead of weight+reps
- Add 8 new cardio exercises: swimming, hiking, rowing outdoor, cycling
outdoor, elliptical, stair climber, jump rope, walking
- Add bilateral flag to dumbbell exercises for accurate tonnage calculation
- Make SetTable, SessionCard, history detail, template editor, and exercise
stats API all render/compute dynamically based on exercise metrics
- Rename Profile to Stats with lifetime cards: workouts, tonnage, cardio km
- Move route /fitness/profile -> /fitness/stats, API /stats/profile -> /stats/overview
Replace substring matching with a shared fuzzy scorer that matches
characters in order (non-contiguous) with bonuses for consecutive
and word-boundary hits. Results are ranked by match quality.
Enables real-time workout synchronization across devices using
Server-Sent Events and an ephemeral MongoDB document (24h TTL).
Rest timers now use absolute timestamps instead of interval-based
countdown for accurate cross-device sync. Adds +/-30s rest timer
adjust buttons.
Replace hardcoded Nord color references with semantic CSS variables
across all fitness components and pages. Use --color-primary instead
of --nord8 for interactive elements (auto-switches between --nord10
in light mode and --nord8 in dark mode). Change RPE color from
--nord13 (yellow) to --nord12 (orange) for better light mode contrast.
Fix mobile responsiveness on measure page form inputs.
- Add exerciseId to WorkoutSession model (interface + schema)
- Fix button-in-button hydration warning in TemplateCard (use div)
- Expand FitnessChart dataset type to include all Chart.js properties
- Fix getTime type error in session update with proper cast
- Fix weight nullable type in profile stats with non-null assertion
- Fix $or query typing in templates list endpoint
- Re-add gym link on homepage pointing to /fitness
Add all 5 PPL+Upper/Lower templates matching the target split,
with Day 3 (Legs) adjusted to include Bulgarian split squats and
standing calf raises, and Day 5 (Lower) reworked with front squats,
hip thrusts, and goblet squats — all equipment-free of machines.
Also adds incline row, decline crunch, flat leg raise, and nordic
hamstring curl to the exercise list, and updates the WorkoutTemplate
model to use exerciseId instead of name for exercise references.
- 5-tab layout (Profile, History, Workout, Exercises, Measure) with shared header nav
- Workout system: template CRUD, active workout on /fitness/workout/active with localStorage persistence, pause/resume timer, rest timer, RPE input
- Shared workout singleton (getWorkout) so active workout state is accessible across all fitness routes
- Floating workout FAB indicator on all /fitness routes when workout is active
- AddActionButton component for button-based FABs (measure + template creation)
- Profile page with workouts-per-week bar chart and weight line chart with SMA trend line + ±1σ confidence band
- Exercise detail with history, charts, and records tabs using static exercise data
- Session history with grouped-by-month list, session detail with stats/PRs
- Body measurements with latest values, body part display, add form
- Card styling matching rosary/prayer route patterns (accent-dark, nord5 light, box-shadow, hover lift)
- FitnessChart: fix SSR hang by moving Chart.register to client-side, remove redundant $effect
- Exercise API: use static in-repo data instead of empty MongoDB collection
- Workout finish: include exercise name for WorkoutSession model validation
Search component needs access to all recipes to filter across
categories/tags/etc. Previously these pages only passed their
pre-filtered subset, so selecting additional filters yielded
no results. Now each page fetches allRecipes in parallel and
passes it to Search, falling back to the route-specific subset
when no filters are active.
The glob in sync.ts targeted a nonexistent /src/routes/glaube/ directory
instead of the actual [faithLang=faithLang] parameterized route. This meant
zero prayer pages were ever precached for offline use.
- Fix glob to match [faithLang=faithLang] and expand param segments to
both language variants (glaube/faith, gebete/prayers, rosenkranz/rosary)
- Extract validPrayerSlugs to shared module for build-time route enumeration
- Add faith to service worker cacheable route regex
Show first mystery image at the Pater Noster instead of the Gloria Patri
by removing the early lbead2 trigger. Fix IntersectionObserver to prefer
the topmost intersecting entry so short _pater sections aren't skipped.
Use full viewport height (100dvh) for the SVG container to prevent
clipping at edges.
Override SearXNG's native CSS variables with Nord palette (cream white
light mode, true black dark mode). Replace SearXNG logo with Bocken
logo. Custom base.html template injects the CSS. Deploy script supports
reset to restore original state.
- Move theme toggle to right side of header (before notifications)
- Remove border from toggle, style consistently with other nav icons
- Fix dark mode hover background on toggle button
- Use exact Lucide SunMoon icon for system theme
- Dark logo filter in light mode
- Increase header height to 3.5rem
- Light mode with homepage warm beige palette (no pure white)
Match the homepage dark mode surface colors (#000/#111/#1a1a1a/#222)
for boxes, code, inputs, cards, and menus instead of Nord greys.
Keeps Nord only for accent colors and text.
- Floating glass pill navbar matching homepage/jellyfin header style
- Full black page background
- Custom head_navbar template: logo links to bocken.org, home button
for logged-in users, icons on all nav items, remove Help/Explore
- Icon-only nav on mobile, hide dropdown triangles, round avatar
- Deploy script to rsync theme + template to server