@@ -142,8 +142,7 @@ await ros.close(); // cancels subscriptions, closes both transports
142142
143143Today ** ` reconnect: true ` is accepted but ignored** (the SDK warns
144144once). If the server drops, the client is dead — ` connect() ` again
145- and re-` subscribe() ` . Auto-reconnect with resubscribe is on the
146- roadmap.
145+ and re-` subscribe() ` .
147146
148147## 6. End-to-end
149148
@@ -203,37 +202,74 @@ curl -sS -X POST http://localhost:9001/capability/call/dangerous \
203202
204203## 8. How it compares
205204
206- ` rclnodejs ` ships ** two** browser ↔ ROS 2 bridges, side-by-side
207- with the upstream ` rosbridge ` + ` roslibjs ` stack:
208-
209- | | ` rosocket ` | ** ` rclnodejs/web ` ** | ` rosbridge ` + ` roslibjs ` |
210- | --------------------------- | --------------------------------------- | -------------------------------------------------------------------- | ---------------------------------------- |
211- | ** Browser API** | Hand-rolled ` WebSocket + JSON ` | ` import { connect } from 'rclnodejs/web' ` | ` roslibjs ` |
212- | ** URL shape** | ` /topic/<name> ` , ` /service/<name> ` | ` /capability ` (WS) + ` POST /capability/{call,publish}/<name> ` (HTTP) | rosbridge protocol over WS |
213- | ** Public surface** | All listed topics/services | ** Required ` web.json ` allow-list** — a reviewable artifact | The whole ROS graph |
214- | ** TypeScript types** | ` any ` -shaped | Single string generic → request/response/message | ` any ` -shaped; bolt-on community packages |
215- | ** HTTP ` call ` / ` publish ` ** | ❌ | ✅ — ` curl ` , Postman, AI-agent tool-use just work | ❌ |
216- | ** Best for** | Quick prototypes, ` roslibjs ` -style apps | New apps, AI agents, typed UIs | Graph introspection, rqt-web, fleet UIs |
217-
218- ` rosocket ` and ` rclnodejs/web ` are ** siblings** , not layers — run as
219- separate processes on separate ports. ` rosbridge ` remains the right
220- choice when you genuinely need graph-shaped semantics (anything that
221- has to enumerate the live graph rather than work against a fixed
222- contract).
205+ The browser ↔ ROS 2 space already has ` rosbridge ` + ` roslibjs ` , and
206+ ` rclnodejs ` itself ships a second, lighter bridge called ` rosocket ` .
207+ All three speak to the same ROS graph — the differences live in ** the
208+ contract you sign with the browser** , not in transport tricks.
209+
210+ > 💡 ** Why we don't try to hide the ROS graph.** Robotics has no
211+ > stable equivalent to the web's URL/DOM/REST/SQL primitives, so any
212+ > attempt at a fully product-agnostic ` robot.navigate(...) ` style API
213+ > ends in unbounded capability explosion. All three options below
214+ > therefore keep the browser facing topics/services/actions
215+ > deliberately. The differentiator is the operational surface
216+ > _ around_ the graph (allow-list, types, transports, governance), not
217+ > a new frontend abstraction. ` robot.navigate() ` -style verbs belong
218+ > in the integrator's product layer on top of these.
219+
220+ ### Pick by the contract you want
221+
222+ | You want… | Use |
223+ | ------------------------------------------------------------------------------- | --------------------------------------------------------------------- |
224+ | ** A reviewable allow-list, typed SDK, and curl-able HTTP** for new browser apps | ** ` rclnodejs/web ` ** _ (this guide; default for new code)_ |
225+ | Live graph introspection / debug consoles / ` rqt ` -web / fleet topic discovery | ` rosbridge ` + ` roslibjs ` |
226+ | Hand-rolled ` WebSocket + JSON ` against a couple of named topics, no SDK at all | [ ` rosocket ` ] ( ../rosocket/ ) |
227+ | You already have a working ` roslibjs ` codebase with no migration pressure | Stay on ` rosbridge ` + ` roslibjs ` |
228+ | You need ROS 2 Actions | ` rosbridge ` + ` roslibjs ` _ (rclnodejs/web does not implement actions)_ |
229+
230+ ### Detailed matrix
231+
232+ | | ** ` rclnodejs/web ` ** _ (default)_ | [ ` rosocket ` ] ( ../rosocket/ ) | ` rosbridge ` + ` roslibjs ` |
233+ | --------------------------- | -------------------------------------------------------------------- | --------------------------------------- | ---------------------------------------------------------------- |
234+ | ** Public API surface** | ** ` web.json ` allow-list — reviewable artifact** | All listed topics/services | The whole live ROS graph |
235+ | ** Browser API** | ` import { connect } from 'rclnodejs/web' ` — typed, three verbs | Hand-rolled ` WebSocket + JSON ` | ` roslibjs ` |
236+ | ** TypeScript types** | Single string generic → request/response/message from generated maps | ` any ` -shaped | ` any ` ; bolt-on community packages |
237+ | ** Wire shape** | ` /capability ` (WS) + ` POST /capability/{call,publish}/<name> ` (HTTP) | ` /topic/<name> ` , ` /service/<name> ` (WS) | rosbridge protocol over WS |
238+ | ** HTTP ` call ` / ` publish ` ** | ✅ — ` curl ` , Postman, AI-agent tool-use just work | ❌ | ❌ |
239+ | ** Setup** | ` npx rclnodejs-web web.json ` | ` npx rosocket --topic … ` | ` apt install ros-<distro>-rosbridge-server ` + Python launch file |
240+ | ** Auth hooks** | ` verifyClient ` / ` verifyRequest ` per transport (today) | Connection-level | ` securityglobs ` plugin |
241+ | ** Mature / battle-tested** | New (2.0) | New (2.0) | 10+ years in production |
242+
243+ ### Sibling, not competitor: ` rosocket `
244+
245+ ` rosocket ` and ` rclnodejs/web ` ship in the ** same** rclnodejs package
246+ but are independent runtimes — different ports, different contracts,
247+ no shared state. Reach for ` rosocket ` when you genuinely just want
248+ "one named topic over a raw WebSocket"; reach for ` rclnodejs/web `
249+ when you want a typed SDK and a reviewable allow-list. Neither
250+ replaces the other.
251+
252+ ### Not a ` rosbridge ` replacement
253+
254+ ` rosbridge ` is still the right tool when the browser genuinely needs
255+ ** graph-shaped semantics** — enumerating live topics, building
256+ ` rqt ` -style debug UIs, fleet dashboards that have to discover what's
257+ running. ` rclnodejs/web ` deliberately gives that up in exchange for a
258+ narrow, declarative contract.
223259
224260## 9. Auth, HTTPS, Actions
225261
226262- ** HTTPS / ` wss:// ` .** The runtime speaks plain ` ws:// ` and
227263 ` http:// ` . Put nginx, Caddy, or any TLS proxy in front of
228264 ` rclnodejs-web ` ; clients then point at ` wss:// ` / ` https:// ` .
229- - ** Auth.** Today, gate at the connection level via the
265+ - ** Auth.** Gate at the connection level via the
230266 ` verifyClient(req) ` / ` verifyRequest(req) ` hooks on
231267 ` WebSocketTransport ` / ` HttpTransport ` (return ` false ` to reject
232- with a 401). Per-capability scopes are on the roadmap.
268+ with a 401).
233269- ** Browser ROS install?** No — the browser only ever speaks to the
234270 endpoint ` rclnodejs-web ` exposes.
235- - ** Actions.** Not yet — reserved as the ` action ` kind in the wire
236- protocol; coming in a follow-up release .
271+ - ** Actions.** Not implemented. Use ` rosbridge ` + ` roslibjs ` if you
272+ need ROS 2 Actions in the browser today .
237273
238274## See also
239275
0 commit comments