A 60-second taste
Define a model and query it, all locally, no server. Then wire it into React and the list stays live.
@docstack/client
import { ClientStack, Class, Attribute } from '@docstack/client';
// A local database, with named transactions enabled.
const stack = await ClientStack.create('my-app', { transactions: true });
// A class is a schema, and a document.
const taskClass = await Class.create(stack, 'Task', 'class', 'User tasks');
await Attribute.create(taskClass, 'title', 'string', 'Title', { mandatory: true });
await Attribute.create(taskClass, 'priority', 'string', 'Priority');
await Attribute.create(taskClass, 'isComplete', 'boolean', 'Done?', { defaultValue: false });
await taskClass.add({ title: 'Install DocStack', priority: 'high' });
// SQL, against the browser's own storage.
const { rows } = await stack.query(
`SELECT title FROM Task WHERE priority = ? AND isComplete = false ORDER BY title`,
'high'
);
@docstack/react
import { StackProvider, useClassDocs } from '@docstack/react';
const App = () => (
<StackProvider config={[{ name: 'my-app', patches: SCHEMA }]}>
<TaskList />
</StackProvider>
);
const TaskList = () => {
// Re-renders whenever a Task changes, locally or arriving over sync.
const { docs, loading } = useClassDocs('my-app', 'Task');
if (loading) return <p>Loading…</p>;
return <ul>{docs.map(t => <li key={t._id}>{t.title}</li>)}</ul>;
};
Why DocStack
A document store with the things applications actually need, without giving up the offline-first, replication-friendly nature that made document stores worth using.
Offline-first by default
The database is embedded. No round trip for a read, a write, a validation or a join. Works on a plane, in a basement, on a train.
SQL in the browser
SELECT, JOIN, GROUP BY, subqueries, ORDER BY … LIMIT, with index pushdown and streaming scans. No hand-written map/reduce.
Logic as data
Triggers and jobs live in the database as documents. Update behaviour at runtime; it replicates with the rest.
Field-level encryption
Mark an attribute encrypted and it is ciphertext on disk and on the remote. Your sync target holds data it cannot read.
Access by scope
Content is sealed under an attribute formula. A session that does not satisfy it cannot produce the plaintext. Denial is decryption failure, not a check.
Bring-your-own-remote sync
stack.sync({ remote }) against any PouchDB-compatible database, including the user's own Google Drive. DocStack never learns about your provider.
Versioned schema patches
Migrations as declarative documents with a semver ledger: applied once, all-or-nothing, gated across devices so a trailing client cannot corrupt a leading one.
Named write transactions
Stage a multi-document change, read your own staged state, commit as one batch through the full pipeline, or discard it. Atomicity is reported, not assumed.
Live React bindings
Every hook subscribes to the local database. No refetching, no cache invalidation, no staleness story to own.
Who it's for
- Offline-first field and mobile apps. Data collection, point-of-sale, inspections, note-taking. Validation and business logic run without connectivity, and reconcile later.
- Serverless personal apps with user-owned backup. Sync to the user's own Drive. Multi-device sync and real backup with no server, no storage bill, and no custody of anyone's data.
- Privacy-sensitive and regulated data. Health notes, financial records, journals. Encrypted attributes are unreadable to the storage operator and to the sync remote.
- Multi-tenant products and internal tools. Each tenant gets a scope sealed under its attribute; one deployment serves many tenants while one tenant's devices can hold, but never read, another's data.
- Analytics and reporting surfaces. The SQL engine lets support staff and analysts query joined, filtered data without a bespoke reporting API.
Packages
@docstack/client
The engine: schema, SQL, triggers, jobs, encryption, patches, transactions, sync. Runs in the browser.
@docstack/pouchdb-adapter-googledrive
The user's own Google Drive folder as a PouchDB remote. Append-only log, lazy loading, multi-writer safe.
Workbench
Browse a database, edit its schema, run queries, view the entity-relation diagram. In the browser, no install.
Open the workbench@docstack/server
The same engine deployed server-side: a sync hub, shared workspaces, server-side jobs. Preview, not published.
What it is forPre-1.0 and moving. @docstack/client and @docstack/react are published and in production use; the workbench is an application you visit rather than install; @docstack/server is a preview of the same engine deployed server-side. Every decision behind the engine is recorded as an architecture decision record.