Skip to main content

Quickstart

This guide demonstrates how to build a passwordless notes application using nilDB.

We will be using secretvaults for private storage, MetaMask for identity, and Nillion's Network User Credentials (NUC) for secure, decentralized authentication.

What You'll Build​

In this quickstart, you'll create a simple notes app that requires login via MetaMask and learn:

  1. Builder setup: You (as a builder/application) will register for a Nillion API key
  2. Create a standard collection: Define a standard collection with an encrypted content field
  3. Wallet-scoped data storage: Store and manage a user's notes with create, read, update, and delete (CRUD) operations

This showcases Nillion's core value: builders can preserve privacy by default while storing data securely across multiple nilDB nodes.

What You'll Learn​

  • How builders create standard collections with encrypted fields
  • How users authenticate with MetaMask and get a DID-backed NUC session
  • How sessions persist via invocation tokens
  • How to use %share (schema) and %allot (write payload) correctly
  • How the @nillion/secretvaults library handles encryption and share distribution automatically

Code Reference​

  • The completed full tutorial code is here.

1. Prerequisites​

  • MetaMask browser extension and wallet
  • Node.js 20+ and pnpm

2. Project Setup​

Clone the demo repository.

git clone https://github.com/NillionNetwork/blind-module-examples
cd blind-module-examples/nildb/secretvaults-ts/standard-collection/nextjs-app-metamask-full
pnpm install
pnpm run dev

Project Structure​

src/
app/
layout.tsx
globals.css
page.tsx
profile/page.tsx
components/
Notes.tsx
ProtectedRoute.tsx
context/
AuthFlowManager.tsx
LogContext.tsx
NillionContext.tsx
NillionState.ts
hooks/
useBuilderProfileQuery.ts
useProfile.ts
useNillion.ts
usePersistedConnection.ts
useSessionQuery.ts
useInitializeSessionMutation.ts
useLoginMutation.ts
useNillionClient.ts
useNotesCollection.ts
useNotes.ts
config.ts

This is the project structure you'll use.

Config file​

This configuration is required to connect to the three nilDB nodes.

nildb/secretvaults-ts/standard-collection/nextjs-app-metamask-full/src/config.ts
loading...

3. MetaMask + Session Flow​

We subscribed to the nilPay platform using a MetaMask account, so now we want to sign in with that account. This requires interfacing with a web3 wallet and is primarily done in src/context/NillionContext.tsx.

We also use the viem library to detect and prove ownership of the account.

Key Concept:

Signer.fromWeb3() wraps MetaMask's signing capability so Nillion can use it for NUC token creation.

nildb/secretvaults-ts/standard-collection/nextjs-app-metamask-full/src/context/NillionContext.tsx
loading...

Relevant files:

src/hooks/useInitializeSessionMutation.ts:

  • initializeSession():
    • Checks subscriptionStatus
    • Builds SecretVaultBuilderClient.from({ blindfold: { operation: "store" } })
    • Mints per-node invocation tokens
    • Ensures builder profile exists (readProfile, then register if needed)
    • Returns { nillionClient, nildbTokens }.
    • On success, saves the session into React Query (["session"]) and persists tokens via usePersistedConnection.

src/context/AuthFlowManager.tsx

  • Decides whether to initialize or log in based on MetaMask connection and whether a stored session already exists.

src/hooks/useLoginMutation.ts

  • Rehydrates from localStorage (nildbTokens)
  • Reuses invocation tokens when available, otherwise mints fresh tokens
  • Ensures builder profile exists
  • Writes session back to React Query.

src/hooks/usePersistedConnection.ts

  • Persists connection state and session credentials in localStorage
  • Exposes hasStoredSession used by AuthFlowManager

Key concepts:

  • Invocation Tokens: Node-specific tokens (one per nilDB node)
  • Blindfold: Enables automatic encryption for %allot fields

4. Collection Creation (Standard Collection)​

Before storing notes, we need a standard collection with a schema.

  • In the schema, encrypted fields use %share
  • In write payloads, encrypted values use %allot
nildb/secretvaults-ts/standard-collection/nextjs-app-metamask-full/src/hooks/useNotesCollection.ts
loading...

5. Create, Read, Update, Delete (CRUD) Operations​

Key patterns

Notice how content is wrapped in { "%allot": value } when sending.

The SDK automatically:

  1. Detects the %allot marker
  2. Encrypts the value
  3. Splits it into secret shares
  4. Sends one share to each nilDB node

In this example:

  • Notes are written with createStandardData
  • Reads are filtered by walletAddress
  • Updates and deletes use _id filters on the same collection
nildb/secretvaults-ts/standard-collection/nextjs-app-metamask-full/src/hooks/useNotes.ts
loading...

6. UI Layout​

src/app/page.tsx:

  • useNillion() to connect to MetaMask, log out, and access state (address/DID)
  • useSessionQuery() to know when the session is ready
  • Displays authentication logs so users can follow session setup progress

src/app/profile/page.tsx:

  • Wrapped with <ProtectedRoute> to ensure only authenticated users can access.
  • Uses useProfile() to display builder profile details
  • Renders <Notes />, which is where CRUD happens

src/components/Notes.tsx:

  • Hook integration
    • Calls useNotes() which wires together:
      • useNotesCollection() (ensures/creates collection with encrypted content schema).
      • useNillionClient() (provides nillionClient + per-node tokens).
      • All CRUD operations
      • Encryption happens in the hook via ensureAllot() which wraps content as { "%allot": string }.

7. Running Your App​

After you run your app with pnpm run dev, open http://localhost:3000 and:

  1. Click "Connect with MetaMask"
  2. Approve the MetaMask connection
  3. Wait for session initialization
  4. Open the profile page
  5. Create a note - the content is automatically encrypted
  6. Refresh the page - your session persists
note

During session initialization, MetaMask may prompt you to sign 3 or more times. This is expected: nilDB uses per-node invocation authorization (typically one signature per node) in addition to the root session flow.


What Just Happened?​

🎉 Congratulations! You built a privacy-preserving notes app where:

  1. Users authenticate with MetaMask - no passwords needed
  2. A builder profile is created (or reused) automatically during session setup
  3. A standard notes collection is created (or reused) per wallet
  4. Note titles and wallet addresses stay plaintext for filtering/display
  5. Note content is encrypted and split into secret shares across nilDB nodes
  6. Sessions persist via per-node invocation tokens in localStorage
?

Were you able to complete the quickstart?

Advanced Features​

Query Operations​

// Create and run queries on encrypted data
const query = {
_id: randomUUID(),
name: 'Find Users by Name',
collection: collectionId,
variables: {
searchName: {
description: 'Name to search for',
path: '$.pipeline[0].$match.name',
},
},
pipeline: [{ $match: { name: '' } }, { $count: 'total' }],
};

await builder.createQuery(query);

OpenAPI​

You can access the OpenAPI specifications for any node by visiting the following URL pattern: https://{endpoint}/openapi.json, where {endpoint} is replaced with your specific node address. For instance, to view the API specs for the staging node, you would use: https://nildb-stg-n1.nillion.network/openapi.json.

Next Steps​

Now that you understand the basics of Nillion private storage, you can:

  • Explore more complex collection schemas
  • Implement query operations on encrypted data
  • Build applications that respect user privacy by default