From f1c468f90f4d57f4579db2e7b72fea79637fe6b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Thu, 9 Jul 2026 12:17:54 +0200 Subject: [PATCH] =?UTF-8?q?chore(release):=20v1.28.3=20=E2=80=94=20consist?= =?UTF-8?q?ent=20spacing=20and=20alignment?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A layout-audit-driven consistency pass: one shared left edge for insight cards (headings and body align, worst on mobile), no scroll past content on settings and admin pages, Settings/Notifications only in the account menu on mobile, the dashboard action beside its greeting text, and preventive-care/cycle/onboarding cards on the shared card anatomy. The spacing and alignment rules are recorded in the standards. Also stages the document rasterization native binding in the image so a scanned PDF is read on an image-only AI provider. --- CHANGELOG.md | 16 ++++++++++++++++ Dockerfile | 14 ++++++++++++++ docs/api/openapi.yaml | 2 +- package.json | 2 +- public/sw.js | 2 +- 5 files changed, 33 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a669c910..f340e7822 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,22 @@ ## [Unreleased] +## [1.28.3] — 2026-07-09 — Consistent spacing and alignment + +A consistency pass across the app, driven by a layout audit. Insight cards now +share one left edge — headings and body text line up instead of drifting from +card to card (worst on mobile). Settings and admin pages no longer scroll past +their content into empty space. On mobile, Settings and Notifications live only +in the account menu instead of being duplicated in the overflow menu. The +dashboard greeting keeps its action beside the text rather than pushing it onto +its own line. Preventive-care, cycle, and onboarding cards adopt the shared card +anatomy. The spacing and alignment rules behind these are written down so they +hold going forward. + +Also folds in the document PDF rasterization runtime: the image renderer now +loads in the container, so a scanned PDF is read on an image-only AI provider +(previously it quietly fell back to text-only). + ## [1.28.2] — 2026-07-09 — Automatic AI document reading (opt-in) One opt-in in AI settings: read every uploaded document automatically with your diff --git a/Dockerfile b/Dockerfile index a883e6c82..7d3bcd895 100644 --- a/Dockerfile +++ b/Dockerfile @@ -81,6 +81,20 @@ COPY --from=builder /app/public ./public COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static +# @napi-rs/canvas (document PDF rasterization): Next's file tracer copies the +# native binary's package into the standalone tree but NOT the pnpm symlink that +# @napi-rs/canvas's loader resolves it through, so at runtime it fails with +# "Failed to load native binding" and rasterization silently degrades. Copy the +# prebuilt .node into the canvas package dir itself so the loader's built-in +# local-file fallback (`require('./skia..node')`) resolves it. Per-arch +# buildx installs only the matching musl triple, so the find is arch-correct. +RUN CANVAS_DIR="$(find ./node_modules/.pnpm -maxdepth 4 -type d -path '*@napi-rs+canvas@*/node_modules/@napi-rs/canvas' 2>/dev/null | head -1)"; \ + NODE_BIN="$(find ./node_modules/.pnpm -maxdepth 5 -name 'skia.linux-*-musl.node' 2>/dev/null | head -1)"; \ + if [ -n "$CANVAS_DIR" ] && [ -n "$NODE_BIN" ]; then \ + cp "$NODE_BIN" "$CANVAS_DIR/" && chown nextjs:nodejs "$CANVAS_DIR/$(basename "$NODE_BIN")" && \ + echo "canvas native binding staged: $(basename "$NODE_BIN") -> $CANVAS_DIR"; \ + else echo "WARN: canvas native binding not found; PDF rasterization will degrade to local text"; fi + # Copy Prisma for migrations (schema, migration SQL, config, engines) COPY --from=builder /app/prisma ./prisma COPY --from=builder /app/prisma.config.ts ./prisma.config.ts diff --git a/docs/api/openapi.yaml b/docs/api/openapi.yaml index 870b9d6b6..2a30750d1 100644 --- a/docs/api/openapi.yaml +++ b/docs/api/openapi.yaml @@ -1,7 +1,7 @@ openapi: 3.1.0 info: title: HealthLog API - version: 1.28.2 + version: 1.28.3 description: >- Self-hosted personal-health-tracking PWA — public API surface for the iOS native client and external ingest. diff --git a/package.json b/package.json index 783cd92c6..e1d16a182 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "healthlog", - "version": "1.28.2", + "version": "1.28.3", "description": "Self-hosted personal-health-tracking PWA with Withings integration, AI insights, and doctor-report PDF export.", "license": "PolyForm-Noncommercial-1.0.0", "homepage": "https://healthlog.dev", diff --git a/public/sw.js b/public/sw.js index b47ec4239..fbed073e5 100644 --- a/public/sw.js +++ b/public/sw.js @@ -36,7 +36,7 @@ try { // v1.4.38.4 → v1.4.42. Do not hand-edit; bump `package.json` and rebuild. const CACHE_VERSION = (typeof self !== "undefined" && self.__APP_VERSION__) || - /* @sw-version-fallback */ "v1.28.2"; + /* @sw-version-fallback */ "v1.28.3"; const STATIC_CACHE = `healthlog-static-${CACHE_VERSION}`; const PAGE_CACHE = `healthlog-pages-${CACHE_VERSION}`; // v1.18.6 — read-only data cache for a curated allowlist of safe GET `/api/*`