Skip to content

How Nodelets works

Nodelets has three parts: a bridge beside the equipment, a cloud that serves the API, and the clients that call it.

The bridge is one Go program on a machine in the same network as the devices. It runs as a service on Linux or macOS. It holds its own private key, talks to devices through its two drivers, HTTP and MQTT, and keeps one connection open to the cloud, which it opened itself.

The bridge holds everything about how to reach each device: the definitions, each device’s base URL or broker, and any headers. These never leave the machine. The bridge forwards live values as they arrive and never stores readings.

The cloud handles accounts and sign-in, checks every credential and permission, routes each call to the right bridge, and serves the REST API, the WebSockets and the MCP endpoint.

For each device the cloud holds what the device can do: its properties, actions and events, with their schemas and the operations each one allows. It does not hold addresses, bindings or headers. Each Nodelet has its own object in the cloud, with its own identity, alongside a second object of the same ID that holds its saved readings and its record.

The cloud sees values and commands in plaintext as they pass through it.

  • The dashboard at https://dashboard.staging.nodelets.com manages the account: API keys, MCP connections, bridges, and each device’s record. Its Bridges page shows what each Nodelet can do, as a snapshot from when the page loaded. It shows no device values and cannot send commands.
  • Programs call the REST API and WebSocket with an API key.
  • AI clients connect over MCP with an approved connection.

A definition describes one kind of device. When the bridge publishes a device, the cloud makes it a Nodelet, and the same capabilities appear on every interface: as REST routes, as WebSocket subscriptions, as MCP tools and resources, and in a W3C Thing Description. One difference: MCP has no tool for events, which arrive on the WebSocket.

When a program reads the practice thermostat’s temperature:

  1. The program sends GET /nodelets/nl_.../properties/temperature with its API key.
  2. The cloud checks that the key is current, that the Nodelet belongs to the key’s account, and that a permission covers reading temperature. A failed check answers at once, and nothing goes further.
  3. The cloud checks that the definition binds a read for temperature, and passes the call to the router that holds the bridge’s connection.
  4. The router sends one thing.interact message down the bridge’s open connection, with a deadline.
  5. The bridge looks up the binding, GET /temperature with the pointer /temperature, and sends one request to the device’s base URL.
  6. The bridge takes the value at the pointer, checks it against the definition’s schema, and replies.
  7. The cloud checks the value again and returns it to the program.

A write follows the same path. It also adds an entry to the device’s record, first when it is sent and again when its result arrives.

For live values, the router asks the bridge to subscribe to a property, and the bridge holds a server-sent events stream open to the device. Each value travels up the same connection and the router forwards it to everyone watching.

The router also holds one subscription to every observable property of each Nodelet, whether or not anyone is watching. From that stream it saves readings at the spacing the account’s plan allows. A viewer attaches to the same subscription, so watching adds no load on the device.