Configuration-first
Describe collections (episodes, lessons, tiles) and their policies once: transport, size threshold, limits, retries, notification UI.
Making a file available offline takes five browser APIs that don’t know about each other: Background Fetch, service workers, the Cache API, IndexedDB and the Storage API. Then come the edge cases nobody wants to write twice: re-attaching to a download after a reload, resuming a half-finished file, answering Range so <audio> can seek, staying under quota, and falling back in every browser that has no Background Fetch.
Offlibrary wraps all of it behind a config object and one method.
Configuration-first
Describe collections (episodes, lessons, tiles) and their policies once: transport, size threshold, limits, retries, notification UI.
Background Fetch when available
Downloads keep going after the tab or the browser closes, with the browser’s own progress notification, and re-attach after reloads.
Resumable fallback everywhere else
Streaming fetch with live progress, pause, resume, cancel and retries. Partial data is checkpointed to IndexedDB and resumes with Range, even after a reload.
Offline media that seeks
The service-worker module answers Range with 206 Partial Content straight from the cache. Use the original URL; it just works offline.
Storage you can reason about
Quota pre-checks, persist(), per-collection maxItems / maxBytes with LRU eviction, and pinned items that are never evicted.
First-class Workbox plugin
offlibrary/workbox brings stored files into your Workbox routes and strategies: OfflibraryPlugin, a ready-made route, and Background Fetch handling. No extra dependency. Learn more.
npm install offlibrarypnpm add offlibraryyarn add offlibrarybun add offlibraryimport { createOfflibrary } from 'https://cdn.jsdelivr.net/npm/offlibrary@0/dist/offlibrary.min.js';About 10 KB gzipped on the page and 4 KB in the service worker. Zero runtime dependencies, TypeScript types included.
import { createOfflibrary } from 'offlibrary';
navigator.serviceWorker.register('/sw.js');
const library = createOfflibrary({ namespace: 'podcast', collections: { episodes: { maxItems: 20 } }, // keep the 20 most recently used});
library.on('progress', ({ item }) => render(item)); // item.progress is 0..1await library.collection('episodes').download({ id: 'ep-42', url: 'https://cdn.example.com/ep-42.mp3', title: 'Episode 42',});
// Later, offline: same URL, served from the device, seeking included.audio.src = 'https://cdn.example.com/ep-42.mp3';import { offlibrarySW } from 'offlibrary/sw';
// Stores finished Background Fetches, updates the notification,// and serves stored files with Range support.offlibrarySW();import { precacheAndRoute } from 'workbox-precaching';import { registerRoute } from 'workbox-routing';import { NetworkOnly } from 'workbox-strategies';import { initOfflibrary, offlibraryMatch, offlibraryHandler } from 'offlibrary/workbox';
initOfflibrary();precacheAndRoute(self.__WB_MANIFEST);registerRoute(offlibraryMatch, offlibraryHandler({ fallback: new NetworkOnly() }));| Browser | Transport | What you get |
|---|---|---|
| Chrome, Edge, Opera, Samsung Internet | Background Fetch | Downloads survive tab and browser close, with a system notification |
| Firefox, Safari (incl. iOS), Android WebView | Resumable streaming fetch |
Same API and events; pauses when the tab closes, resumes on the next visit |
Background Fetch is Chromium-only, so Offlibrary treats it as a progressive enhancement. Browser support, with dates.