Modern browsers ship a full storage stack: a private filesystem (OPFS), a transactional NoSQL database (IndexedDB), an HTTP cache you control (Cache Storage), and a background proxy (Service Workers) that decides what loads when the network dies. Used together, they let a web app work fully offline — no server required.
This guide walks the whole stack with runnable examples. And since NitroIDE itself is an offline-first PWA that persists your files locally, everything here mirrors patterns that work in production today.
The Origin Private File System gives your origin a private directory with near-native file performance — ideal for large assets, WASM modules, or virtual file systems:
Need synchronous, high-speed writes — e.g. streaming data from a worker? Sync access handles are the answer, but they only exist inside workers:
OPFS is for files; IndexedDB is for structured records — settings, document metadata, search indexes. It's asynchronous and transactional, which makes the raw API verbose. In practice, keep a tiny promise wrapper or use a micro-library; the key ideas are object stores and indexes:
OPFS vs IndexedDB — which one? Files and binary blobs → OPFS (faster, streaming-friendly). Structured records, queries, and indexes → IndexedDB. Many real apps use both: file bytes in OPFS, metadata and search indexes in IndexedDB.
A service worker sits between your page and the network. Register it once, and it can serve cached responses when offline, prefetch strategically, and even mock APIs during development:
Two honest requirements: service workers need HTTPS (or localhost), and their scope is limited to their directory and below. They also can't intercept the very first page load that registers them.
Normally a service worker delays navigation while it boots. Navigation preload lets the browser fetch the page in parallel with worker startup:
Background Sync lets you queue work while offline and have the browser retry it when connectivity returns — the classic "offline commit" pattern:
Two tabs editing the same OPFS file is a race condition waiting to happen. The Web Locks API gives you mutexes across tabs and workers:
If you store sensitive data locally, encrypt it. AES-GCM via WebCrypto is straightforward — the honest caveat is key management: a key stored next to the data it protects only defends against other origins and casual snooping, not against someone with full device access:
The offline test that matters: open DevTools → Network → set "Offline", then reload your app. If it boots and your data is there, your storage layer works. If it shows a dinosaur, you have a service worker gap. NitroIDE passes this test — it's a PWA that keeps working on airplane mode.
Prototype offline-first frontends in a browser IDE that works offline itself.
Launch NitroIDE