ctrodb 1.4: Offline Sync for the Browser, Zero Dependencies

ctrodb is a client-side database for TypeScript. Schema validation, MongoDB-like queries, full-text search, relations — all in about 8KB gzipped with zero runtime dependencies. v1.4 is the biggest release yet. It adds offline sync. npm install ctrodb GitHub: github.com/ctrotech-tutor/ctrodb ctrodb.vercel.app/docs Sync engine with change tracking. Every create, update, and delete is recorded in a local change log and pushed to your server when connectivity returns. import { Database, syncPlugin,
ctrodb is a client-side database for TypeScript. Schema validation, MongoDB-like queries, full-text search, relations — all in about 8KB gzipped with zero runtime dependencies.
v1.4 is the biggest release yet. It adds offline sync.
npm install ctrodb
Enter fullscreen mode Exit fullscreen mode
GitHub: github.com/ctrotech-tutor/ctrodb
Docs: ctrodb.vercel.app/docs
What's in v1.4
Sync engine with change tracking. Every create, update, and delete is recorded in a local change log and pushed to your server when connectivity returns.
import { Database, syncPlugin, HttpTransport } from "ctrodb"
const transport = new HttpTransport({
url: "https://api.myapp.com/sync",
})
const db = new Database({
name: "my-app",
schema: { ... },
plugins: [syncPlugin({ transport })],
})
await db.connect()
Enter fullscreen mode Exit fullscreen mode
Three conflict strategies out of the box — last-write-wins, client-wins, server-wins — plus a custom resolver hook. Field-level merge isn't built in as a strategy but you can implement it in the custom resolver.
const db = new Database({
name: "my-app",
schema: { ... },
plugins: [syncPlugin({
transport,
strategy: "custom",
conflictResolver: (conflict) => {
return { resolution: "merged", merged: { ...conflict.local, ...conflict.remote } }
},
})],
})
Enter fullscreen mode Exit fullscreen mode
HTTP transport works with any backend. WebSocket transport for real-time push. Trigger sync manually, on interval, or let the auto-sync handle it.
await db.sync()
Enter fullscreen mode Exit fullscreen mode
React hooks for sync status and queue inspection:
import { useSyncStatus, useSyncQueue } from "ctrodb/react"
function SyncIndicator() {
const { isSyncing, pendingChanges } = useSyncStatus()
if (isSyncing) return <span>Syncing...</span>
if (pendingChanges > 0) return <span>{pendingChanges} pending</span>
return <span>All changes saved</span>
}
Enter fullscreen mode Exit fullscreen mode
Devtools component for debugging:
import { SyncDevPanel } from "ctrodb/react"
// Shows queue, event log, manual sync trigger
if (import.meta.env.DEV) <SyncDevPanel />
Enter fullscreen mode Exit fullscreen mode
Devtools utilities — inspect, retry, compact, stats — all take the database instance:
import { inspectSyncQueue, retryFailedSync, getSyncStats, compactSyncQueue } from "ctrodb"
const queue = await inspectSyncQueue(db)
const stats = await getSyncStats(db)
await retryFailedSync(db)
Enter fullscreen mode Exit fullscreen mode
What else
- New
useDochook for single-record subscriptions -
useSynchook for manual sync control with event callbacks -
DatabaseProviderfor React context - Custom adapter support
- CDN usage (IIFE build in npm package)
Links
- npm:
npm install ctrodb - GitHub: github.com/ctrotech-tutor/ctrodb
- Quick start: ctrodb.vercel.app/docs/getting-started/quick-start
- Sync docs: ctrodb.vercel.app/docs/sync/overview
- React setup: ctrodb.vercel.app/docs/react/setup
- API reference: ctrodb.vercel.app/docs/api-reference/database
Zero dependencies. Runs in the browser and Node.js. MIT license.



