SQLite for the browser with real-time sync. Build offline-first apps that work across tabs and devices.
- Offline-first - Full SQLite database in the browser via sql.js
- Real-time sync - Optional network sync via Modu Network
- Cross-tab sync - Changes sync instantly across browser tabs
- Conflict resolution - Automatic rollback and replay when operation order differs
- Persistent storage - Database persists to localStorage
- Simple API - Familiar SQL queries with typed results
npm install modu-sqlimport { ModuSQL } from 'modu-sql';
const db = new ModuSQL({
dbName: 'my-app',
roomId: 'shared-room'
});
// Initialize (local only)
await db.init();
// Define schema
db.createTable({
name: 'todos',
columns: [
{ name: 'id', type: 'TEXT' },
{ name: 'title', type: 'TEXT' },
{ name: 'completed', type: 'INTEGER', default: 0 }
],
primaryKey: 'id'
});
// CRUD operations
db.insert('todos', { id: '1', title: 'Buy milk', completed: 0 });
db.update('todos', { completed: 1 }, { id: '1' });
db.delete('todos', { id: '1' });
// Query with SQL
const result = db.query<Todo>('SELECT * FROM todos WHERE completed = 0');
console.log(result.rows);Enable real-time sync across devices with Modu Network:
import { ModuSQL } from 'modu-sql';
import { ModuNetwork } from 'modd-network';
const db = new ModuSQL({
dbName: 'my-app',
roomId: 'shared-room'
});
await db.init(ModuNetwork, 'ws://localhost:8001/ws', {
onRoomCreate: () => {
console.log('Room created - you are the authority');
},
onConnect: (snapshot, operations) => {
console.log(`Connected, received ${operations.length} operations`);
renderUI();
},
onInput: (operation) => {
console.log('Remote operation:', operation.type, operation.table);
renderUI();
},
onDisconnect: () => {
console.log('Disconnected - working offline');
}
});new ModuSQL(config?: ModuSQLConfig)| Option | Type | Description |
|---|---|---|
dbName |
string |
Database name for localStorage persistence (default: 'modusql') |
roomId |
string |
Room ID for network sync |
Initialize the database. Optionally connect to network for sync.
Create a table with the given schema.
db.createTable({
name: 'users',
columns: [
{ name: 'id', type: 'TEXT' },
{ name: 'email', type: 'TEXT', nullable: false },
{ name: 'created_at', type: 'INTEGER', default: 0 }
],
primaryKey: 'id'
});Column types: TEXT, INTEGER, REAL, BLOB
Insert a row.
Update rows matching the where clause.
Delete rows matching the where clause.
Execute a SQL query and return typed results.
const result = db.query<User>('SELECT * FROM users WHERE email = ?', ['user@example.com']);
console.log(result.rows); // User[]Disconnect and close the database.
| Property | Type | Description |
|---|---|---|
id |
string |
Unique client ID (persisted across sessions) |
isOnline |
boolean |
Whether connected to network |
pendingCount |
number |
Number of unconfirmed operations |
ModuSQL uses an authority-based sync model:
- Local operations are applied immediately (optimistic updates)
- Operations are sent to the authority node which assigns sequence numbers
- Authority broadcasts operations to all clients in deterministic order
- Clients apply operations and rollback/replay if order differs from optimistic
This ensures all clients converge to the same state while maintaining responsiveness.
MIT