Run OxiDB entirely in the browser. No server needed — data lives in memory within the WASM module and can be persisted to OPFS (the browser's Origin Private File System) so it survives page reloads. Supports MongoDB-style JSON queries, aggregation, and indexes.
Download the pre-built WASM package from GitHub releases and extract into your project:
curl -L -o oxidb-wasm.tar.gz \
https://github.com/parisxmas/OxiDB/releases/download/v0.34.0/oxidb-wasm-v0.34.0.tar.gz
mkdir wasm && tar xzf oxidb-wasm.tar.gz -C wasm/
Your project structure:
your-project/
wasm/
oxidb_wasm.js # ES module entry point
oxidb_wasm.d.ts # TypeScript types
oxidb_wasm_bg.wasm # WASM binary (~1.5 MB gzipped)
oxidb_wasm_bg.wasm.d.ts
index.html
Note: WASM files must be served from your own web server (same origin). Direct import from GitHub URLs will not work due to CORS restrictions.
Load the WASM module and create an in-memory database:
<script type="module">
import init, * as oxidb from './wasm/oxidb_wasm.js';
await init(); // load WASM binary
oxidb.init(); // create in-memory database
// ready to use
</script>
// Single document — returns document ID
const id = oxidb.insert('users', JSON.stringify({
name: 'Alice', age: 30, city: 'Berlin'
}));
// Multiple documents — returns JSON array of IDs
const ids = JSON.parse(oxidb.insert_many('users', JSON.stringify([
{ name: 'Bob', age: 25, city: 'Tokyo' },
{ name: 'Charlie', age: 35, city: 'Berlin' }
])));
// All documents
const all = JSON.parse(oxidb.find('users', '{}'));
// Filter
const berliners = JSON.parse(oxidb.find('users',
JSON.stringify({ city: 'Berlin' })
));
// Operators: $gt, $gte, $lt, $lte, $ne, $in, $nin, $exists, $regex
const older = JSON.parse(oxidb.find('users',
JSON.stringify({ age: { $gt: 25 } })
));
// Single document
const alice = JSON.parse(oxidb.find_one('users',
JSON.stringify({ name: 'Alice' })
));
// Returns number of modified documents
const n = oxidb.update('users',
JSON.stringify({ name: 'Alice' }), // filter
JSON.stringify({ $set: { age: 31 } }) // update
);
// Operators: $set, $unset, $inc, $mul, $min, $max, $push, $pull, $addToSet
oxidb.update('users',
JSON.stringify({ city: 'Berlin' }),
JSON.stringify({ $inc: { age: 1 } })
);
// Returns number of deleted documents
const n = oxidb.delete('users',
JSON.stringify({ age: { $lt: 20 } })
);
const total = oxidb.count('users', '{}');
const berliners = oxidb.count('users',
JSON.stringify({ city: 'Berlin' })
);
oxidb.create_index('users', 'age');
oxidb.create_index('users', 'city');
const pipeline = JSON.stringify([
{ $match: { age: { $gte: 20 } } },
{ $group: {
_id: '$city',
count: { $sum: 1 },
avg_age: { $avg: '$age' }
}},
{ $sort: { count: -1 } }
]);
const stats = JSON.parse(oxidb.aggregate('users', pipeline));
const names = JSON.parse(oxidb.list_collections());
oxidb.drop_collection('old_data');
The engine core is in-memory, but the browser gives every origin a private, persistent file store — OPFS (Origin Private File System). persist_opfs() snapshots the whole database to a real origin-private file (oxidb.json); load_opfs() restores it on the next visit. Both are async (they return Promises).
await init(); // load the WASM binary
oxidb.init(); // create the in-memory database
await oxidb.load_opfs(); // rehydrate from OPFS if a snapshot exists (first run: false)
// ... insert / update / delete as usual ...
oxidb.insert('tasks', JSON.stringify({ title: 'Buy milk', done: false }));
await oxidb.persist_opfs(); // write a fresh snapshot to OPFS
A common pattern is to reload on start and snapshot on unload:
window.addEventListener('beforeunload', () => { oxidb.persist_opfs(); });
Note: OPFS is available in all modern browsers (Chrome, Edge, Firefox, Safari 16.4+). The snapshot is a full image, so it is best suited to small/medium datasets; clear_opfs() deletes it for a fresh start.
<!DOCTYPE html>
<html>
<head><title>OxiDB WASM</title></head>
<body>
<pre id="out"></pre>
<script type="module">
import init, * as oxidb from './wasm/oxidb_wasm.js';
await init();
oxidb.init();
// Insert
oxidb.insert('tasks', JSON.stringify(
{ title: 'Buy groceries', done: false, priority: 'high' }
));
oxidb.insert('tasks', JSON.stringify(
{ title: 'Write docs', done: true, priority: 'medium' }
));
// Index
oxidb.create_index('tasks', 'priority');
// JSON query
const urgent = JSON.parse(oxidb.find('tasks',
JSON.stringify({ priority: 'high', done: false })
));
// Aggregation
const stats = JSON.parse(oxidb.aggregate('tasks', JSON.stringify([
{ $group: { _id: '$done', count: { $sum: 1 } } }
])));
document.getElementById('out').textContent =
JSON.stringify({ urgent, stats }, null, 2);
</script>
</body>
</html>
| Function | Arguments | Returns |
|---|---|---|
init() | — | Creates in-memory database |
insert(collection, jsonStr) | collection name, JSON document string | Document ID (string) |
insert_many(collection, jsonStr) | collection name, JSON array string | JSON array of IDs |
find(collection, queryStr) | collection name, JSON query string | JSON array string |
find_one(collection, queryStr) | collection name, JSON query string | JSON string or "null" |
update(collection, queryStr, updateStr) | filter, update operations | Modified count (number) |
delete(collection, queryStr) | collection name, JSON query string | Deleted count (number) |
count(collection, queryStr) | collection name, JSON query string | Count (number) |
aggregate(collection, pipelineStr) | collection name, JSON pipeline string | JSON array string |
create_index(collection, field) | collection name, field name | — |
list_collections() | — | JSON array of names |
drop_collection(name) | collection name | — |
dump() | — | JSON image string of the whole database |
restore(imageStr) | image from dump() | — |
persist_opfs() | — | Promise<void> — snapshot to OPFS |
load_opfs() | — | Promise<boolean> — restore from OPFS (false if none) |
clear_opfs() | — | Promise<void> — delete the OPFS snapshot |
# Prerequisites: Rust, wasm-pack
cargo install wasm-pack
# Clone and build
git clone https://github.com/parisxmas/OxiDB.git
cd OxiDB/oxidb-wasm
./build.sh
# Output in pkg/
persist_opfs() to snapshot to OPFS and load_opfs() to restore, so data survives page reloadsoxidb_wasm.d.ts)