Commit Graph
18 Commits
Author SHA1 Message Date
Marc-André Bombeck 62eb431d66 release: v1.32.0 — hardening and scalability (#580)
* release: prepare v1.32.0

* test: stabilize water capture re-entry
2026-07-22 04:14:15 +02:00
Marc-André Bombeck 23ded20306 fix(pages): replace bare auth-gate spinners with a layout-reserving skeleton
Introduce a shared PageAuthGate (header + tile skeleton) and adopt it on the
top-level pages that flashed a lone centered spinner while auth resolved:
mood, measurements, achievements, illness, mental-wellbeing, checkups, cycle,
and the labs / medications / custom-metrics / illness detail routes. The
auth-resolving frame now reserves the page geometry instead of snapping in
after a spinner.
2026-07-09 00:23:13 +02:00
Marc-André Bombeck 887c79ec86 refactor(ui): unify page headers and surface read failures
Add a PageHeader primitive (one H1 vocabulary, optional description,
back-link, and action slots) and route the hand-rolled headers through
it, so every module reads with the same title/subtitle rhythm and no
icon beside the page title. Mental Wellbeing gains a visible header.
Add a QueryErrorCard and wire the list surfaces so a failed read shows
a retry card instead of falling through to the empty state, and swap
their full-page spinners for skeletons that hold the layout.
2026-07-02 00:00:37 +02:00
Marc-André Bombeck b3e6ba03d7 feat(measurements): add custom metrics (define, log, chart)
Add a user-defined custom-metric store alongside the built-in measurements
on the Measurements surface. A user defines an arbitrary metric (name, unit,
optional target window, decimals, description), logs values, and charts them.

The store is a separate generic catalog + values pair, isolated from the
closed measurement-type system: not synced, not in FHIR, not in insights —
log and chart only. Names and units are plaintext, mirroring the biomarker
catalog. The inline list lives beneath the measurement list (no new nav
entry); tapping a metric opens a detail page with the trend chart, target
band, stat strip, and an editable value history.

Migration 0224 adds custom_metrics and custom_metric_entries.
2026-06-30 08:54:39 +02:00
Marc-André Bombeck 1f4ba5939d style: apply prettier across the tree
One-shot prettier pass so the new format:check gate starts from a clean
baseline. Formatting only — no behaviour change. Generator-owned and
vendored artifacts stay untouched via .prettierignore.
2026-06-19 22:20:31 +02:00
Marc-André Bombeck c7425ca426 feat(vorsorge): add 7-day trend strip + measurements deep link to reminder cards
Enrich the Vorsorge cards with a discreet 7-day trend strip and a path
into the underlying readings.

- A quiet seven-bar strip of the reminder metric's last seven readings
  sits under the metric context on both the dashboard summary card and
  the full-grid cards, mirroring how a dashboard tile carries a small
  trend. Neutral muted bars, no status colour. A free-text reminder or a
  metric with fewer than two readings shows nothing, so card height stays
  stable. The strip reads a bounded last-7 window per type through the
  existing measurements endpoint, cached by type under the measurements
  invalidation prefix.
- The card kebab gains a 'Show measurements' item for measurement-linked
  reminders that opens /measurements pre-filtered to that type.
- The measurements list accepts a ?type=<MEASUREMENT_TYPE> deep link that
  seeds the existing client-side type filter while leaving the rail
  interactive; unknown tokens are dropped. The ?add= behaviour is
  unchanged.
- New labels added across all six locales.
2026-06-19 19:45:14 +02:00
Marc-André Bombeck 3ba542f797 fix(onboarding): make the guided tour first-time-only, drop every re-entry trigger
The guided tour now exists only as the first-time auto-start after onboarding.
Remove every in-app trigger that re-opened it: the per-module "show this tour"
button on the dashboard, measurements, mood, medications, labs, illness, cycle,
achievements, insights, and coach surfaces; and the Settings replay card.

Delete the now-orphaned ModuleTourTrigger component, the tour-restart worker,
the healthlog:module-tour and healthlog:tour-restart event listeners, the
single-stop overlay path, and the force-launch session marker. The first-time
auto-launch gate and the tour overlay itself are unchanged. Prune the orphaned
i18n keys across all locales and update the affected tests.
2026-06-18 23:58:27 +02:00
Marc-André Bombeck 33fec28b29 feat(onboarding): per-module tour re-entry + consolidated replay
Add a 'Diese Tour zeigen' affordance to every module header that opens the
tour narrowed to that module's card in place, plus additive data-tour
anchors (measurements/medications/labs/illness/vorsorge/cycle/mood/
insights/coach/integrations/export/achievements) so the cross-page walk
has a real target on each page. Consolidate the full-tour replay onto a
single Settings -> Advanced card, relabel it, and drop the duplicate from
About. The replay reset clears the stored progress so it restarts cleanly.
2026-06-18 19:49:37 +02:00
Marc-André Bombeck 9c8c7051aa fix(labs): pin add-entry action bars to the sheet footer; tighten header
The lab and biomarker forms portal their Cancel/Save row into the
ResponsiveSheet sticky footer (footerSlot pattern) so Save stays reachable
on mobile instead of scrolling away. The Labs header folds Manage
biomarkers into an overflow kebab beside the primary Add, mirroring the
medication header. The biomarker detail gains a self-edit Pencil opening
the pre-filled form. Add buttons on the labs detail and measurements page
meet the min-h-11 sm:min-h-9 tap floor.
2026-06-16 23:12:04 +02:00
Marc-André BombeckandClaude Opus 4.8 b7b160d4fa fix(headers): keep list-page header actions on one row on mobile
The medications header used flex-wrap, so its action group (take-all
+ customize wrench + Add) dropped to a second row below the title on
narrow viewports. Drop the wrap and let the title block shrink: title
div gets min-w-0, subtitle truncates, action group keeps shrink-0 —
the wrench and Add stay top-right inline with the heading.

The mood, measurements and dashboard headers shared the same latent
root cause (title div missing min-w-0, subtitle/greeting not
truncating, action group not shrink-0). Apply the same minimal guard
so none of them can wrap or compress the actions either.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 10:52:39 +02:00
Marc-André Bombeck 5778dd0be0 fix(release): ssr-safe add-param, noon-anchored compliance days, localized wizard assertion
The measurements page consumed its add parameter during render, which
crashed server rendering now that every route renders dynamically with
real search params. Compliance day buckets anchored to the current
wall-clock minus twelve hours, so before local noon the current day was
missing from every bucket series — they anchor on local noon now. The
wizard spec accepts the localized start date its summary deliberately
shows, and the generated contract picks up the version bump.
2026-06-11 11:01:22 +02:00
Marc-André Bombeck a8149e0bdf fix(ux): honest deletes, stable hydration and tidy numbers after release review
Server and first client render now agree everywhere query state used to
leak into the chrome, checkboxes no longer nest inside buttons, delete
confirmations admit the undo they offer, raw step counts drop their
decimals, the truncated unit label wraps instead, streaks know their
singular, the medication header speaks the user's date format, a failed
coach turn keeps the user's message and says what went wrong, settings
status notes follow a language switch, the locale only flips once its
bundle actually loaded, and the last raw api fetches in hooks move onto
the shared client.
2026-06-11 03:30:18 +02:00
Marc-André Bombeck 7e7e17c68c feat(medications,coach,insights): record the dose you actually took
An intake can carry the dose that was actually taken — editable in the
quick-add and log dialogs, shown as a quiet deviation line in the
history. The measurements and mood lists refresh by pull on touch, the
insight sub-pages gain the same customize entry as the overview, and an
answered coach follow-up offers to adopt the answer into the matching
self-context field.
2026-06-11 00:10:01 +02:00
Marc-André Bombeck 04765ea8ac style: one spacing, title and skeleton language across the app
Icons inside buttons drop their manual margins in favour of the
button's built-in gap (two hundred call sites), form field stacks settle
on one spacing step, card titles on exactly two sizes, inline field
errors on one text size, and a dozen hand-rolled loading pulses move
onto the shared skeleton primitive while keeping their silhouettes. The
intake dialog wording joins the rest of the app on 'übersprungen', and
the UI guidelines now document the two deliberate footer and
touch-target systems.
2026-06-10 16:54:15 +02:00
Marc-André Bombeck f5962497d6 v1.4.34.4 — audit-driven hotfix bundle (security, UX, code-quality, docs)
Consolidated hotfix landing the findings from a six-axis audit
covering mobile security, UX + accessibility, code quality + docs,
README + discoverability, web performance, and mobile-deep responsive
behaviour. None of the changes break the public API or the existing
data shape; every fix is additive and SAFE under the v1.4.34.x web
freeze. Full audit reports live in `.planning/round-audit-*.md`.

Security
  - Password rotation now wipes API tokens + refresh tokens in the
    same `$transaction` as session revocation. A stolen iOS Bearer no
    longer survives a user-initiated password change or an admin reset.
  - `/.well-known/` proxy bypass tightened to an explicit-allowlist
    `Set`. Stale `/api/auth/codex/callback` PUBLIC_PATHS entry dropped.
  - HSTS gains `preload`. Withings host removed from the global CSP
    and gated to the integration's own routes.
  - `getClientIp` warns once per process on `TRUST_PROXY_HOPS`/XFF
    mismatch + exposes a tagged helper for tighter universal buckets.
  - Service worker rejects off-origin notification-click URLs. Offline
    fallback body switched to a locale-neutral icon. Manifest gains
    `scope`, `id`, `display_override`.

UX + accessibility
  - i18n leaks closed on Dialog/Sheet close-X, ChartSkeleton's loading
    announcement, and the notifications-section breadcrumb.
  - Focus rings on bottom-nav, the More overflow button, and the
    mobile top-bar user menu.
  - Tap-target floor: Input / NativeSelect / Select / DateTimeInput
    switch to `h-11 sm:h-10`.
  - Admin chip-strip auto-scroll-into-view (matches v1.4.33 settings).
  - List-page subtitles visible on mobile.
  - Insights empty-state CTA vocabulary normalised so the link opens
    the right measurement form (was silently failing for
    BODY_TEMPERATURE / BLOOD_GLUCOSE / PULSE).

Mobile-deep
  - `viewport.themeColor` reacts to light/dark mode.
  - TopBar + Coach FAB reserve safe-area-inset-top / -bottom for
    notched iPhones.
  - Sonner toaster switches to `theme="system"`.

Code quality
  - `SESSION_SECRET` dropped — the env var was documented as required
    but never read by code. Three secrets, not four. Self-hosters
    upgrading can delete the existing line.
  - `toJson<T>()` helper consolidates seven Prisma JSON-cast sites.
  - `db-compat.ts` gains a header docstring naming it the
    schema-bootstrap path.
  - Passkey response types adopted from `@simplewebauthn/server`;
    `any` + eslint-disable pragmas drop out.
  - Zero-TODO CI gate added at `.github/workflows/no-todo-markers.yml`.

Documentation + discoverability
  - README rework: How-it-compares matrix, Apple Health + AI Coach
    promoted to standalone Key-Features bullets, status block, latest
    release + GHCR badges, OpenAPI pointer, three-secret Quick Start.
  - openGraph + twitter cards now carry `images` and a
    `summary_large_image` Twitter card.
  - GitHub repo metadata: description tightened from 290 to 156
    chars + keyword-front, `homepageUrl` flipped from a personal
    tenant to the demo site, six generic / PII-adjacent topics
    swapped for six high-intent ones.
  - Five new user-facing docs: `docs/self-hosting/getting-started.md`,
    `docs/self-hosting/reverse-proxy.md`,
    `docs/integrations/apple-health.md`,
    `docs/integrations/withings.md`,
    `docs/integrations/ai-providers.md`.
  - `docs/README.md` clarifies the docs tree as internal playbooks
    vs the user-facing `docs.healthlog.dev` site.
2026-05-17 00:39:58 +02:00
Marc-André Bombeck 4f09c3f862 chore(release): v1.4.27
v1.4.27 — Mobile capability and maintainer-finding cleanup.

ResponsiveSheet primitive (bottom-sheet on narrow viewports, centred dialog on desktop)
applied to BD, Weight, Glucose, Mood, Activity forms. Maintainer-finding cleanups across
Coach, Insights, Reports, Privacy. GeoLite2 offline geocoding with resilience layer
(graceful fallback when EULA not yet propagated). E2E gap-fill coverage. 450-line
release notes attached to the GitHub Release.
2026-05-15 22:59:10 +02:00
Marc-André BombeckandClaude Opus 4.7 1d65f3b925 feat(lists): empty states for measurements, mood, medications, achievements (impl)
Follow-up to 9a74f8e — that commit's pathspec didn't pick up the
implementation files, only the new test. This commit lands the actual
EmptyState wiring described in the previous message:

- src/components/measurements/measurement-list.tsx — Activity icon,
  filter-aware empty state, optional onAddFirst CTA prop.
- src/components/mood/mood-list.tsx — Smile icon, mirroring filter
  semantics + optional onAddFirst.
- src/app/measurements/page.tsx + src/app/mood/page.tsx — pass
  onAddFirst so the empty-state CTA opens the same dialog as the
  header button.
- src/app/medications/page.tsx — refactor inline icon+text+button
  block to the EmptyState primitive (Pill icon).
- src/app/achievements/page.tsx — Trophy icon for the no-achievements
  state, reusing the existing noneUnlockedYet string.

Together with 9a74f8e the four feature lists now share a consistent
empty-state surface with the rest of the app.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 21:51:48 +02:00
Marc-André Bombeck 38309932f3 Initial release v1.0.0
HealthLog — personal health-tracking PWA with weight, blood pressure,
pulse, mood tracking, medication compliance, Withings integration,
doctor report PDF export, and Dracula-themed UI.
2026-03-10 20:14:33 +01:00