Framework Adapters
How Swoff bridges service worker events to your framework's reactive system.
What is an Adapter?
An adapter listens to window events dispatched by the service worker registration code and exposes them as reactive state in your framework — hooks, composables, stores, signals, or services.
The adapter layer is the only framework-specific code in Swoff. Everything else (SW template, build script, registration logic) is plain JavaScript.
Event Flow
SW Registration Code (framework-agnostic)
↓ dispatches
window.addEventListener('sw-update-available', ...)
window.addEventListener('sw-progress', ...)
window.addEventListener('sw-ready', ...)
window.addEventListener('sw-error', ...)
window.addEventListener('sw-auth-state-change', ...)
window.addEventListener('cache-invalidated', ...)
window.addEventListener('background-sync-complete', ...)
window.addEventListener('mutation-sync-complete', ...)
window.addEventListener('mutation-queue-changed', ...)
window.addEventListener('push-subscription-changed', ...)
window.addEventListener('push-permission-changed', ...)
↓
Adapter (framework-specific)
↓ exposes
useSWUpdate() / useSWProgress() / useCachedFetch() / useMutationQueue() / useAuth() / usePushSubscription() / useNetworkStatus() / useBackgroundSync() / useCacheInvalidation() — React
useSWUpdate() / useSWProgress() / useNetworkStatus() / useBackgroundSync() / useCacheInvalidation() — Vue composables
... — Svelte stores, Solid signals, Angular servicesEvents to Listen To
| Event | Detail | When |
|---|---|---|
sw-update-available | { version: string } | New SW version detected |
sw-progress | { percent: number } | During SW download |
sw-ready | none | SW activated and ready |
sw-error | none | SW registration failed |
sw-auth-state-change | none | Auth state changed (login/logout/refresh) |
cache-invalidated | { tags: string[] } | Cache tags invalidated (by this tab or another) |
mutation-sync-complete | { succeeded: number, failed: number } | Queue sync finished |
mutation-queue-changed | none | Queue contents changed (added/processed) |
background-sync-complete | { succeeded: number, failed: number } | Background sync finished |
push-subscription-changed | { subscribed: boolean } | Push subscription added/removed |
push-permission-changed | { permission: NotificationPermission } | Permission granted/denied |
Window Properties
| Property | Type | Purpose |
|---|---|---|
currentSWVersion | string | undefined | Active SW version |
latestSWVersion | string | undefined | Server-side version |
swMinSupportedVersion | string | undefined | Minimum version that can still serve |
swUpdateRequired | boolean | undefined | Whether update is enforced |
Adapter Responsibility
Your adapter should:
- Listen to
sw-update-availableand exposeavailableVersion,forceUpdate - Listen to
sw-progressand exposeprogress,status - Provide
acceptUpdate()— registers new SW viaregisterServiceWorker() - Provide
dismissUpdate()— setssessionStorage['sw-dismissed-update'] - Provide
checkForUpdates()— manually fetchesversion.json - Listen to
cache-invalidated/mutation-sync-complete/background-sync-complete/push-subscription-changedand expose reactive state for each feature
React Implementation
React uses hooks with useState, useEffect, and useCallback. See React Hooks.
Vue Implementation
Vue uses composables with ref, reactive, and onMounted/onUnmounted. See Vue Composables.
Svelte Implementation
Svelte uses stores with writable and lifecycle functions. See Svelte Stores.
Next Steps
- See Component Specs — what each component does
- Choose your ecosystem: React, Vue, Svelte
Swoff