Android step detector silently returns no events on API 29+
when ACTIVITY_RECOGNITION is ungranted, so cadence was always
absent from recorded tracks. Declare the permission, request
it at GPS start, guard sensor registration and retry it from
MainActivity.onRequestPermissionsResult when the user grants
mid-session, and toast a hint if they deny.
Export each cardio exercise's stored GPS track from the history
detail page. Cadence is emitted per-point via Garmin's
TrackPointExtension v1 so Strava/Garmin Connect preserve it.
Filename: YYYY-MM-DD-<workout> <mins>min <Activity>.gpx.
The store-picker read localStorage at component init, which crashed
SSR on full-page loads of /cospend/list with 'localStorage.getItem is
not a function'. Deferred the read to onMount and wrapped writes in
try/catch.
Long-press modal on /cospend/list now lets you change the item's name
and quantity (e.g. "500g", "3x") alongside category and icon. The
quantity is re-prepended to the name so the existing parser keeps
picking it up.
Replace /1962 and /1969 with /vetus and /novus — matches how Catholics
actually refer to the missals (Vetus Ordo / Novus Ordo), reads the same
across de/en/la, and sidesteps the value-laden old-vs-new framing.
Rite pill labels flip to "Vetus" / "Novus"; the year stays visible in
the subtitle. Legacy year-slug URLs 307-redirect to keep bookmarks alive.
Romcal's liturgical scope emits LY N with a stale post-Pentecost tail
~3 weeks into December; dates from Advent I onward belong to LY N+1.
Month/ring views already shift — port the same rollover to the detail
page so Dec 1–20 stop showing "After Pentecost" data and Dec 21–31 stop
404'ing.
Server runs from build output dir where CWD-relative `static/*.tsv`
misses — adapter-node ships static assets at build/client/. New
resolveStaticAsset() helper uses import.meta.url to find the bundled
location, falls back to <cwd>/static/ in dev.
Fixes ENOENT on drb.tsv/allioli.tsv after deploy.
The projection gate required the date to be strictly after today,
so the current day never showed a projected burn even before any
workout had been logged. Loosened to >= today and removed a
now-duplicate isTodayOrFuture/today declaration introduced by the
earlier round-off flicker fix.
PeriodTracker gains an optional mode prop ('entry' | 'projection' |
'full') that gates which sections render. The measure page keeps the
full tracker for the user's own cycle (logging plus calendar). The
stats page now mirrors it in projection mode and is the sole home
for shared cycles, which used to clutter the measure page.
Unifies PNG and SVG body-part images behind a single CSS-mask
render path, so both now colorize with a --accent CSS variable.
Accent splits by measurement type: --blue for proportion parts
(chest, shoulders, waist, hips) and --nord8 for muscle parts
(neck, biceps, forearms, thighs, calves). Stats cards gain a
matching 8%-tint fill and accent-colored hover border. History
page header image enlarged. Thigh SVG stroke-width bumped to 11
for better mask legibility.
Placeholders and +/- fallback now use the most recent recorded
value per part; previously placeholders were hardcoded "—" and
+/- bumped from 0. Buttons step by 0.5 cm (manual input still
accepts 0.1 resolution).
Body-parts grid now lives on /fitness/stats, and per-part history
pages moved from /fitness/measure/history/<part> to
/fitness/stats/history/<part>. Measure page keeps weight/BF entry
and the body-parts measure launcher.
Replaced the auto-selecting $effect that was clobbering manual slot
picks with explicit init in onMount and advancement inside pray().
Selecting lunch/evening after praying morning now works.
- LanguageSelector: add kalender/calendar/calendarium mappings so swapping
language from /glaube/kalender/... produces /faith/calendar/... instead
of the broken /faith/kalender/... URL.
- HeroCard: move margin-bottom off the anchor so the plain (1969) variant
keeps the same bottom spacing as the linked (1962) variant.
- Calendar overview: omit detail href on 1969 so the hover chevron /
hover elevation don't appear when no detail page exists.
- Detail route: 404 any /detail/... under the 1969 rite — only 1962 has
day-detail pages.
- Auto-fill missing vernacular propers from Allioli (DE) or DRB (EN)
when the 1962 missal bundle lacks a translation, mapped per Latin slot
via romcal's scriptureRef blocks (compound refs split 1-to-1 when
segment count matches slot count).
- Strip Psalm superscriptions and trailing periods so lookups parse and
Bible text aligns with the Latin antiphon.
- Localize the section reference header (Marc → Mk, Vulgate→Hebrew
psalm shift for DE) instead of showing raw Latin.
- Add Latin / Parallel / Vernacular view toggle with localStorage
persistence; hide Allioli/DRB badge in Latin-only view.
- Latin column now takes primary text color; vernacular secondary,
matching the Prayer.svelte convention.
Removes decorative route-label h1s across fitness, recipe and cospend
pages — replaced with sr-only h1s for assistive tech and a shared
.sr-only utility in app.css. On the measure page, the tucked-away
profile chip becomes a dismissible setup banner that only appears
when sex/height/birth year are missing, with a permanent "Edit profile"
link at the foot of the page.
Macro split now always renders (faded rings + hint when no food logged),
and the calorie balance hint distinguishes missing demographics/weight
from missing food-log data with a warning style.
ActionButton now renders as <a> (href) or <button> (onclick), so
SaveFab wraps it to inherit the shake/hover/focus behavior already
used by AddButton/EditButton. Body-parts review replaces its inline
save button with SaveFab for consistency.
Latest measurements render as a 3x3 card grid (vertical mobile,
horizontal on ≥768px) linking to `/fitness/{measure}/{history}/{part}`
with summary stats + chart. Slugs localize (hals, oberschenkel, …)
when on the German route.
Pre-compute romcal year maps on server boot for current + next civil year
across en/de/la in each rite's default diocese, non-blocking so startup is
unaffected.
Also fixes several 1962-rite rendering bugs: commemorations previously
leaked 1969-shape ids (e.g. andrew_apostle) next to proper 1962 sancti;
station church names came through unresolved because RomcalConfig's
internal i18next has no bundle loaded; season names arrived as raw keys
(advent.season) for the same reason. All three now resolve locally via
the shipped 1962 bundle with Latin as fallback. ClassIV ferias get a
small dot on the grid.
The active-workout activity picker updated local state + workout.name
but never synced workout.activityType, so every hiking/walking/cycling
workout was saved with an inner exercise of 'running'. That silently
applied the wrong kcal model — running Minetti for hiking/walking
(~43% overestimate) and running instead of the cycling physics model
(large overestimate for cycling).
Adds an activityType setter on the workout store and invokes it from
selectActivity() so the saved session's exercise matches the picked
activity.
Average calorie balance was comparing logged-day intake against all-day
expenditure, producing a spurious deficit on weeks with untracked days.
Now restrict both sides to days with non-zero logged intake so the
subtraction compares apples to apples.
Past and today return projectedExercise=null, so the estimate no longer
appears on days where the user could have just skipped a workout. Also
skips the WorkoutSchedule lookup when not needed.
- Add `timing` handle in hooks.server.ts emitting Server-Timing headers
and expose `locals.timing.mark/measure` for per-load instrumentation.
- Drop dead `getEnrichedExerciseById` fallback in fitness detail page —
server load already 404s via errorWithVerse, so the client no longer
pulls exercisedb-raw.json (~760KB) into the detail bundle.
- Add `{ createdBy: 1, nextExecutionDate: -1 }` index on RecurringPayment
for user-scoped list queries.
- Narrow populate projections in cospend/debts (title/date/category on
userSplits, _id only on allRelatedSplits) to cut payload + hydration.
- Parallelize today's sessions + WorkoutSchedule lookup in the nutrition
page load via Promise.all; add `.lean()` + `.select('templateId')` to
the lastScheduled query.
Cap shell height to viewport minus header so the bottombar stays visible,
allow the stage to scroll internally, and swap the thigh diagram to a
mask-tinted SVG that tracks the text-primary color across themes.
SvelteKit's handleError hook is skipped for expected `error()` throws,
so verses set there never reached `$page.error` for server-thrown 404s
and auth denials. Introduce `errorWithVerse()` in `$lib/server/errorQuote`
that fetches a random verse first, then throws `error(status, body)`
with `{ message, bibleQuote, lang }`, making the quote available in
every `SectionError`. Convert all page load throws (catchalls, layout
validators, calendar, prayers, recipes, fitness, cospend, admin) and
hooks.server auth gates to the helper. Add `src/error.html` as a
branded last-resort fallback.
Replace the emoji/gradient card with an editorial layout: small lucide
glyph, oversized error code, hairline-divided serif bible quote.
Extract shared ErrorView + SectionError components and a bilingual
string helper. Add +error.svelte at each section root (faith, recipes,
fitness, tasks, cospend) so errors render inside the correct layout and
inherit the section-specific header/nav. Catch-all [...rest]/+page.ts
stubs route unmatched URLs through the section layout so the right
error page catches them.
The raw series has `pending: number | null`, but the rendered series stores
pending as `{ x, y, value }` for SVG placement. Legend labels were calling
`.toFixed(1)` directly on the object, crashing as soon as a pending value
existed (i.e. whenever the user typed a measurement).
romcal's package.json is not listed in its exports map, so
require.resolve('romcal/package.json') throws ERR_PACKAGE_PATH_NOT_EXPORTED
under Node's strict exports enforcement. Resolve the main entry instead
and walk up until we find the package.json belonging to romcal itself.
romcal's 1962 bundle files live outside the package's exports map and were
being loaded via a cwd-relative path. Under systemd the server runs with
cwd /usr/share/webapps/homepage/dist/, so node_modules/romcal/... resolved
against dist/ and hit ERR_MODULE_NOT_FOUND. Switch to createRequire +
require.resolve('romcal/package.json') so the bundle path is anchored to
the actual package root regardless of cwd.
Also track scripts/hooks/pre-push which runs scripts/deploy.sh after a
master push to origin. Git has no native post-push hook; pre-push is the
closest client-side equivalent — if deploy fails the push is aborted.
Install with: ln -sf ../../scripts/hooks/pre-push .git/hooks/pre-push
New /fitness/measure/body-parts route with step-by-step tape-measure
flow, per-step tips, L/R paired inputs, inline history chart, and
review-before-save summary. Measure page replaces the old body-parts
accordion with a launch button. Fitness layout goes full-bleed and
hides the site footer for this route via a :has() attribute selector,
and the desktop 3-column grid now extends rail and side panel up past
the floating nav while the middle column compensates with padding.
Inline italic captions under each single-sided input (neck, shoulders,
chest, waist, hips) and row-spanning captions with a primary accent bar
under each paired row (biceps, forearms, thighs, calves) — one tip per
pair, not per side. EN + DE copy.
Schema uses flat keys (leftBicep, rightBicep, leftForearm, ...), but
create/edit forms built nested objects (biceps: {left, right}), which
Mongoose silently stripped — so paired parts never persisted. The
latest-measurements endpoint also wraps the body-parts doc in
{value, date}; the display path skipped the .value hop, hiding every
body-part field. Switch client to flat keys end-to-end.
- Reserve an angular gap in the ring and render a clickable green triangle
that jumps to Advent I of the following liturgical year; on hover the
center numeral previews the upcoming LY in a muted color.
- Show the liturgical year (not civil) in the ring center so Advent 2025
already reads 2026, and promote the selected arc to the top of the
SVG paint order so its highlighted border is never clipped by neighbors.
- Lift the selected-season glow by mixing the season tint with the
foreground color so purple stays visible on dark backgrounds and white
on light backgrounds.
- On feast-dot hover, pop a colored SVG pill with the short date and feast
name, tracked by ISO so it auto-clears when the dot is unmounted by
navigation.
- Server now derives the liturgical year from the selected date, shifting
yearMap forward when the URL civil date lies past Advent I of that year
so clicks on Dec 25 no longer select the prior post-Pentecost cycle.
- Add data-sveltekit-keepfocus on ring anchors to avoid the focus-scroll
jump after client-side navigation.
Switch the romcal dependency to AlexBocken/romcal (monorepo fork with
collapsed bucket prefixes) and strip the runtime prefix-fallback chain
from liturgicalCalendar.ts — name/propers lookups now use a single
flat id. The 1962 data model shrinks to just what the rendering uses
(commem {id,name}, detail carrying propers as {key, la[], local[]})
and the detail + overview pages drop the rubrics/octave/properSource
fields that never got wired in.
- Rotate the ring smoothly to put the selected day under a static vertical
needle pin; pivot uses a shortest-arc Tween, respects prefers-reduced-motion,
and falls back to today when no selection. Pin + bar cross-fade color in
lockstep (650ms cubicOut) to the selected day's liturgical color (gold when
selected == today).
- Split the overview into an inline hero (selected day) and a dedicated
/detail/{yyyy}/{mm}/{dd} route that opens on hero click; drop the old
inline detail block.
- Restyle the month grid to a minimalist card-grid: taupe feria fills,
rounded cells, gold today-ring + dot, Roman-numeral rank badges, and
equal-width columns via minmax(0, 1fr) so long feast names no longer
stretch a column.
- Default the calendar view to the ring, reorder the view switcher
(ring first), and match hero-card color transition to the ring timing.
- Extract shared calendar types to $lib/calendarTypes.ts and server helpers
to $lib/server/liturgicalCalendar.ts so the overview + detail routes share
one source of truth. Bump romcal dep to the dev branch, alias the Swiss
1969 bundle so its exports resolve.
- Bump version to 1.35.0.
Show propers text for each 1962 celebration with scripture reference pills
grouping each block. When a translated proper is missing, fall back to the
local-language Bible (Douay-Rheims for en, Allioli for de), showing a note
above the translated column. Handles multi-segment refs (e.g. "Ps 118:85;
118:46") with inherited book/chapter, and shifts Vulgate→Hebrew psalm
numbering for Allioli.
Also restructures date navigation as folder-based optional params
(/yyyy/mm/dd) with the rite forced as a required path segment so day/month
navigation stays within the active rite.
Add a small banner on the 1962 rite view noting that day-to-day data is
still being verified and that local proper calendars (diocese, order,
national feasts) are not yet layered on top of the general Roman
calendar. Bump the romcal dep to AlexBocken/romcal1962#e4731a8 for the
Holy Week / Easter Octave name fixes and the Pentecost-season color fix
(ordinary-time Sundays are now Green, not White/Red).
Replace four tastytea-style SVGs (blanket, hammer, teapot, heart_tastytea)
whose 800px viewBox clashed with the 33.866666 viewBox of the rest, and add
the full Tirifto gutkato_ set. Catalog grows from 54 to 113 positive stickers
(new foods/drinks, rose and cat colors, professions, cute expressions, signs).
Adds a calendar tile to the /faith (glaube/fides) LinksGrid linking to the
liturgical calendar. Homepage description and WIP body reference the "older
rite" / "alten Ritus" rather than "Tridentine" to avoid loaded connotations;
subtitle labels keep the neutral Ordinary/Extraordinary Form terminology.
Adds `/faith/calendar`, `/glaube/kalender`, `/fides/calendarium` route backed by
romcal v3 + @romcal/calendar.general-roman with native EN/DE/LA locales. Month
grid, today hero, and day detail panel use liturgical colors from the rubric.
Header gets a segmented 1969/1962 pill toggle; selecting 1962 shows a WIP
placeholder (Tridentine calendar data not yet wired up).
WebKit's hidden <input type="checkbox" switch> haptic trick is gated on
tap-completion, not tap-start. Firing on pointerdown ran the programmatic
click() before iOS committed to "this is a tap" so the switch-toggle
haptic was suppressed. pointerup lands inside iOS's tap-completion
window — still earlier than click (no movement filter, no 300ms wait).
Android native bridge path is unaffected.
Derive recents from current-day entries merged with historical
server data so logging a food updates the quick-log bar instantly.
FoodSearch now emits onfavoritechange so toggling a heart keeps
the quick-log favorites tab in sync without reloading.
Align muscle group and equipment filters in the exercise picker
with the rest of the fitness UI — horizontal pill scrollers, multi-
select, with Lucide icons for each equipment type.
Edit mode now shows a pill row (breakfast/lunch/dinner/snack with their
icons) beneath the grams input so the entry can be moved to another meal.
Food cards are also draggable; dropping onto a different meal section
optimistically moves the entry (rolls back on API error). Desktop/pointer
only — touch devices use the pill row.
Allow users to nest steps inside a repeat group (e.g. "5×: 30s sprint,
60s recovery") when building GPS interval templates. Groups are tagged
{ type: 'group', repeat, steps } alongside flat { type: 'step' } entries
and capped at one nesting level. Entries are expanded into a flat list
before handing off to the native Android TTS/interval service, so the
runtime state machine is unchanged.