A pure-JS, content-addressed, copy-on-write virtual filesystem for the browser, featuring: deduplication, filesystem universes (snapshots), events, and optional asynchronous sync.
jFS3 is a modern, lightweight filesystem engine designed for browser environments and offline-first applications.
It stores file data as immutable, hashed blocks in IndexedDB, keeps inode structures in RAM while synchronizing them back to IndexedDB, and provides advanced features such as copy-on-write, universes (snapshots), block-level deduplication, and an event-driven architecture.
All in ~10 kB minified and with zero dependencies.
All file data is chunked, hashed, and stored by content.
All modifications create new blocks while preserving old ones.
Identical blocks across all files, directories, universes are stored only once.
Universes are isolated copies of filesystem subtrees.
Example:
fs.cloneUniverse("/", "@backup"); // create snapshot
fs.cloneUniverse("@backup", "/"); // restore snapshotIncludes events:
- change-path
- create-file
- change-file
- delete-file
- create-dir
- delete-dir
- read-file
- write-block
- write-inode
- read-inode
- delete-inode
- move
- copy
- create-tree
- delete-tree
- create-universe
- delete-universe
Includes send/receive frame encoding, block transfer, metadata merge, tombstones, and timestamp-based conflict resolution.
Example (with WebXDC):
const fs = new jFS3(2048, true) // blocksize: 2048, sync: true
// add send (TX)
fs.addTX(
// called on given interval (when payload aviable)
(frame) => {
window.webxdc.sendUpdate({payload:frame})
},
// set interval (default: 10s)
window.webxdc.sendUpdateIntervalย || 10000,
// set max-frame-size (default: 128kB)
window.webxdc.sendUpdateMaxSize ||ย 128000
)
// connect receive (RX)
window.webxdc.setUpdateListener((update) => fs.pushRX(update.payload));Works in browsers, PWAs, WebViews, offline apps, and extensions (~10 kB minified).
<script src="jFS3.js"></script>Or:
import jFS3 from "./jFS3.js";const fs = new jFS3(4096); // Use blocksize: 4096 bytes
// Run when Filesystem is ready
fs.onready(async () => {
// Create directories
fs.mkdir("/docs");
// Write
await fs.writeFile("/docs/hello.txt", "Hello World");
// Read
const file = await fs.readFile("/docs/hello.txt");
console.log(await file.text());
// Create a snapshot
fs.cloneUniverse("/", "@u1");
// Delete file
fs.rm("/docs/hello.txt");
// Restore snapshot to revive deleted file
fs.cloneUniverse("@u1", "/");
});JSON-based inode structures containing type, blocks, timestamps, etc.
Immutable, hashed blocks stored under a "blocks" store.
When writing data, jFS3 only stores new blocks if the content is unique. Existing blocks are reused through hash-based deduplication.
Runs every 30 seconds to delete unreferenced blocks.
jFS3 is built around the concept of filesystem universes.
The root universe "/" represents the active filesystem, but additional universes (e.g. "@backup", "@u1") can be created for snapshots, branching, and isolated changes.
Also any path can be transferred into a subpath of another or even the same universe, producing an identical copy of that subtree.
Uses base64-encoded JSON frames for block + inode replication.
fs.mkdir(path)fs.rmdir(path)fs.listdir(path)fs.chdir(path)fs.getcwd()
fs.writeFile(path, data, blocksize?)fs.readFile(path)fs.rm(path)
fs.copy(src, dest)fs.move(src, dest)
fs.abspath(path)fs.relpath(path, target?)fs.join(root, path)fs.split(path)fs.splitext(path)
fs.metainfo(path)fs.quota(path?)
fs.listUniverses()fs.cloneUniverse(src, name)fs.deleteUniverse(name)fs.transfer(srcTree, destTree)fs.deleteTree(path)
fs.on(event, handler)fs.off(event, handler)fs.onready(func)
fs.addTX(sendFunction, interval, frameSize)fs.pushRX(frame)
- Client-side File-Explorer
- Offline-first editors (text, code, binary)
- WebXDC / DeltaChat apps
- P2P sync
- Versioning + snapshots
- Git-like branching in-browser
Issues and feature suggestions are welcome. Contributions are appreciated!