Use your body as a game controller. Your phone watches you move; the game plays on your TV.
An iPhone runs Apple's Vision body-pose detection on the front camera and uses your movement to drive a game rendered full-screen on the phone. Mirror the phone to any TV (AirPlay, Chromecast, or QuickTime to a Mac) to play on the big screen. Everything runs on the phone — no server, no accounts, no cloud.
iPhone: front camera ─► Vision pose ─► game (WKWebView) ─► screen
│ mirror (AirPlay / Chromecast / QuickTime)
▼
TV
v1 is deliberately serverless and single-device — the fastest path to answering
the only question that matters: does body-control feel good? Multiplayer, a
browser display, Chromecast receivers, and cross-network play are v2 and already
have their scaffolding in the repo (parked). One live exception: the app can
optionally also stream pose to the PartyKit relay (AppModel.streamToWebsite) so
a browser mirrors your motion — a working preview of the v2 relay path that the
local game does not depend on.
| v1 (now) | v2 (parked) | |
|---|---|---|
| Devices | one iPhone + a mirrored TV | phones + a shared browser/TV |
| Transport | in-process JS bridge | PartyKit relay (server/) |
| Display | game on phone, screen-mirrored | browser (web/) + Chromecast receiver |
| Recording | ReplayKit screen capture | camera-record + composite |
| Players | 1 | 1–4 |
| Dir | What |
|---|---|
protocol/ |
v1 wire/bridge message shapes — single source of truth |
web/ |
The game: TypeScript + Vite + Canvas. A reusable SDK + Game interface. The phone (bridge) runs Motion Maker (grab/toss playground); Reach & Dodge is the plain-browser socket consumer. Runs in a phone WebView (v1) or a browser (v2). |
ios/ |
SwiftUI app: camera, Vision pose, WebView game host, JS pose bridge, ReplayKit recording |
server/ |
PartyKit relay — parked for v2 |
docs/ |
Decision log / journey |
The game is fully playable in a desktop browser with a keyboard/mouse debug controller — the quickest way to feel the games and iterate on them.
pnpm install
pnpm --filter motion-web run dev # http://localhost:5173- Open
http://localhost:5173/?debug=1for Reach & Dodge (the plain-browser default): mouse = hands, arrow keys = lean, space = squat. - Open
http://localhost:5173/?game=motion-maker&debug=1for Motion Maker — the same playground the phone runs: mouse = a hand, hold left mouse / space = close the hand (grab), release to drop.
The phone renders the game; you mirror it to a TV. The web game is bundled into the
app (ios/Resources/webgame), so no dev server or Mac network is needed to play.
- Generate + open the Xcode project:
cd ios && brew install xcodegen && xcodegen generate && open Motion.xcodeproj
- Set your signing team (a free Apple ID works).
- Run on a physical iPhone (camera required). Grant camera + Photos permissions.
- Stand back so your whole body is in frame, calibrate, play.
- Mirror to a TV: Control Center → Screen Mirroring → your Apple TV / AirPlay-2 TV / Chromecast (or use QuickTime over USB to view on the Mac).
- Tap Record to save a screen recording (game + your camera inset) to Photos.
Iterating on the web game from the phone? Run pnpm --filter motion-web run dev, set
GameConfig.forceDevServer = true, point the app's dev-server IP at your Mac, and
refresh the bundle after changes with ./scripts/sync-webgame.sh.
Pushes and pull requests run the repository-owned TypeScript code-health gate and an unsigned iOS Simulator build. The gate covers formatting and lint, types, tests and full-source coverage, unused code, complexity, duplication, cycles, dependency risk, suppressions, and repository hygiene. Existing debt is ratcheted so it cannot grow and is tracked in #26. Physical-device and signing evidence stays manual because hosted CI cannot exercise the camera path.
pnpm checkThe public landing is a separate static Cloudflare Pages surface. Release it
only from a clean, synchronized main after exact-main CI is green:
pnpm run deployThe parked PartyKit relay keeps its separate server deploy command and is not
released by the landing command.
MVP POC. See PROJECT_STATUS.md and
docs/decision-log.md. The main product risk is control
feel, not infrastructure — which is exactly why v1 strips out all the servers.
⚠️ The iOS app compiles cleanly for the iOS Simulator but has not yet run on a physical device (the Simulator has no camera). Key things to verify first: that ReplayKit captures the WebView game content, and that the Vision left/right joint mapping matches the player. See the verify list inPROJECT_STATUS.md.