PWA Foundation
Install prompt, SW generation, versioning, manifest, icons, and storage estimate.
If you're coming from Workbox: Swoff generates a complete, auditable service worker from config — no manual SW code, no runtime Workbox modules bundled into your app. The generated SW is a
.jsfile you can read, debug, and commit. See the Comparison: SW Toolkits.
Preconditions
- A
swoff.config.json(runnpx @swoff/cli initif you don't have one) - Node.js (to run the CLI and build script) — no
package.jsonrequired, see Ecosystem Compatibility for non-Node.js projects
Status
On by default. PWA support is enabled automatically after swoff init.
Enable
PWA is enabled by default after swoff init. To enable it in an existing config, set features.pwa.enabled: true in swoff.config.json.
Generated files
| File | What it does | Import in your code? |
|---|---|---|
swoff/pwa/prompt.ts | Install prompt listener, isInstallable(), promptInstall() | Yes (bundler only) |
swoff/sw/template.js | The SW source — reads cache strategies, auth, tags from config headers | No, built into SW |
swoff/sw/generator.mjs | Build script that produces the final sw.js | Run: node swoff/sw/generator.mjs |
swoff-api.bundle.js | Same PWA/storage APIs via window.swoff.isInstallable() etc. for no-bundler projects | No (auto-initializes) |
Usage
Bundler projects
import { initServiceWorker } from "./swoff/client-injector";
import { isInstallable, promptInstall } from "./swoff/pwa/prompt";
// At app startup — also wires up PWA install handler automatically
initServiceWorker();
// Show install button when available
if (isInstallable()) {
const result = await promptInstall();
// result.outcome === "accepted" | "dismissed"
}No-bundler projects
Include the auto-initializing bundles, then use the API on window.swoff:
<script src="/swoff/client-injector.bundle.js"></script>
<script src="/swoff/swoff-api.bundle.js"></script>
<script>
// PWA install prompt
const installable = swoff.isInstallable();
if (installable) {
const result = await swoff.promptInstall();
// result.outcome === "accepted" | "dismissed"
}
</script>Config
{
"features": {
"pwa": {
"enabled": true,
"preventDefaultInstall": false
},
"serviceWorker": {
"autoActivate": false
}
}
}pwa.enabled— generate PWA install prompt and injectorpwa.preventDefaultInstall— capture the browser's install event without showing it; show your own UIserviceWorker.autoActivate— skip waiting and activate new SW immediately
PWA assets
Generate app icons, splash screens, and manifest.json from a source image:
npx @swoff/assets --source <path-to-icon> --output swoff/assetsThis creates platform-ready assets (PNG at various sizes, SVG favicon, Apple touch icons) and a manifest.json configured for your PWA. The generated manifest is automatically precached by the SW.
Build the SW
node swoff/sw/generator.mjsAdd this to your build script. It reads the config headers from generated source files and produces your final sw.js.
Offline analytics
The SW tracks which routes fell back to cached or offline responses. The useSwoffAnalytics adapter exposes { lastEvent, events, clear } — see the Navigation Caching guide for usage and event shapes.
Framework adapters
This section has three adapters:
useSwoffPwa
Exposes install prompt state: { isInstallable, promptInstall }.
Events listened to: beforeinstallprompt (browser native event).
If your framework already has a useSwoffPwa adapter (React, Vue, Svelte), the CLI generates it into swoff/adapters/. See the Blueprint for the event reference and adapter patterns.
useSwoffPrecache is covered in the Service Worker guide. useSwoffStorage is covered in the Connectivity guide.
Related
- Comparison: SW Toolkits — full PWA feature matrix