@classytic/webdb-kit
v0.1.0
Published
IndexedDB repository kit built on @classytic/repo-core — the same repository contract as mongokit/sqlitekit, for local-first & browser-extension apps with no backend. Zero runtime deps, pluggable driver.
Readme
@classytic/webdb-kit
A small, typed IndexedDB repository kit for apps that keep useful data in the
browser. It implements the @classytic/repo-core contract, so local and server
repositories can share application code without making this package depend on
Arc, React, or a backend service.
Use only the subpaths you need. There is no root barrel and no bundled runtime dependency.
Good fits
- POS, field, and form apps that must keep working during a network outage
- browser extensions with structured, searchable data
- video, image, and document editors storing projects, timelines, drafts, thumbnails, and edit metadata
- local catalogs, queues, history, and larger client-side datasets
- tests or SSR using the matching in-memory driver
For a video editor, keep project state and smaller blobs in IndexedDB. Put very large source media in OPFS, the File System Access API, or another file store; do not force every video byte through the repository.
Why not localStorage?
| localStorage | IndexedDB through webdb-kit |
|---|---|
| synchronous and can block the UI | asynchronous |
| strings only | objects, arrays, dates, and blobs |
| no indexes or transactions | indexed queries and atomic transactions |
| best for a few preferences | better for records and offline application data |
Use localStorage for a theme or a handful of settings. Use this kit when the
browser data has records, indexes, pagination, migrations, or related writes.
Is it a Firebase replacement?
No. Firebase is a hosted backend with authentication, server data, realtime delivery, and managed synchronization. webdb-kit is a backend-neutral local database layer.
That narrower scope is useful when you want fast local reads, offline writes, no vendor lock-in, and the same repository contract as your server. A future or application-owned outbox can synchronize these local records with any backend. Automatic sync, authentication, conflict resolution, and collaborative CRDTs are intentionally not claimed by this package today.
Install
npm i @classytic/webdb-kit @classytic/repo-coreQuick start
import { openDatabase } from '@classytic/webdb-kit/database';
import { defineStore } from '@classytic/webdb-kit/schema';
type Product = {
id: string;
category: string;
name: string;
stock: number;
};
const products = defineStore<Product>({
name: 'products',
keyPath: 'id',
indexes: { category: {} },
});
const db = await openDatabase({
name: 'pos',
version: 1,
stores: [products],
});
const repo = db.repository(products);
await repo.create({ id: 'p1', category: 'food', name: 'Rice', stock: 12 });
await repo.update('p1', { stock: 11 });
const food = await repo.find({ category: 'food' });
const page = await repo.getAll({ sort: 'name', page: 1, limit: 20 });Use a transaction when related local writes must succeed or fail together:
await db.transaction([sales, pendingMutations], 'readwrite', async (tx) => {
await tx.add('sales', sale);
await tx.add('pending-mutations', mutation);
});Keep transaction callbacks database-only. Do not await network requests or timers inside them.
Optional cache and optimistic mutations
The /cache subpath adds a framework-independent memory cache, subscriptions,
stale-while-revalidate behavior, and optimistic repository writes with rollback.
It is separate from durable IndexedDB storage and is not loaded unless imported.
import {
createCachedRepository,
createWebQueryCache,
} from '@classytic/webdb-kit/cache';
const cache = createWebQueryCache({
defaults: { staleTime: 30, gcTime: 300, swr: true },
});
const cachedProducts = createCachedRepository(repo, cache, {
name: 'products',
});
await cachedProducts.update('p1', { stock: 10 });Subpaths
| Import | Purpose |
|---|---|
| @classytic/webdb-kit/database | open a database and run transactions |
| @classytic/webdb-kit/schema | define stores and indexes |
| @classytic/webdb-kit/repository | typed repository implementation |
| @classytic/webdb-kit/filter | portable filter matching |
| @classytic/webdb-kit/cache | optional SWR cache and optimistic writes |
| @classytic/webdb-kit/driver/memory | tests and SSR |
| @classytic/webdb-kit/driver/indexeddb | explicit browser driver |
| @classytic/webdb-kit/errors | stable error types and codes |
Schema changes use explicit versioned migrations. Indexed equality and range queries are pushed to IndexedDB when a matching index exists; other portable filters remain correct through in-memory matching.
Choose another tool when
- you only need a few preferences: use
localStorage - you need hosted auth, realtime server data, and managed sync: use Firebase, Supabase, or a similar backend
- you need collaborative editing: add a CRDT such as Yjs or Automerge
- you need SQL analytics or multi-gigabyte media storage: use a browser SQLite or OPFS-based solution
License
MIT
