npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@nanobpm/nano-ide-trigger-mqtt

v1.0.0

Published

MQTT trigger source pack for the Nano/Urban RAD console: subscribe to broker topics and drive process instances from messages (ADR 0025).

Readme

MQTT trigger — @nanobpm/nano-ide-trigger-mqtt

Turn any MQTT message into a running process. Subscribe to a broker topic and let each message start a process or correlate into a running one — the "when this happens…" half of a Zapier-style automation, for your own apps.

This is a pack on the nano-ide-trigger-* marketplace axis for the Nano / Urban RAD console. Installing it adds a new trigger source kindmqtt — that any App can declare. The pack ships a small out-of-process driver that the runtime auto-launches and supervises; the driver only produces events, and the runtime owns the durable inbox, dispatch, retry, and lifecycle (ADR 0025).

Why you'd want it

MQTT is the lingua franca of IoT and home automation. With this pack an Urban App can react to anything that speaks MQTT:

  • Home automation — Home Assistant, Zigbee2MQTT, Tasmota, ESPHome, Shelly… a door opens, a sensor crosses a threshold, a button is pressed → kick off a process.
  • Industrial / edge — PLCs and gateways publishing telemetry over MQTT/MQTTS.
  • Your own devices — an ESP32 publishing { "value": 21.4 } becomes a typed event your process reasons about.

Install

Install it into your Urban workspace's extensions like any other pack — from the console Extensions marketplace (search "MQTT"), or from the CLI:

c8ctl load plugin @nanobpm/nano-ide-trigger-mqtt

Once installed, mqtt shows up as a recognised source kind in the console Triggers panel, and you can declare triggers of type: "mqtt".

Use it in an App

Declare a trigger of type mqtt in your nano.app.json:

{
  "triggers": [
    {
      "id": "room-temp",
      "type": "mqtt",
      "config": {
        "url": "mqtt://localhost:1883",
        "topics": "home/+/temperature",
        "qos": "1"
      },
      "connection": "broker",
      "action": {
        "start": "handle-reading",
        "variables": "{ room: split(body.topic, \"/\")[2], celsius: body.payload.value }"
      }
    }
  ],
  "connections": {
    "broker": {
      "type": "mqtt",
      "username": "{{ env.MQTT_USER }}",
      "password": "{{ env.MQTT_PASS }}"
    }
  }
}

Each received message is delivered to the App as the event body:

{
  "topic": "home/kitchen/temperature",
  "payload": { "value": 21.4 },
  "ts": "2026-07-24T00:00:00.000Z"
}
  • topic — the concrete topic the message arrived on (wildcards resolved).
  • payload — the message payload parsed as JSON when possible, else the raw UTF-8 string.
  • ts — ISO-8601 receive time.

Reference these in the action's FEEL (variables / correlationKey), e.g. body.payload.value, split(body.topic, "/")[2].

Configuration

| field | required | default | notes | | --- | --- | --- | --- | | url | yes* | mqtt://localhost:1883 | Broker URL. Schemes: mqtt://, mqtts:// (TLS), ws://, wss://. A connection.url overrides this. | | topics | yes | — | Topic filter(s) to subscribe to. Comma-separate several. MQTT wildcards + (single level) and # (multi level) are allowed, e.g. home/+/temperature, sensors/#. | | qos | no | 1 | Subscription QoS: 0 (at most once), 1 (at least once), 2 (exactly once). |

* A broker URL is required, but it may come from either config.url or the referenced connection.url.

Credentials

Put credentials in a connections[] entry (referenced by the trigger's connection), never inline in config — secrets should be env templates ({{ env.VAR }}) the host resolves. The connection object may supply:

| key | notes | | --- | --- | | url | Broker URL; overrides config.url. | | username / password | Broker credentials. | | clientId | Fixed MQTT client id (otherwise the library picks one). |

Delivery semantics

The driver POSTs every received message to the trigger ingress with a stable idempotency key, and the runtime's inbox is at-least-once: a message that is briefly un-POSTable (ingress hiccup) is retried with backoff, and a retried delivery is collapsed rather than double-processed. Design your process actions to tolerate the occasional duplicate (idempotent starts / correlation keys).

MQTT itself only redelivers retained messages on reconnect; live messages published while the driver was down are not replayed.

How it runs

The runtime launches driver.ts as a supervised child process — Node ≥ 22.6 with --experimental-strip-types (the default), or Deno — passing the trigger's context in the environment:

| env var | value | | --- | --- | | NANOBPMN_HOOK_URL | the ingress endpoint the driver POSTs events to | | NANOBPMN_TRIGGER_CONFIG | JSON of the trigger's config | | NANOBPMN_TRIGGER_CONNECTION | JSON of the referenced connection, or null | | NANOBPMN_WEBHOOK_TOKEN | shared secret presented as X-Webhook-Token (if the trigger sets auth) | | NANOBPMN_PROJECT / NANOBPMN_TRIGGER_ID / NANOBPMN_TRIGGER_TYPE | identity, for logs |

On crash the driver is restarted with capped backoff; on App stop it receives SIGTERM and disconnects cleanly. Its stdout/stderr stream into the App's trigger log, so [mqtt] connected / subscribed / errors are visible in the console.

Troubleshooting

  • No events arriving — check the App's trigger log for [mqtt] connected and [mqtt] subscribed: <topic>@<qos>. If you see reconnecting… in a loop, the broker URL or credentials are wrong.
  • no topics configured — set config.topics (comma-separated); the driver refuses to start without at least one.
  • ingress rejected event (401/403) — the trigger declares an auth secret but the env var it names is unset or mismatched.
  • Payload arrives as a string, not an object — the message wasn't valid JSON; body.payload is then the raw text. Publish JSON to get a structured object.

License

Apache-2.0.