The decentralised backend for web apps.
Caution
Research Preview -- Not Production Ready
Enbox is under heavy, active development. You should expect:
- Breaking API changes without prior deprecation
- Data loss -- preview DWN servers may be wiped at any time
- Security gaps -- the codebase has not been audited; do not store sensitive data
- Missing documentation -- some features are undocumented or partially documented
We are not yet accepting external contributions. If you build on Enbox today, pin your dependencies and be prepared to adapt. This notice will be removed when Enbox reaches a stable release.
An open-source TypeScript SDK for building apps on Decentralized Web Nodes (DWNs). You get typed schemas, real-time subscriptions, queries, and end-to-end encryption -- but instead of a centralised database, every user gets their own encrypted personal datastore that syncs across devices and apps.
DWN is an open standard maintained by the Decentralized Identity Foundation. Anyone can run a DWN server, and any app that speaks the same protocol can interoperate. Enbox provides the tooling to build on that standard: an SDK, an agent framework, a server implementation, and the cryptographic primitives underneath.
| Centralised backend | DWN-based (Enbox) | |
|---|---|---|
| Data ownership | Provider holds all user data | Each user controls their own node |
| Auth | Email/password, OAuth providers | Decentralized Identifiers (DIDs) + seed phrase recovery |
| Schema | SQL tables, document collections | Protocol definitions (declarative, portable across apps) |
| Real-time | Server-pushed change feeds | DWN subscriptions (LiveQuery) |
| Encryption | At-rest, server-side | End-to-end (two-layer: vault + record-level JWE) |
| Hosting | Managed cloud, single vendor | Run your own server, use a community node, or both |
| Lock-in | Data lives in the provider's infra | Data follows the user -- switch apps without losing anything |
bun add @enbox/apiCreate an Enbox instance. Data syncs to whatever DWN endpoint(s) you configure -- a community node, your own, or both.
import { Enbox, defineProtocol } from '@enbox/api';
const { enbox } = await Enbox.connect({
dwnEndpoints : ['https://enbox-dwn.fly.dev'], // ← any DWN server
createIdentity : true,
});Protocols are declarative schemas -- they describe record types, nesting, access rules, and encryption. Any app that installs the same protocol can read and write the same record shapes.
const BookmarkProtocol = defineProtocol({
protocol : 'https://example.com/bookmarks',
published : false,
types : {
folder: {
schema : 'https://example.com/schemas/folder',
dataFormats : ['application/json'],
},
bookmark: {
schema : 'https://example.com/schemas/bookmark',
dataFormats : ['application/json'],
encryptionRequired : true, // ← end-to-end encrypted at the DWN layer
},
},
structure: {
folder: {
$tags : { name: { type: 'string' } }, // queryable server-side
bookmark : {}, // bookmarks nest under folders
},
},
} as const, {} as {
folder: { name: string };
bookmark: { url: string; title: string; note?: string };
});const bookmarks = enbox.using(BookmarkProtocol);
await bookmarks.configure(); // install the protocol on the user's DWN
// Create a folder
const { record: folder } = await bookmarks.records.create('folder', {
data : { name: 'Reading List' },
tags : { name: 'Reading List' },
});
// Add a bookmark (nested under the folder, encrypted automatically)
await bookmarks.records.create('bookmark', {
parentContextId : folder.contextId,
data : { url: 'https://example.com', title: 'Example', note: 'Check later' },
});
// Query all folders
const { records: folders } = await bookmarks.records.query('folder');
for (const f of folders) {
const data = await f.data.json(); // { name: string }
console.log(data.name);
}const { subscription } = await bookmarks.subscribe();
subscription.on('change', () => {
// Re-query or refresh your UI -- changes sync across devices in real time
});For browser apps, @enbox/browser re-exports everything from @enbox/api and @enbox/auth in a single import plus browser-specific helpers (BrowserConnectHandler, wallet-connect, DRL polyfills).
See the @enbox/api README for the full API: repository() helper, singletons, pagination, permissions, and more.
Your app talks to a local DWN running in the browser or on the device. The agent syncs encrypted messages to one or more remote DWN servers over HTTP/WebSocket. The remote server stores ciphertext -- it cannot read the data. Other devices and apps sync from the same remote node, staying in sync automatically.
Agent -- manages DIDs, cryptographic keys, and an encrypted identity vault derived from a 12-word BIP-39 seed phrase. Syncs data between the local DWN and any remote DWN server the user has configured.
DWN -- an open-standard personal datastore governed by protocols: declarative schemas that define record types, access control, and encryption rules. Each user controls their own node. The server is interchangeable -- run by you, the user, a community operator, or all three.
Two-layer encryption -- (1) a user password encrypts the agent's identity as AES-256-GCM JWE via PBKDF2. (2) Protocol types with encryptionRequired: true are encrypted with ECDH-ES+A256KW key agreement using the tenant's X25519 key. Recovery requires only the seed phrase.
Alice's app resolves Bob's DID to discover the DWN service endpoint in his DID document, then sends an encrypted record directly to Bob's DWN. Bob's app picks it up on the next sync. No relay, no shared database, no account on Alice's service -- just two DIDs and a protocol they both understand.
A DWN server is a multi-tenant node that stores and relays messages on behalf of users. Anyone can run one -- it's just an HTTP/WebSocket server backed by a database. There is no central authority; users can point their DID at any server (or several).
We run two preview nodes for development and testing. They are free to use but come with no uptime, data persistence, or security guarantees:
| Node | URL | Notes |
|---|---|---|
| Fly.io | https://enbox-dwn.fly.dev |
SQLite-backed, single region |
| AWS | https://dev.aws.dwn.enbox.id |
Aurora PostgreSQL, us-east-1 |
Set DWN endpoints when creating the auth manager, or override per-identity:
import { AuthManager } from '@enbox/auth';
// Default for all identities created through this manager
const auth = await AuthManager.create({
dwnEndpoints: [
'https://enbox-dwn.fly.dev',
'https://dev.aws.dwn.enbox.id',
],
});
// Or override for a specific identity
const session = await auth.connectVault({
dwnEndpoints : ['https://eu.dwn.example.com'],
createIdentity: true,
});Check server health:
curl https://enbox-dwn.fly.dev/health
curl https://dev.aws.dwn.enbox.id/healthThe @enbox/dwn-server package is a production-ready DWN server that runs anywhere Docker does. It supports PostgreSQL, SQLite, and MySQL for storage, with optional S3 for large blobs.
# Quick start with Docker Compose
git clone https://github.com/enboxorg/enbox.git
cd enbox
docker compose up dwn-serverThen point your app at it:
const auth = await AuthManager.create({
dwnEndpoints: ['https://dwn.your-domain.com'],
});See docs/HOSTING.md for the full deployment guide: Docker Compose configuration, environment variables, production checklist, Fly.io one-click deploy, and AWS ECS setup.
| Package | npm | What it does |
|---|---|---|
@enbox/api |
Start here. Web5.connect(), typed protocols, queries, subscriptions |
|
@enbox/auth |
Auth manager: local connect, wallet-connect, session restore | |
@enbox/browser |
Browser SDK: Enbox.connect(), polyfills, repository() helper |
|
@enbox/protocols |
Pre-built protocol definitions with JSON Schemas | |
@enbox/protocol-codegen |
CLI to generate TypeScript types from protocol definitions |
| Package | npm | What it does |
|---|---|---|
@enbox/agent |
Identity vault, key management, DWN sync engine | |
@enbox/dids |
DID methods (did:dht, did:jwk, did:web), resolution |
|
@enbox/crypto |
Ed25519, X25519, secp256k1, AES, PBKDF2, JWE | |
@enbox/common |
Shared utilities: TtlCache, LevelStore, data conversion |
| Package | npm | What it does |
|---|---|---|
@enbox/dwn-sdk-js |
DWN protocol engine, message handlers, storage interfaces | |
@enbox/dwn-clients |
DWN client libraries, JSON-RPC transport | |
@enbox/dwn-server |
Multi-tenant DWN server (HTTP/WS via Bun.serve) | |
@enbox/dwn-sql-store |
SQL-backed storage (PostgreSQL, SQLite, MySQL) | |
@enbox/dwn-relay |
-- | DWN relay/cache node (standalone repo) |
- Bun >= 1.0
git clone https://github.com/enboxorg/enbox.git
cd enbox
bun install
bun run buildbun run build # Build all packages
bun run test:node # Run all tests
bun run lint # Lint all packages
bun run --filter @enbox/agent build # Build a single packageSeveral packages require Docker services (Pkarr relay, PostgreSQL, NATS) and a local DWN server for their full test suites.
docker compose -f docker-compose.test.yaml up -d --wait
export DID_DHT_GATEWAY_URI=http://localhost:7527
bun run test:nodeSee docs/TESTING.md for the complete testing guide. See GETTING_STARTED.md for a detailed development walkthrough.
| Package | Coverage |
|---|---|
@enbox/api |
|
@enbox/agent |
|
@enbox/common |
|
@enbox/crypto |
|
@enbox/dids |
|
@enbox/dwn-sdk-js |
|
@enbox/dwn-server |
|
@enbox/dwn-sql-store |
Chromium, Firefox, and WebKit are tested via Playwright. Build targets: Chrome 101+, Firefox 108+, Safari 16+.
Packages are published to npm via Changesets. Never bump versions manually -- run bun changeset, then CI handles the rest.
If you discover a security vulnerability, please report it responsibly. Do not open a public issue. Email security@enboxorg.com with details. We will acknowledge receipt within 48 hours.
Enbox is a research preview under heavy development. APIs will change without notice. We are not yet accepting external contributions -- watch the repo for updates.
- Decentralized Web Node Specification
- DID Core Specification
- Enbox Documentation (work in progress)
- Hosting Guide
This monorepo consolidates packages from the decentralized-identity organisation, including dwn-sdk-js, dwn-server, dwn-sql-store, and the web5-js monorepo.