Rclnodejs 2.1: Native ESM for a Web-Native ROS 2 SDK

Hi all,

rclnodejs 2.1.0 is out — and it’s a step toward making rclnodejs a web-native SDK for ROS 2: a platform for bringing ROS 2 to the browser and the modern JavaScript ecosystem. With 2.1.0, the whole package is now native ESM, so building web dashboards, teleop UIs, and browser bridges on ROS 2 feels native to today’s web tooling — with the full ROS 2 runtime still underneath whenever you need real nodes.

TL;DR — 2.1.0 makes rclnodejs native ESM end-to-end. import rclnodejs from 'rclnodejs' just works, the browser SDK (rclnodejs/web) brings ROS 2 to the web, and existing require() nodes keep running untouched — the full ROS 2 runtime is still underneath.

:sparkles: A web-native SDK for ROS 2

  • ROS 2 on the web — reach ROS 2 from a web page with rclnodejs/web: typed APIs over WebSocket, no proxy, no codegen.
  • Native ESM — first-class import and top-level await, ready for Vite/esbuild and the modern web toolchain.
  • Full ROS 2 runtime underneath — real nodes, pub/sub, services, actions, parameters, lifecycle, whenever you need them.
  • Backward compatible — every existing CommonJS (require) project upgrades with zero code changes.

:package: One package, both module systems

// Modern Node / browser — ESM
import rclnodejs from 'rclnodejs';        // full ROS 2 node API
import { connect } from 'rclnodejs/web';  // typed browser SDK
// Existing CommonJS nodes — unchanged
const rclnodejs = require('rclnodejs');

:compass: Where this is heading

Each release moves rclnodejs one step closer to a typed, web-native way into ROS 2:

  • 2.0.0 :globe_with_meridians: — a typed browser SDK (rclnodejs/web) backed by a capability runtime that exposes only what web.json declares, with HTTP call / publish for non-JS clients.
  • 2.1.0 :high_voltage: — native ESM across the whole package, so rclnodejs sits naturally alongside the rest of your web stack.

The arc: from “a Node.js client that happens to run in browsers”“a typed, allow-listed Web SDK for ROS 2”

:wrench: Try it

npm i rclnodejs

Feedback welcome — especially from anyone wiring ROS 2 into web frontends. :raising_hands:

Cheers,
Minggang

1 Like

rclnodejs 2.1.1: SSE Support for Streaming Robot Data to the Web

rclnodejs 2.1.1 is out, adding Server-Sent Events (SSE) subscribe support to the web-native HTTP transport described above. Browsers can now stream live ROS 2 topic data with just the built-in EventSource API — no WebSocket, no SDK, no codegen.

Builds on 2.1.0’s native ESM and the rclnodejs/web HTTP transport from 2.0.0: same capability runtime, now with a subscribe path over SSE alongside the existing call/publish.

Streaming topics into the browser

# Terminal 1
# source /opt/ros/<distro>/setup.bash
ros2 run demo_nodes_cpp talker  # publishes /chatter
# Terminal 2
# source /opt/ros/<distro>/setup.bash
npx -p rclnodejs rclnodejs-web --port 9000 --http-port 9001 \
  --http-sse --http-cors '*' --subscribe /chatter=std_msgs/msg/String
// Browser — no SDK needed
const source = new EventSource(
  'http://localhost:9001/capability/subscribe/chatter'
);
source.addEventListener('message', (e) => console.log(JSON.parse(e.data)));

GET /capability/subscribe/<name> streams as text/event-stream; --http-cors lets cross-origin pages connect too, and --http-sse-keep-alive <ms> controls the heartbeat interval. Full walkthrough: demo/web/javascript/.

Useful anywhere you want live robot data outside a ROS-aware process — a browser dashboard showing topic data in real time, or an agent/LLM tool that subscribes to a topic over plain HTTP instead of speaking ROS 2 natively.

Feedback welcome.

Cheers,
Minggang

2 Likes

rclnodejs 2.2.0-beta.0: ROS 2 Capabilities as Discoverable, Agent-Ready OpenAPI 3.1 APIs

Your web.json allow-list can now describe itself: rclnodejs 2.2.0-beta.0 — the first preview of the 2.2 line — adds an openapi subcommand that emits a standard OpenAPI 3.1 document, so API explorers, codegen, and AI-agent tool-use all get a machine-readable description of your ROS 2 graph for free, no hand-written shim required.

Builds on the rclnodejs/web capability runtime from 2.0.0/2.1.1: the same call/publish/subscribe capabilities you already expose over WebSocket and HTTP, now also describable as one static JSON document.

Generating a document

source /opt/ros/<distro>/setup.bash
npx -p rclnodejs@2.2.0-beta.0 rclnodejs-web openapi web.json > openapi.json

Viewing the document in Swagger UI

The document is plain static JSON, so any OpenAPI viewer works — point Swagger UI at it (no server-side integration needed, just load openapi.json from a CDN build) to get a browsable, “try it out” API reference for your ROS 2 graph:

Full walkthrough: demo/web/javascript/.

Cheers,
Minggang

rclnodejs 2.2.0: Automatic Reconnection for the Web SDK

rclnodejs 2.2.0 is out. RosClient’s reconnect option is now implemented

import { connect } from 'rclnodejs/web';

const ros = await connect('ws://localhost:9000', { reconnect: true });
ros.on('disconnected', () => console.log('connection lost'));
ros.on('reconnecting', ({ attempt, delay }) => console.log(`retry ${attempt} in ${delay}ms`));
ros.on('reconnected', () => console.log('back online'));

Also new: OpenAPI 3.1 export + Swagger UI for the HTTP transport (previewed in 2.2.0-beta.0), and ROS 2 action-graph query APIs (countActionClients/countActionServers, ActionEndpointInfo).

Cheers,
Minggang

1 Like