Progressive Web App reference
This document explains how the Nudger Nuxt frontend is configured as a PWA and what to touch when shipping new capabilities.
Manifest & metadata
- The manifest lives at
app/public/site.webmanifest. It contains the product name, categories, shortcuts, screenshots and the link to all generated icons. - Nuxt exposes it through
app.head.linkinsidenuxt.config.ts. Update thelink+metaentries whenever a new icon or theme color ships. - The same manifest is injected into
@vite-pwa/nuxt(seenuxt.config.ts > pwa.manifest). Keep both in sync by editing the JSON file only, then re-runningpnpm lintto ensure type safety.
Icon & screenshot pipeline
Icons and screenshots live under app/public/pwa-assets. Regenerate the set via Pillow whenever branding evolves:
pnpm exec python3 scripts/generate_pwa_assets.py
The script writes transparent + maskable icons and the two store screenshots referenced by the manifest.
After regenerating assets run pnpm lint so the manifest import stays type-checked.
Service worker & caching
@vite-pwa/nuxt is registered in nuxt.config.ts with:
registerType: 'autoUpdate'so users see updates as soon as the build is deployed.- Workbox runtime caches for API calls (
NetworkFirst) and media (StaleWhileRevalidate). - An offline fallback route served from
server/routes/offline.get.ts.
When touching caching rules adjust the runtimeCaching array near the top of nuxt.config.ts.
Install & offline UX
- The composable
app/composables/usePwaPrompt.tswraps thebeforeinstallpromptevent and service-worker registration state. - UI entry points live in
app/components/pwaand are mounted from the default layout + error layout so all routes share the same UX. - All strings belong to
i18n/locales/*under thepwa.*namespace.
Offline indicator & responsive hints
app/components/pwa/PwaOfflineNotice.vuerenders a floating indicator instead of a blocking banner.- Desktop viewports show a permanent tooltip anchored to a warning icon in the top-right corner.
- Mobile / PWA shells receive an inline pill with retry/close icons sized for touch.
app/composables/pwa/usePwaOfflineNoticeBridge.tsstill manages the shared dismissal state; the indicator simply consumes it together withuseDisplay()fromnuxt-deviceto react to viewport changes.
Barcode scanner pipeline
app/components/pwa/PwaBarcodeScanner.vueowns the capture logic.- When supported, it uses the native
BarcodeDetectorAPI tied touseDevice()to prioritise the rear camera in mobile shells. - If the detector or camera APIs are unavailable, it lazily loads the
vue-barcode-readerstream component as a fallback and keeps emittingdecodeevents with the normalised GTIN/EAN value.
- When supported, it uses the native
app/components/search/SearchSuggestField.vueembeds the component inside the search dialog and forwards detections directly to the/[gtin]route.- This keeps the scanner self-contained and ready for reuse (e.g. in future contribution flows).
Notifications readiness
app/plugins/pwa-capabilities.client.tscaptures whether the browser supports the Notifications + Service Worker combo and stores the registration once it is ready.app/composables/pwa/usePwaCapabilities.tsexposessupportsNotifications, the cached permission and arequestNotificationPermission()helper so future UI can prompt users consistently.- The state is SSR-safe and remains accessible from any component or store without leaking browser globals.
Runtime caching reference
In addition to the default image/API caches, nuxt.config.ts now pre-defines the following Workbox strategies:
nudger-font-styles-StaleWhileRevalidatefor Google Fonts stylesheets.nudger-font-files-CacheFirstfor Google Fonts binaries with a one-year TTL.nudger-static-cdn-StaleWhileRevalidatefor JS/CSS fetched fromcdn.jsdelivr.netorunpkg.com.
These extra caches keep typography and remote UI widgets available offline and reduce layout shifts when the network is flaky.
Validation checklist
Before merging PWA-related work run the standard frontend checks:
pnpm lint
pnpm test
pnpm generate
Additionally, confirm the PWA plugin output using Lighthouse (Chrome DevTools) or pnpm build && pnpm preview followed by a manual install test on desktop + Android.