Nodofi Docs

Nodofi Detailed Handbook

A practical end-to-end guide that shows how to actually run Nodofi in real workflows, with concrete examples and copy-paste commands.

How to use this page: Follow sections in order for your first setup, then use the recipes at the end as a quick reference.

Overview

Nodofi has multiple runtime components. You can start small (Studio + one local Node) and grow into a production network (domain-backed Node, Relay, NVM services, CloudDB, and optional Robot Agent).

Most teams use this sequence:

  1. Run Studio locally.
  2. Run one Node and publish a test app.
  3. Request the app using Nodo JS APIs.
  4. Add payments (optional).
  5. Add Relay for reachability without direct inbound networking.
  6. Add NVM services for headless backend tasks.
  7. Add CloudDB for shared app/service data.

Architecture map

Studio (build/publish)
  -> Node (hosts app files + app API)
  -> Relay (optional reachability layer)
  -> NVM Service Manager (headless service runtime)
  -> CloudDB worker (shared data)
  -> MooChedda (USDC settlement + verification)
  -> Robot Agent (physical robot runtime, optional)

Key principle: payments settle wallet-to-wallet through MooChedda; infrastructure verifies payments but does not custody funds.

Quick local lab (about 15 minutes)

1. Start Studio

git clone <your repo>
cd BeezifiStudio
npm install
cp .env.example .env
# set DB_USER, DB_PASSWORD, DB_NAME, JWT_SECRET in .env
npm run db:init
npm start

Open http://localhost:3000, create your account, and open the Studio editor.

2. Start a local Node

cd desktop-node
npm install
npm start

Open http://localhost:8800. Copy the Node key from the admin page.

3. Create and publish a minimal app

function NODO_START() {
  document.body.innerHTML = '

Hello from Nodofi

My first published app is running.

'; }

In Studio: right click project -> Send to Node. Use http://localhost:8800 and paste the Node key for instant publish.

Publish an app (UI and API)

Studio UI path

  1. Right click a project -> Send to Node.
  2. Set Node address (URL or identity-based target).
  3. Optional: Node key for immediate live publish.
  4. Optional: list in node directory, icon, screenshots, price.

Equivalent API call

curl -s -X POST https://mainnet.yourdomain.com/api/apps \
  -H "Authorization: Bearer <node key>" \
  -H "Content-Type: application/json" \
  -d '{
    "uid": "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4",
    "name": "Weather Board",
    "version": "1.0.0",
    "files": [
      {"type":"html","name":"index.html","content":"<div id=\"app\"></div>"},
      {"type":"js","name":"app.js","content":"function NODO_START(){document.getElementById(\"app\").innerText=\"Online\";}"}
    ]
  }'

Reusing the same uid updates the existing app in place.

Request and run an app from any page

Basic web embedding pattern

<script src="https://mainnet.yourdomain.com/nodo.js"></script>
<div id="mount"></div>
<script>
  Nodo.load({
    node: 'https://mainnet.yourdomain.com',
    uid: 'a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4',
    mount: '#mount',
    watch: true
  });
</script>

When to use watch mode

SettingUse when
watch: trueYou are actively iterating in Studio and want open clients to refresh after republish.
watch: falseYou want deterministic behavior without live updates (typical production pages).

Payments and pricing examples

Set Node pricing policy

curl -s -X POST http://localhost:8800/admin/pricing \
  -H "Content-Type: application/json" \
  -H "X-Node-Admin: 1" \
  -d '{
    "wallet": "04...your MooChedda address...",
    "commissionRate": 0.15,
    "submissionFee": 2
  }'

Programmatic MooChedda payment verification

curl -s -X POST https://moochedda.com/transactions/verify \
  -H "Content-Type: application/json" \
  -d '{
    "fromAddress": "...",
    "toAddress": "...",
    "amount": 2,
    "tokenSymbol": "USDC",
    "timestamp": 1737111111111,
    "signature": "..."
  }'

Robust verification pattern:

  1. Validate signature locally first.
  2. Verify settlement via MooChedda API.
  3. Check amount, recipient, timestamp freshness, and replay status.

Relay setup pattern

Use Relay when nodes/services are behind NAT, no public domain, or no router control.

Minimum relay config

RELAY_PUBLIC_URL=https://relay.yourdomain.com
RELAY_NAME=My Relay
RELAY_OPERATOR=Your Org
REGISTRY_URL=https://registry.nodofi.com
# Optional paid access
# ACCESS_FEE_AMOUNT=2
# ACCESS_FEE_WALLET=04...wallet...
# ACCESS_FEE_PERIOD_DAYS=30

Three-step validation

curl -i https://relay.yourdomain.com/
curl -i "https://relay.yourdomain.com/socket.io/?EIO=4&transport=polling"
curl --http1.1 -i -N -H "Connection: Upgrade" -H "Upgrade: websocket" \
  -H "Sec-WebSocket-Version: 13" -H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" \
  "https://relay.yourdomain.com/socket.io/?EIO=4&transport=websocket"

Expected outcomes: health 200, polling handshake with sid payload, websocket 101.

NVM Service Manager pattern

Service entry template

async function AsyncNodoMain(input, callback) {
  const name = input && input.name ? input.name : 'world';
  callback({ ok: true, message: 'hello ' + name, at: new Date().toISOString() });
}

Call from another app/service

const out = await NodoRequestAsync({
  relay: 'https://relay.nodofi.com',
  recp: 'my-service-project-uid',
  data: { function: 'main', name: 'Nodofi' }
});
console.log(out);

Operational best practice: issue per-developer API keys in the Manager dashboard instead of sharing one global manager key.

CloudDB pattern

Public table CRUD

const db = new NodoCloudDB({
  project: PROJECT_UID,
  key: DATA_KEY,
  relay: 'https://relay.nodofi.com',
  worker: 'NodofiCloudDB'
});

const notes = db.table('notes');
const id = await notes.add({ title: 'first', done: false });
await notes.update(id, { done: true });
const rows = await notes.toArray();
await notes.delete(id);

Private table (wallet-scoped)

const vault = db.table('secrets', {
  private: true,
  wallet: {
    address: MY_MOOCHEDDA_ADDRESS,
    privateKey: MY_MOOCHEDDA_PRIVATE_KEY
  }
});
await vault.add({ secret: 'wallet-bound row' });
Important: Do not put permanent private keys in browser code for production apps. Route sensitive writes through trusted service-side code.

Robot Agent pattern

Minimal robot environment

RELAY_URL=https://relay.nodofi.com
ROBOT_NAME=my-robot-1
HARDWARE=auto
HEARTBEAT_TIMEOUT_MS=3000

Typical first-run flow

  1. Start robot agent and copy pairing key.
  2. In Studio Robot project, Add a robot with relay URL + robot name + key.
  3. Run tethered first, then deploy standalone after hardware validation.

Safety baseline

  • Use deploy mode only after confirming emergency STOP behavior.
  • For motors/propellers, remove load during first script tests.
  • Use isolated external power rails for motor drivers and servos.

Production checklist

AreaChecklist
TLSHTTPS with valid certificate for all public endpoints (Studio, Node, Relay, Manager admin domains).
ProxyWebSocket upgrade configured for Node and Relay; long read timeout for socket.io.
SecretsSet strong JWT_SECRET; keep key material out of public bundles; use dedicated service users.
BackupsBack up DB files/servers and config env files; test restore.
IdentitySet stable public addresses and register where needed (Registry, directories).
ObservabilityEnable service stats, keep logs, add uptime checks for health and websocket handshakes.

Troubleshooting matrix

SymptomLikely causeFirst fix
Node cannot connect via relayWebSocket upgrade blocked by proxyRe-check proxy websocket config and 101 test.
Custom domain verify failsResolver lag / negative DNS cacheValidate with public resolver and set DNS_SERVERS override.
Published app loads but does not runNo NODO_START in JSAdd entrypoint and republish same UID.
CloudDB writes failWrong project key or worker/relay mismatchConfirm key, relay, worker name, and project UID.
NVM publish deniedWrong API key or revoked keyGenerate new developer key in manager dashboard.
Robot parts show simulator-onlyMissing hardware libraryInstall required library and restart agent.

Copy-paste recipes

Recipe A: local sandbox (Studio + Node only)

# terminal 1
cd BeezifiStudio
npm install
npm run db:init
npm start

# terminal 2
cd desktop-node
npm install
npm start

Recipe B: relay-backed topology

Studio (public)
  uses relay: https://relay.yourdomain.com
Node (private/home network)
  outbound connects to same relay
NVM Manager (private)
  outbound connects to same relay
CloudDB worker (private or public)
  outbound connects to same relay

Recipe C: pricing-ready node

1) Configure payout wallet in node admin.
2) Set commission rate (0 to 0.5).
3) Optionally set submission fee.
4) In Studio publish dialog, set app price + payout wallet.
5) Verify purchase unlock flow from App Browser.