MindooDB: End-to-End Encrypted Offline-First Database

0.0.17 · active · verified Wed Apr 22

MindooDB is an end-to-end encrypted, offline-first sync database designed for collaborative applications. It uniquely ensures that encryption keys never leave client devices, meaning servers only ever process and store ciphertext, providing a robust security model against server compromises and data breaches. Built on Automerge CRDTs, it offers real-time collaboration with automatic conflict resolution, tamperproof history, and fine-grained access control through named encryption keys. It functions by syncing content-addressed encrypted blobs, supporting peer-to-peer, client-server, or hybrid synchronization. The package is currently in alpha (`v0.0.17`), indicating active development but with APIs subject to change and it is not yet recommended for production use. Release cadence is irregular during this early development phase. Its key differentiator is the client-side encryption, allowing data control to remain solely with the end-users.

Common errors

Warnings

Install

Imports

Quickstart

This quickstart initializes MindooDB, creates a new end-to-end encrypted document, updates it, and then retrieves and decrypts the content, demonstrating basic client-side data operations without exposing plaintext to a server.

import { MindooDB, type MindooDocument } from 'mindoodb';

async function initializeAndUseMindooDB() {
  // IMPORTANT: For production, manage user passwords securely and do NOT hardcode.
  // This password is used to derive encryption keys for the user's data.
  const userPassword = process.env.MINDOODB_PASSWORD ?? 'secure-dev-password-123';
  const userId = 'my-unique-user-id'; // A unique identifier for the current user

  console.log('Initializing MindooDB...');

  // Instantiate MindooDB. In a real application, you'd configure a persistent
  // storage adapter (e.g., IndexedDB for web) and potentially a sync service.
  const db = new MindooDB({
    userId: userId,
    password: userPassword,
  });

  await db.init();
  console.log(`MindooDB initialized for user: ${userId}`);

  // 1. Create a new end-to-end encrypted document
  console.log('Creating a new document...');
  const newDocument: MindooDocument = await db.createDocument({
    type: 'secret-note',
    title: 'Top Secret Plan',
    content: 'Phase 1: Encrypt everything. Phase 2: Distribute. Phase 3: Profit.',
    tags: ['secret', 'plan', 'e2e']
  });
  console.log(`Document created with ID: ${newDocument.id}`);
  console.log('Initial document content (decrypted client-side):', newDocument.content);


  // 2. Update the document
  console.log('Updating the document...');
  await newDocument.update(currentDoc => {
    currentDoc.content = 'Phase 1: Encrypt everything. Phase 2: Securely distribute. Phase 3: Achieve peace.';
    return currentDoc;
  });
  console.log('Document updated.');

  // 3. Retrieve and verify the document
  console.log('Retrieving the document...');
  const retrievedDocument = await db.getDocument<MindooDocument>(newDocument.id);
  if (retrievedDocument) {
    console.log(`Retrieved document ID: ${retrievedDocument.id}`);
    console.log('Retrieved document title:', retrievedDocument.title);
    console.log('Retrieved document content (decrypted client-side):', retrievedDocument.content);
    console.log('This data was never exposed in plaintext to any server.');
  } else {
    console.error('Failed to retrieve document.');
  }

  // In a real scenario, you would connect to a sync server to exchange
  // encrypted changes with other clients, e.g., await db.sync();
}

initializeAndUseMindooDB().catch(console.error);

view raw JSON →