Skip to content

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.