Skip to main content

JavaScript SDK & Web Apps

Reachy Mini supports full JavaScript web apps that run entirely in the browser. No install, no server, no Python — just open a URL and control your robot from any device, including your phone.

Why Web Apps?

The Python SDK is powerful but requires installation, GStreamer dependencies, and a capable machine. Web apps take a different approach:

  • Zero install — open a link, you're in. Save disk space and setup time.
  • Cross-platform — works on any device with a browser: laptop, tablet, phone.
  • Run from anywhere — control your robot from the other side of the world.
  • Leverage device hardware — use your phone's microphone, speakers, and touchscreen.
  • Instant sharing — send someone a link, they can use the app immediately.

Web apps are deployed as static Hugging Face Spaces (sdk: static). There is no server-side code — the browser connects directly to the robot over WebRTC via a central signaling server.

Python apps are not going away. Web apps are a complementary option, especially suited for lightweight control, remote access, and quick demos.

Architecture

┌─────────────────────────────────┐
│ Browser │
│ (your app + reachy-mini.js) │
└───────┬────────────┬────────────┘
│ SSE/HTTP │ WebRTC (peer-to-peer)
│ signaling │ video + audio + data
┌───────▼──────┐ │
│ Signaling │ │
│ Server │ │
│ (HF Space) │ │
└───────┬──────┘ │
│ │
┌───────▼────────────▼────────────┐
│ Robot │
│ GStreamer WebRTC daemon │
│ camera · mic · motors │
└─────────────────────────────────┘
  1. Your app is a static HTML/JS page hosted on Hugging Face Spaces.
  2. reachy-mini.js handles authentication, signaling, and WebRTC negotiation.
  3. The signaling server relays SDP offers/answers and ICE candidates. It also validates Hugging Face OAuth tokens.
  4. Once the WebRTC connection is established, video, audio, and commands flow peer-to-peer — the signaling server is no longer in the path.

Quick Start

1. Create a Hugging Face Space

Create a new Space on huggingface.co with sdk: static.

Your README.md front matter should look like:

---
title: My Reachy Mini App
emoji: 🤖
sdk: static
pinned: false
hf_oauth: true
hf_oauth_expiration_minutes: 480
---

hf_oauth: true is required — it enables the Hugging Face login button that the signaling server uses for authentication.

2. Add the SDK

In your index.html, import the SDK as an ES module:

<script type="module">
import { ReachyMini } from "./reachy-mini.js";

const robot = new ReachyMini();
</script>

You can grab reachy-mini.js from the reference example or from the npm CDN:

import { ReachyMini } from "https://cdn.jsdelivr.net/npm/@anthropic-robotics/reachy-mini/+esm";

3. Connect to your robot

// Authenticate with Hugging Face
if (!await robot.authenticate()) {
robot.login(); // redirects to HF login page
return;
}

// Connect to the signaling server
await robot.connect();

// Wait for robots to appear
robot.addEventListener("robotsChanged", (e) => {
const robots = e.detail.robots;
console.log("Available robots:", robots);
});

// Start a session with a specific robot
const detach = robot.attachVideo(document.querySelector("video"));
await robot.startSession(robotId);

// You're live — video is streaming, data channel is open

4. Control the robot

// Move the head (roll, pitch, yaw in degrees)
robot.setHeadPose(0, 10, -5);

// Move the antennas (right, left in degrees)
robot.setAntennas(30, -30);

// Play a sound file on the robot
robot.playSound("wake_up.wav");

// Send any JSON command via the data channel
robot.sendRaw({ my_custom_command: "hello" });

5. Receive robot state

// Emitted every ~500ms while streaming
robot.addEventListener("state", (e) => {
const { head, antennas } = e.detail;
// head: { roll, pitch, yaw } — degrees
// antennas: { right, left } — degrees
});

6. Audio

// Unmute robot speaker (muted by default in browser)
robot.setAudioMuted(false);

// Unmute your microphone (bidirectional audio, if robot supports it)
robot.setMicMuted(false);

// Check if bidirectional audio is available
robot.addEventListener("micSupported", (e) => {
console.log("Mic supported:", e.detail.supported);
});

7. Cleanup

detach();                    // remove video binding
await robot.stopSession(); // back to 'connected' state
robot.disconnect(); // close signaling (keeps auth)
robot.logout(); // clear HF credentials

API Reference

Constructor

new ReachyMini({
signalingUrl: "https://cduss-reachy-mini-central.hf.space", // default
enableMicrophone: true, // default — request mic on startSession()
})

State Machine

'disconnected' ──connect()──▸ 'connected' ──startSession()──▸ 'streaming'
▴ disconnect() ▴ stopSession()
└─────────────────────────────┘

Properties (read-only)

PropertyTypeDescription
statestring"disconnected", "connected", or "streaming"
robotsArrayAvailable robots: [{ id, meta: { name } }]
robotStateObject{ head: { roll, pitch, yaw }, antennas: { right, left } } (degrees)
usernamestring|nullHF username after authenticate()
isAuthenticatedbooleanTrue if a valid HF token is available
micSupportedbooleanTrue if robot offers bidirectional audio
micMutedbooleanYour microphone mute state
audioMutedbooleanRobot speaker mute state (local only)

Methods

MethodReturnsDescription
authenticate()Promise<boolean>Check for existing HF OAuth token
login()Redirect to HF login page
connect()PromiseOpen SSE connection, receive robot list
startSession(robotId)PromiseNegotiate WebRTC, resolves when video + data ready
stopSession()PromiseEnd session, back to connected
disconnect()Close signaling (keeps auth)
logout()Clear HF credentials
attachVideo(videoEl)() => voidBind video stream to element; returns cleanup function
setHeadPose(roll, pitch, yaw)booleanSet head orientation in degrees
setAntennas(right, left)booleanSet antenna positions in degrees
playSound(filename)booleanPlay a sound file on the robot
sendRaw(data)booleanSend arbitrary JSON via data channel
requestState()booleanRequest a state snapshot
setAudioMuted(muted)Mute/unmute robot speaker (local)
setMicMuted(muted)Mute/unmute your microphone

Events

Use robot.addEventListener(name, handler) — the SDK extends EventTarget.

EventDetailDescription
connected{ peerId }Signaling connection established
disconnected{ reason }Signaling connection lost
robotsChanged{ robots }Robot list updated
streaming{ sessionId, robotId }WebRTC session active
sessionStopped{ reason }Session ended
state{ head, antennas }Robot state update (~500ms)
videoTrack{ track, stream }Video track available
micSupported{ supported }Bidirectional audio availability
error{ source, error }Error from signaling, webrtc, or robot

Math Utilities

import { rpyToMatrix, matrixToRpy, degToRad, radToDeg } from "./reachy-mini.js";

rpyToMatrix(roll, pitch, yaw) // degrees → 4×4 rotation matrix (ZYX)
matrixToRpy(matrix) // 4×4 matrix → { roll, pitch, yaw } in degrees

Security

  • Authentication goes through Hugging Face OAuth — only users logged in to HF can access the signaling server.
  • By default, you can only connect to robots registered under your own HF account.
  • WebRTC connections are encrypted (DTLS/SRTP).

Prerequisites

  • Your robot must be running the wireless firmware and connected to the central signaling server.
  • The robot must have a valid Hugging Face token configured (see Usage).
  • Currently supported on wireless versions only.

Example

A full working example is available as a Hugging Face Space: cduss/webrtc_example

It demonstrates video streaming, head/antenna control, bidirectional audio, and sound playback — all from a single static HTML page.

Loading Comments...