Read-only offline dashboard
Merged
FR
6d ago+138+138+012345678901234567890123456789-3-3-0123456789
What & why
Follow-up to #654–#657. When offline, show the user's last-loaded abode instead of the bare offline page.
- Pages kept for a week (
d606a67). The service worker already served cached page HTML when offline, but expired it after one day, so most offline launches landed on/~offline. It now keeps pages for 7 days (still max 32 entries, and still cleared when the signed-in user changes). Item images were already cached, so the grid comes back with its covers. - Offline page links to the saved dashboard. If the page asked for was never cached, "Open your saved abode" goes to
/dashboard. When that isn't cached either, the offline page simply comes back. - Offline banner (
6f315ce) across the signed-in app, driven by a newuseIsOnlinehook (useSyncExternalStore, assumed online during SSR). It says the page is as last loaded and that changes need a connection, and it firesoffline_banner_shown.
Checklist
- User-facing change → added/updated a PostHog event, or N/A:
offline_banner_shown - User-facing or service change → docs updated, or N/A: README features (PWA line)
- New error paths report via
captureServerException/ the error boundary, or N/A: N/A - New behavior is covered by tests, or N/A:
offline-banner.test.tsx(hidden online; appears and disappears with connectivity; shows on a page loaded offline), the offline page link test, and a story - If this fixes a recurring defect, considered a guardrail via the
learnskill, or N/A: N/A
Notes
- Verified against a production build with Playwright, using a throwaway public page that renders the banner, since the dashboard needs a DB:
- Online, the banner is hidden.
- Offline, a reload serves the cached copy (same server timestamp), it hydrates, and the banner shows. No console errors.
- An uncached page offline falls back to the offline page with the new link.
- Not done: disabling mutation controls while offline. Saves and edits fail with their existing error toasts, which the banner explains.
Generated by Claude Code