Developers

The sandbox

Read this before you build. Every limit here is deliberate, and none of them are configurable.

No network. At all.

A Content Security Policy is injected before your code runs:

default-src 'self' 'unsafe-inline' data: blob:; connect-src 'none';
script-src 'self' 'unsafe-inline'

connect-src 'none' means no fetch, no XHR, no WebSocket, no beacon. No CDN scripts, no Google Fonts, no analytics, no error reporting, no API you own.

Everything ships in your folder. Inline your CSS, embed images as data URIs, bundle your own fonts.

This is the single most important thing to design around, and the most common reason a plugin that worked in a browser does nothing on the device. The simulator does not enforce it — test on a device before you publish.

The only outside information available to you is data.weather().

You cannot leave your folder

File access is scoped to your own plugin directory. You cannot read another plugin's files, the app's files, or anything else on the device.

Navigation away from your own bundle is refused — links, redirects, window.location. Your plugin is one page, for its whole life.

Nothing persists

Storage is non-persistent. localStorage, cookies and caches are cleared between runs. Anything the user should still have next time has to be re-derived or re-entered.

A storage API is the most-requested thing not yet built. If you need it, say so — that is how it gets prioritised.

Rate limits

voice.speak one per 0.4s, 300 characters
motor.* one move per 0.35s
camera events about 6 per second

Exceeded calls resolve false and are dropped, not queued. A backlog of stale commands is worse than a missed one, especially for movement.

Ambient plugins yield

An ambient plugin gives up the screen the moment the robot leaves idle, and whenever the display deep-dims for battery. Do not depend on running continuously.

What you can rely on

Your page is a full modern WebView. Canvas, WebGL, CSS animation, Web Audio, touch — all of it works. The limits above are about the outside world, not about what you can build on screen.

The simulator loads your plugin in a plain iframe

It does not inject anything. Two consequences, and both look like the simulator being broken if you don't know them:

Include the SDK yourself. Add <script src="../hairobo-sdk.js"></script> before your own script, as every example does. Without it hairobo is undefined and nothing runs. On a real robot the app injects the SDK before your page loads, so that tag 404s there and does nothing — which is why it is not in the manifest's files.

Serve your plugin from the same origin as the simulator. The SDK reaches the fake robot through window.parent, and a browser blocks that across origins. A plugin loaded from your own domain into a simulator on ours will load and then refuse every call. Put the folder next to the simulator, or run both from one local server.

← Previous Permissions Next → Publishing
Preorder Deskmate dock

Reserve your dock.

Drop your details and we'll email you the moment it ships, with early-bird pricing.