4. Write the frontend app
Now the app, using the personal SDK. PersonalSdk is platform-agnostic
— it takes one adapter per enclave it declares (Personal + Group). We use the formalized
NetworkAdapter from @enc-protocol/client (codegen'd from the Lean spec): it does
plaintext signed writes and the ECDH session-authenticated reads the node requires.
npm config set @enc-protocol:registry https://npm-registry.ocrybit.workers.dev/
npm install @enc-protocol/personal-cli @enc-protocol/client @enc-protocol/protocol-runtimeenc-personal.mjs — wire the SDK to a node
// enc-personal.mjs
import { PersonalSdk } from '@enc-protocol/personal-cli'
import { flattenEnclaveManifest } from '@enc-protocol/protocol-runtime'
import { createIdentity } from '@enc-protocol/client'
import { NetworkAdapter } from '@enc-protocol/client/network-adapter.js'
export { createIdentity }
/** Build a PersonalSdk wired to a real node (mints the owner's enclaves). */
export async function createPersonalSdk({ nodeUrl, identity = createIdentity() }) {
const M = PersonalSdk.MANIFESTS
const adapters = {}
for (const name of M.app.enclaves) { // ['Personal', 'Group']
// the bundled enclave manifest → the wire RBAC manifest for this owner
const wire = flattenEnclaveManifest(M.enclaves[name]).enclaveManifest(identity.publicKeyHex)
const adapter = new NetworkAdapter(nodeUrl, '', identity)
await adapter.createEnclave(wire) // mint + wire the ECDH reader
adapters[name] = adapter
}
const sdk = new PersonalSdk({ adapters, identity: { pubHex: identity.publicKeyHex } })
await sdk.init()
return sdk
}app.mjs — the app
// app.mjs — NODE_URL=http://localhost:8787 node app.mjs
import { createPersonalSdk } from './enc-personal.mjs'
const sdk = await createPersonalSdk({ nodeUrl: process.env.NODE_URL || 'http://localhost:8787' })
await sdk.submitPublic({ draft: 'hello from my Personal app' })
await sdk.submitPrivate({ draft: 'a note only I can read' })
const posts = await sdk.queryPublic()
const notes = await sdk.queryPrivate()
console.log('public feed:')
for (const p of posts) console.log(' •', JSON.parse(p.content).draft)
console.log('private notes:')
for (const n of notes) console.log(' •', JSON.parse(n.content).draft)Run it (with the node from step 1 running):
$ NODE_URL=http://localhost:8787 node app.mjs
public feed:
• hello from my Personal app
private notes:
• a note only I can readThe NetworkAdapter mints the enclave, signs writes, and runs the ECDH session-authenticated
reads the node enforces — all from the formalized client SDK. Each query returns event
objects whose content is the JSON you wrote, so JSON.parse(p.content).draft reads the field
back.
Next: Write a test →