Skip to content

Quickstart

This content is for the 0.2.0-alpha.3 version. Switch to the latest version for up-to-date documentation.

This walks you from install to a working, end-to-end-encrypted feature in about five minutes. You’ll create a client, sign a user in with zero-knowledge auth, and store + read encrypted data.

  1. Install the SDK.

    npm install @muhkoo/connect

    The ZK login proof needs snarkjs at runtime — it’s an optional peer dependency, loaded lazily only when a user signs in. Add it if your app does logins:

    Terminal window
    npm install snarkjs
  2. Create a client.

    src/muhkoo.ts
    import { Client } from "@muhkoo/connect";
    export const client = new Client({
    apiKey: "mk_live_pk_…", // your app key — mk_live_pk_… or mk_test_pk_…
    // baseUrl defaults to the hosted accelerator; override only for staging / self-hosting.
    });
  3. Register and sign a user in.

    Identity is derived from (username, password) on the device — the password never leaves the browser.

    // First-time users:
    await client.auth.zk.register({
    username: "ada",
    password: "correct horse battery staple",
    email: "ada@example.com", // optional
    });
    // Returning users:
    const user = await client.auth.zk.login("ada", "correct horse battery staple");
    console.log(user); // { username: "ada", commitment: "…" }
  4. Store some encrypted data.

    set(collection, id, value) seals the value before it leaves the device. The server stores ciphertext.

    await client.storage.set("todos", "t1", { title: "Ship docs", done: false });
    const todo = await client.storage.get<{ title: string; done: boolean }>("todos", "t1");
    // └ { title: "Ship docs", done: false } (decrypted locally)
    const ids = await client.storage.list("todos"); // ["t1"]
  5. Send a realtime message.

    // End-to-end-encrypted direct message:
    await client.message.send("user:grace", { text: "Hello 👋" });
    // The recipient subscribes to their own id to receive DMs:
    client.message.subscribe("user:ada", (e) => {
    console.log("from", e.from, ":", e.data);
    });
App.tsx
import { client } from "./muhkoo";
async function signInAndLoad(username: string, password: string) {
const user = await client.auth.zk.login(username, password);
// Live-update the UI as todos change across the user's devices.
client.storage.on("change", (e) => {
if (e.collection === "todos") render();
});
return client.storage.list("todos");
}