SwoffSwoff

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 .js file you can read, debug, and commit. See the Comparison: SW Toolkits.

Preconditions

  • A swoff.config.json (run npx @swoff/cli init if you don't have one)
  • Node.js (to run the CLI and build script) — no package.json required, 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

FileWhat it doesImport in your code?
swoff/pwa/prompt.tsInstall prompt listener, isInstallable(), promptInstall()Yes (bundler only)
swoff/sw/template.jsThe SW source — reads cache strategies, auth, tags from config headersNo, built into SW
swoff/sw/generator.mjsBuild script that produces the final sw.jsRun: node swoff/sw/generator.mjs
swoff-api.bundle.jsSame PWA/storage APIs via window.swoff.isInstallable() etc. for no-bundler projectsNo (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 injector
  • pwa.preventDefaultInstall — capture the browser's install event without showing it; show your own UI
  • serviceWorker.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/assets

This 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.mjs

Add 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.

On this page