Slow networks: lazy editor, right-sized grid images, offline share queue

Merged
FR
6d ago
+743-60

What & why

Slices 3 and 4 of the slow-network / mobile PWA work (after #654 and #655), one commit each so they can be reviewed separately.

Lighter dashboard first load (a2e9767)

  • The inline note composer pulled Tiptap/ProseMirror into the dashboard's first-load bundle. It now loads with next/dynamic (ssr: false).
  • First paint doesn't change: the editor already uses immediatelyRender: false, so it never server-rendered.
  • Measured on a prod build: first-load JS for the dashboard client tree drops from 910 → 759 KB gzipped (−151 KB, about 17%), and no ProseMirror code is left in first-load chunks.

Right-sized grid images (f57be8d)

  • Grid tiles used to fetch a single 800px q90 rendition whatever size they were shown at.
  • Img/BlurImage now take an optional sizes. Passing it opts a resized image-proxy URL into a srcset of 400/600/800 widths. Only widths up to the URL's own are offered, so nothing ever fetches more than before.
  • The grid uses sizes="auto, (max-width: 640px) 50vw, 33vw".
  • Retries now cache-bust every srcset candidate. Browsers load from srcset rather than src, so busting src alone would have stopped retries working.
  • Grid quality goes from q90 to q80.
  • Applied to the main image card, the article cover and the video thumbnail.

Offline share queue (c77ec58)

  • A share opened with no connection used to land on the offline page and be lost. The service worker now catches a failed /save navigation and queues the exact save /save would have made (Serwist BackgroundSyncQueue). It then redirects to the offline page, which says the link is saved for later.
  • The queue replays on Background Sync. As a backstop, the offline page also asks the service worker to replay when the connection returns, because headless Chromium never fired sync in my tests.
  • A save that gets a 401 or 5xx stays queued (for up to 7 days), so a session that expired while offline doesn't drop it.
  • The offline page now reloads itself once the connection is back.
  • Fix to an existing rule: the "Supabase" cache rule also matched same-origin localhost and 127.0.0.1, so on a localhost deployment it swallowed every app request. It's now cross-origin only.

Checklist

  • User-facing change → added/updated a PostHog event, or N/A. N/A: replayed saves hit from-url with source: share_target, which is already tracked server-side.
  • User-facing or service change → docs updated, or N/A. N/A: no new flow to document.
  • New error paths report via captureServerException / the error boundary, or N/A. N/A: client/service-worker best effort.
  • New behavior is covered by tests, or N/A: image-url.test.ts, img.test.tsx, srcSetForAttempt + hook retry tests, share-queue.test.ts, ~offline/page.test.tsx.
  • If this fixes a recurring defect, considered a guardrail via the learn skill, or N/A. N/A.

Notes

  • Verified the offline queue against a prod build (next start + Playwright):
    • Going offline and opening /save?url=… redirects to /~offline#share-queued, with one entry in the queue.
    • Back online, the queue replays: the entry is removed on a final response and kept on a 401.
    • I could not test a successful authenticated replay without a session.
  • No visual change from the lazy-loaded editor; the composer story renders.

Generated by Claude Code