Web Launcher SDK
Overview
Build HTML5 and Three.js apps that run inside Fluffer and drive the player's toy through the launcher bridge. What the SDK packages are and how apps run.
Fluffer is a phone app (iOS and Android) that hosts small interactive apps and games and connects them to the player's Bluetooth toy. You build your app with ordinary web technology: HTML, CSS, TypeScript or JavaScript, Canvas or Three.js. Fluffer takes care of pairing, Bluetooth, permissions and the app lifecycle. Your code asks for a buzz, and the toy buzzes.
The Web Launcher SDK is the set of packages and conventions that make this work.
#What you can build
- Haptic games: arcade, rhythm, puzzle or action games where every collision, pickup and level-up can be felt.
- Interactive experiences: anything that turns touch, timing or game state into motor patterns.
- Apps that save media: camera or creative apps that save photos and video to the player's photo library.
- Apps that remember things: documents and files kept on the device, private to your app.
- Account-aware apps: apps that, with the player's explicit consent, recognise the Fluffer account and verify it on your own backend.
#How an app runs inside Fluffer
- The player opens your app from Fluffer's catalog.
- Fluffer loads your bundle in a web view. Your app is served from its own address (
https://<your-app>.fluffer.app/), so its storage is never shared with other apps. - Before your first frame, Fluffer injects a small bridge into the page. The bridge is a JSON request/response channel between your code and the launcher, called
fluffer-bridge/1. - Your app performs a handshake: it says which capabilities it wants (for example
device.vibrate), and Fluffer answers with the capabilities it actually granted, plus the connected toy, if any. - From then on your app sends requests (
device.setAllMotors,host.exit, ...) and receives events (device.connectionChanged,tips.received, ...). - When the player backgrounds Fluffer, per-frame work in
game.onTickstops with the page. When they leave your app, Fluffer closes it and the toy stops, so save progress as you go.
Your app never touches Bluetooth and never asks the OS for Bluetooth permission. The capabilities you can use are the ones your manifest declares and the launcher grants.
#The SDK packages
| Package | What it is for | Use it when |
|---|---|---|
@fluffer/game-kit | The recommended framework. One call (createGame()) does the handshake, frame loop, pointer and keyboard input, auto-pause, 14 named haptic primitives, 25 haptic recipes, reactive state, on-device storage, and helpers for tips, media and accounts. | You're building a game or interactive app. Start here. |
@fluffer/launcher-sdk | The lower-level bridge client. Exposes Scanner, LauncherDevice, host, user, the manifest validator and a mock launcher for browser development and tests. | You want raw device control, are porting an app written for the standalone Fluffer SDK, or are writing tests. |
fluffer-sdk | The standalone Fluffer SDK for apps that talk to a toy directly over Bluetooth, outside the launcher. @fluffer/launcher-sdk mirrors its API and re-exports the types you need. | You don't need it for launcher apps. It only matters if you're moving an existing standalone app into Fluffer. |
@fluffer/game-kit is built on @fluffer/launcher-sdk and re-exports the pieces a game needs (host, user, isInLauncher, FlufferError, FlufferErrorCode and the common types), so most apps import from one place.
#A minimal app
This is a complete Fluffer app: tap the screen and the toy gives a short buzz.
import { createGame, haptics } from '@fluffer/game-kit';
const game = await createGame({
capabilities: ['device.vibrate'],
canvas: document.querySelector('canvas'),
});
game.onPointer((e) => {
if (e.type === 'down') void haptics.impact(0.7);
});
It needs a manifest.json next to it:
{
"manifestVersion": 1,
"minSdkVersion": "0.1.0",
"engine": "html5",
"entry": "index.html",
"orientation": "landscape",
"capabilities": ["device.vibrate"]
}
In a plain browser tab, createGame() notices it isn't inside Fluffer and installs a mock launcher with a virtual toy, so the same code runs on your laptop without hardware.
#The same thing with the lower-level SDK
import { Scanner, host } from '@fluffer/launcher-sdk';
const scanner = new Scanner({ requestedCapabilities: ['device.vibrate'] });
await scanner.init(); // handshake with the launcher
const [info] = await scanner.getDevices(); // the toy the player already paired
if (info) {
const device = await scanner.createDevice(info);
await device.setAllMotors({ m1: 180, m2: 180, m3: 0, m4: 0 }); // 0-200 per motor
}
setTimeout(() => host.exit(), 30_000);
#Where to go next
- Getting started: scaffold, run and package your first app.
- Bridge protocol: every method, event and capability.
- Manifest: what your app declares.
- Haptics: the primitives and recipes that make a game feel good.
- Storage: keep data on the device.
- Accounts: consent-first identity.
- Publishing: prepare your app for Fluffer.