CTRLLR

CTRLLR Documentation

Welcome to CTRLLR — turn phones into game controllers for your web app.

What is CTRLLR?

Players scan a QR code with the CTRLLR mobile app and their phone becomes a low-latency gamepad, streamed to your page over a peer-to-peer WebRTC data channel. @ctrllr/sdk gives you a simple, type-safe API on top: connected controllers, live input state, and edge-detected button events. One phone is a single-player controller; several phones make instant couch multiplayer.

The controller

Every connected phone gives you the same layout:

  • Joystick — analog stick, x / y in -1..1
  • A, X, Y, Z — four aimable action buttons: besides pressed, each reports an x / y displacement while held, so a single button can shoot and aim
  • Start — a simple press-only button

Features

  • No extra hardware — controllers are the phones already in the room
  • Peer-to-peer input — WebRTC data channels; the signaling server only brokers the connection
  • TypeScript first — fully typed state, events, and payloads
  • Framework agnostic — a plain event-emitting manager; works with React, Vue, vanilla JS, or a canvas game loop
  • Multiplayer by default — controllers get stable indexes (0, 1, 2…); a freed index is handed back on reconnect

Quick Example

import { CtrllrManager } from '@ctrllr/sdk';

const ctrllr = new CtrllrManager({ signalingUrl: '...' });
await ctrllr.connect();

ctrllr.on('controllerconnected', ({ controller }) => {
  console.log(`P${controller.index + 1} (${controller.username}) joined`);

  controller.on('buttondown', (e) => {
    if (e.input === 'a') fire(e.x, e.y); // aimable: direction included
  });
  controller.on('statechange', ({ state }) => {
    move(state.joystick.x, state.joystick.y);
  });
});

Want to feel it first? Play CTRLLR Invaders — then open the Debugger to watch the raw input stream.


Ready to dive in? Head to the Getting Started guide.