currentStreak() was starting its backward walk from today, so if the
user hadn't checked in yet today the first lookup missed and it
returned 0 — even with a perfect streak on previous days.
Now when today's entry is absent and the goal is still active, the
count starts from yesterday instead. Once the goal window has closed
the original end-of-window anchor is preserved.
beforeinstallprompt fires asynchronously after renderLanding() runs,
so the click handler was never attached when the prompt arrived late.
Always attach the handler and check deferredInstallPrompt at click time.
- Landing page shows an "add to home screen" button when the browser
install prompt is available (Android/desktop) or on iOS Safari with
a share-menu hint; hidden when already running in standalone mode
- Last visited user route (/ray or /cer) is saved to Dexie meta and
restored on next open so the app reopens where you left off
- Active user in the topbar brand renders as a filled accent-color pill
- A 1px accent-color frame wraps the entire viewport while a user is active
Vanilla HTML/JS/CSS PWA with Dexie offline-first sync, Hono+SQLite backend,
served via nginx reverse-proxy. Two seed goals (no-sugar, no-social-media)
for users ray and cer.
Local dev runs at https://raycer.test via the shared Traefik proxy.
Production deploys to https://raycer.altweb.me on cool2026/personal via
docker-compose.coolify.yaml — see deploy/COOLIFY.md.