PWA & offline¶
FigureCollector is a Progressive Web App — installable on iOS, Android, and desktop, with offline-first capability.
Installation¶
- iOS Safari: tap "Share" → "Add to Home Screen". The PWA opens fullscreen, hidden URL bar.
- Android Chrome: a prompt usually appears; otherwise menu → "Install app".
- Desktop Chrome / Edge: install icon in the address bar.
Mobile navigation¶
On phone-sized viewports the app adds a bottom tab bar — thumb-reach navigation instead of the desktop header:
| Tab | Route |
|---|---|
| 蒐 Collection | /collection |
| 目 Catalogue | /browse |
| + (center seal, hanko-red) | add a figure |
| 価 La Cote | /cote |
| ⋯ Plus | opens the drawer with every secondary route |
The bar respects the iOS safe-area inset, marks the active tab with the gold
diamond, and disappears on lg+ viewports where the header navigation takes
over.
Service Worker caching strategy¶
The SW is generated by vite-plugin-pwa + Workbox at build time and serves several precaches + runtime caches:
| Pattern | Strategy | Why |
|---|---|---|
| App shell (JS/CSS/HTML) | Precache | Hashed build outputs; new shells trigger a "Nouvelle version" toast. |
/api/photos/* |
CacheFirst (30 d) | Photos are immutable — the storage_key changes per upload, so caching aggressively is safe. |
/api/figures* |
NetworkFirst (3 s timeout) | Catalog reads must surface mutations on the next navigation. The cache stays as an offline fallback when the network truly fails. |
/api/external/* |
StaleWhileRevalidate (24 h) | MFC / AniList proxies — cache is fine, server already has its own. |
*.wasm, *.onnx |
CacheFirst (1 y) | ML model weights; hashed URLs change on rebuild. |
staticimgly.com/@imgly/background-removal-data/* |
CacheFirst (1 y) | bg-removal models; pinned versioned URLs. |
| Google Fonts | StaleWhileRevalidate / CacheFirst | CSS + font files. |
Why NetworkFirst on /api/figures*?¶
Earlier versions used StaleWhileRevalidate and the user reported "new figurines don't appear" and "thumbnail changes need a reload". Reason: SWR serves the stale cache synchronously on the first refetch, masking the freshly-mutated data. NetworkFirst with a 3-second timeout gives fresh data when online and falls back to cache only when the network truly fails.
Update prompt¶
registerType: "prompt" — when a new SW is detected, the user gets a "Nouvelle version disponible · Recharger" toast. They control when the new shell activates. The push handler is shipped as a sibling push-handler.js and importScripts'd by the SW so push delivery + precache live in a single registration.
Offline behavior¶
- Browse + Collection: TanStack Query serves the last-known list. New mutations queue and dispatch on reconnect.
- Photo upload: fails fast offline (no offline-queue yet).
- Web Push: continues to receive pushes even when the app is closed, provided the OS isn't blocking the SW.