Offline-PWA toolkit for a small family of offline-first PWAs. It owns the three things every offline PWA in the family was hand-rolling:
- a hardened service worker (resilient per-URL precache, navigation fallback, content-hashed cache versioning, foreign-cache-safe eviction),
- an offline-readiness signal the app renders into its own badge, and
- build orchestration — esbuild bundles your
sw.ts/ui.tsand injects a content-hashed precache manifest, so the asset list can't drift from reality.
Designed for the family's no-bundler stack: esbuild bundles the consumer's entry points (importing this package),
tsconly type-checks.
/// <reference types="@tklepzig/offline-kit/global" />
import { createOfflineServiceWorker } from "@tklepzig/offline-kit/sw";
createOfflineServiceWorker({
cacheName: "myapp-cache",
precache: __SW_MANIFEST, // injected at build time by the CLI / buildPwa()
});Type-check it with the shipped base config:
import { observeOfflineReadiness } from "@tklepzig/offline-kit";
observeOfflineReadiness({
onStatus: ({ state, missing }) => {
// state: "caching" | "ready" | "incomplete" | "unavailable"
// render your own badge / text here
},
});The returned handle has refresh() for an on-demand re-check (e.g. when a
dialog showing the badge opens).
Add an offline-kit.config.js and call the CLI from your build:
// offline-kit.config.js
export default {
precache: ["ui.js", "style.min.css", "manifest.webmanifest", "assets/**/*"],
};// package.json
"scripts": {
"build": "tsc --noEmit && tsc -p tsconfig.sw.json --noEmit && sass … && offline-kit build",
"pwa:watch": "offline-kit build --watch"
}Defaults: page ui.ts → ui.js (ESM), SW sw.ts → sw.js (IIFE), target: "es2020", shell "./" from index.html. offline-kit build --watch runs an
esbuild watch for the dev loop.
The CLI is a thin wrapper over buildPwa, which stays exported for apps that
need extra build steps or custom control:
import { buildPwa } from "@tklepzig/offline-kit/build";
await buildPwa({ precache: [...], watch: false });Versioned with Changesets; snapshot
releases publish from a PR via a /snapshot comment (see .github/workflows).