Developers

Publishing

You don't host anything. Upload your folder, try it on your own robot, then submit it for review.

1. Build it in the simulator

The simulator runs your plugin with the robot stubbed out — revoke permissions, fake a missing dock, watch every call. Get it working there first; it is much faster than a device.

2. Upload it as a draft

Drop your folder on hairobo.com/developers/submit. manifest.json plus every file it lists.

The checks run immediately, before anything is stored. Blocking errors come back as checks.errors and nothing is recorded until they are fixed:

  • manifest doesn't parse, or id isn't reverse-DNS, or version isn't semver
  • entry isn't a relative .html path inside your folder
  • a file in files wasn't in the upload
  • bundle over 5 MB, or over 60 files
  • code calls fetch, XMLHttpRequest, WebSocket, EventSource, sendBeacon or importScripts — plugins have no network access (connect-src 'none'), so these cannot work on a device
  • a remote src= — the sandbox blocks it and you get a blank screen. Bundle the file and list it in files.
  • you call hairobo.motor.* without "motor" in permissions — every call would be refused at runtime

checks.warnings don't block. The most common one:

permission "camera" is requested but never used

Asking for a permission you don't use is the single most common reason a submission comes back. Remove it.

3. Try it on your own robot

Open Hai Robo signed in with the account you uploaded from, go to Settings → Plugins → Gallery. Your draft is there, marked DRAFT, above the public plugins. Tap Try it.

Nobody else can see it. It is not in the gallery for anyone but you, and it will not be until a reviewer approves it.

You get the real thing: the real sandbox, the real permission prompt, the real CSP, the real motors. The only difference from a published plugin is that nobody has reviewed it.

4. Iterate

Re-upload the same version as often as you like. A draft is mutable — fixing one line does not cost you a version number. Tap Reinstall in the gallery to pull the new bytes.

Freezing happens when you submit, not when you upload.

5. Submit for review

One button on the portal. From that moment the bytes are fixed: what a reviewer reads and what eventually ships are exactly what you submitted, and further uploads to that version are refused.

The checks run again here, against what is stored rather than what you last uploaded — so the report a reviewer sees describes the code a reviewer reads.

6. Review

A person reads the source, runs it, and checks the permissions match what it does. Not a code review: a check that the plugin is what it says it is and isn't hostile. Expect a few days.

If it comes back, review_note says why. Fix it, upload a new version, and submit again — a rejected version stays rejected.

Approved plugins appear in the gallery for everyone.

Updating

Upload a new version and submit it. Each version is reviewed on its own, and your live version keeps serving throughout — a rejected update never takes down the version already approved.

Adding a permission means the user is asked again, and the new permission stays ungranted until they agree; the rest keep working meanwhile. Removing one needs nothing.

Version numbers

  • A draft can be re-uploaded any number of times.
  • Once submitted, that version is closed. To change anything, bump the version.
  • A rejected version can never be resubmitted. Bump and upload again.

What gets removed

Set out fully in CONTENT-POLICY.md. In short: plugins that request permissions they do not use, misrepresent what they do, target or harass anyone, or try to get around the sandbox rather than work within it.

Users can report a plugin from the gallery. Reports are read by a person.

A plugin can be pulled two ways, and both are used together when something is actually wrong: suspending it hides it from the gallery, which stops new installs; the blocklist stops the copies already on people's devices.

Being useful, not just working

The plugins people keep are the ones that respect where they are — a device on a desk that is mostly idle. Quiet by default, obvious at a glance, and correct about whether a dock is even connected.

info.get() tells you what you actually have. Use it before offering a robot feature you cannot deliver.

← Previous The sandbox Next → Content policy
Preorder Deskmate dock

Reserve your dock.

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