Scan a QR code. Your phone becomes the controller. The TV becomes the console.
Free, open-source party games for any smart TV or browser โ no console, no app install, no account. Up to 8 friends play together with the phones already in their pockets.
โถ Play now: playwithtv.leadup.in ยท How it works ยท Run it yourself ยท Build a game ยท Contribute
| ๐ฑ Phone = controller | Buttons, a touchpad, or motion: tilt to steer, flick to slice, push to punch, swing to bat. Every player picks the mode they like. |
| ๐บ TV = console | Any TV with a browser, the free Android TV app, a laptop on a projector. Games are drawn in 2D canvas or WebGL and tuned to run at 60 fps on 1 GB Android TVs. |
| โก Fast | Phones talk to the TV over a direct WebRTC link on your Wi-Fi (about 8 ms). The server only introduces them and runs no game code. |
| ๐จโ๐ฉโ๐งโ๐ฆ Everyone plays | 1โ8 players, no sign-up, nothing to install on the phones. |
| ๐งฉ Built to grow | Each game is one folder. Songs, dance routines, levels and trivia packs are plain text files anyone can write. |

The TV lobby. Phones join by scanning the code.

The phone controller: buttons, touchpad or motion, whichever each player picks.
20 games are live today, and every one also plays with plain buttons.
| Game | Players | What you do | |
|---|---|---|---|
| ๐ต | Beat Blade | 1โ4 | Your phone is a light saber: slice neon blocks to the beat of original synth songs |
| ๐ | Gully Super Over | 1โ8 | Street cricket: swing the phone to bat, flick to bowl |
| ๐บ | Ghat Rush | 1โ8 | Split-screen monsoon racing down mountain hairpins |
| ๐ฅ | Kalari Clash | 1โ4 | A martial-arts brawler: chain strikes, kicks and specials |
| ๐ฎ | Lantern Lane | 1โ4 | A co-op platformer through a festival night |
| โ | Monsoon Courier | 1โ4 | A speed platformer race over rain-soaked rooftops |
| ๐๏ธ | Stepwell Secrets | 1โ4 | Climb, swing and solve your way down an ancient step-well |
| ๐ซ | Tiffin Tornado | 1โ4 | Co-op kitchen chaos on a moving train |
| ๐ณ | Kitchen Rush | 2 | Run a food truck together |
| ๐๏ธ | Carry Me Home | 1โ2 | Carry a sofa together through a house โ in step |
| ๐ฒ | Tandem Ride | 1โ2 | A bike that only flies when you pedal together |
| ๐๏ธ | Skyline Stacker | 1โ4 | Falling-block city building |
| ๐ | Glowworm Grove | 1โ4 | A glowing snake game in night gardens |
| ๐ฑ | Comet Kitty | 1โ4 | Maze chase in a space station |
| ๐ | Buzz Field | 1โ4 | Minesweeper in a meadow, with forgiving honey jars |
| โ๏ธ | Kings Row | 1โ2 | Draughts / checkers, phone against phone or the AI |
| ๐ด | Drop Four | 1โ2 | Four in a row at the travelling fair |
The couples games (Mind Match, Two Paths, Lantern Truths) and Tamil Trivia Royale are held back from TVs while they are reworked. More are on the way: a dance game (Groove Party), motion sports (bowling, boxing, air hockey, penalties, kart racing) and camera fitness games where the phone watches your body and the video never leaves the phone. The full list with status is in docs/catalogue.md.
Gully Super Over ยท Kalari Clash ยท Lantern Lane
- On the TV open playwithtv.leadup.in/tv in its browser, or install the Android TV app (
apps/tv-android). - On each phone scan the QR code on the TV (or type the 5-character room code at
/join). Enter a name. - Pick a game on the TV. Each phone shows its controller; choose Buttons, Touchpad or Motion.
- Every game starts with a short practice so everyone learns the moves before it counts.
Motion tips: hold the phone the way the game shows (usually sideways). On iPhone, tap Allow when Safari asks for motion access. Open
/sensorson a phone to check its sensors are working.
flowchart LR
subgraph Home["Your living room (same Wi-Fi)"]
P1["๐ฑ Phone 1<br/>controller"]
P2["๐ฑ Phone 2<br/>controller"]
TV["๐บ TV<br/>renders the game"]
end
HUB["โ๏ธ Hub server<br/>(rooms + introductions only)"]
P1 -- "WebRTC data channel ~8 ms" --> TV
P2 -- "WebRTC data channel ~8 ms" --> TV
P1 -. "join, then fallback relay" .-> HUB
P2 -. "join, then fallback relay" .-> HUB
TV -. "create room, QR code" .-> HUB
- The TV asks the hub for a room and shows its QR code.
- A phone scans it, joins the room over a WebSocket, and the hub introduces the phone to the TV (WebRTC signalling).
- From then on the phone sends input straight to the TV over a WebRTC data channel. If the Wi-Fi blocks that, input goes through the hub instead, and the game keeps going.
- The game runs entirely on the TV: physics, rules, music, drawing. The phone only sends small input messages, such as a stick position or "punch at 12:00:01.234".
Why the server stays light: it never runs games or streams video. A room costs a few kilobytes, and once the direct link is up the input stays inside your home and never touches the server. Rooms, connections per address and relay traffic are capped, so one small server can host many living rooms at once.
flowchart LR
S["Accelerometer +<br/>gyroscope (60 Hz)"] --> C["Auto-calibrate<br/>(hold still < 1 s)"]
C --> G["Gesture engine<br/>packages/motion"]
G -->|"tilt x/y"| I["Input sender"]
G -->|"push ยท flick ยท twist ยท shake ยท swing<br/>+ the moment it peaked"| I
I --> TV["๐บ TV game"]
packages/motionturns raw sensor readings into tilt and gestures on the phone itself.- Each gesture is stamped with the moment it peaked, so rhythm and sports games judge your timing, not the Wi-Fi's.
- The same game code works with buttons, touchpad or motion. A game only ever sees actions such as
"roll"or"jump".
apps/
server/ Fastify hub: rooms, WebSocket signalling, relay fallback, admin API (Postgres/Redis optional)
web/ React + Vite: the TV app (/tv), the phone controller (/join), every game in src/games/<game>/
tv-android/ Tiny Android TV wrapper (WebView) with a TV launcher banner
packages/
protocol/ Shared types, message schemas (zod) and the game catalogue
motion/ The phone-side gesture engine (tilt, push, flicks, saber swings) with tests
content/ Trivia question packs (plain JSON)
tools/blender/ Blender scripts that render sprites, backdrops and 3D models (CC0)
e2e/ Playwright tests: a real TV page plus simulated phones with fake motion sensors
docs/ Building games, performance budgets, device compatibility, real-device test checklist
examples/ Self-hosting with Docker Compose + nginx
- Node.js 26+ and pnpm 10 (
corepack enablesets up pnpm) - macOS, Linux or Windows (WSL)
- Optional: Docker (for self-hosting), Blender 4 (for art assets), Android Studio / Gradle (for the TV app)
git clone https://github.com/leadupofficial/playwithtv.git
cd playwithtv
corepack enable
pnpm install
pnpm devOpen http://localhost:5173/tv for the TV and http://localhost:5173/join in another tab as a phone.
Buttons and touchpad work right away. ?quick=1 on the TV URL makes every game short, which helps when testing.
Phones only allow motion sensors on https pages, so the dev server can serve a self-signed certificate:
sh scripts/start-lan.sh # macOS: finds your Wi-Fi IP itself
IP=192.168.1.20 sh scripts/start-lan.sh # Linux: give your computer's LAN IPIt prints the TV and phone addresses. Open the TV address on the TV (or laptop) and scan the QR code with your phones.
Accept the certificate warning once on each device. Logs are in .run/.
pnpm typecheck # TypeScript across every package
pnpm test # unit tests (Vitest)
pnpm e2e # end-to-end: real TV page + simulated phones (Playwright; first: pnpm exec playwright install chromium)
pnpm perf # frame-time budget per game against the production build, on a software GPU
pnpm build # production buildcd examples/self-host
cp ../../.env.example .env # set ADMIN_TOKEN, add POSTGRES_PASSWORD=โฆ (openssl rand -hex 24 for each)
# replace play.example.com in docker-compose.yml and nginx.conf with your domain
docker compose up -d --buildThe hub listens on 127.0.0.1:8080. Put nginx, Caddy or Traefik with TLS in front of it (nginx.conf).
Without DATABASE_URL and REDIS_URL it runs in memory, which is fine for a single box. Settings are in .env.example.
In production the server refuses to start with a weak ADMIN_TOKEN, an empty ALLOWED_ORIGINS or a non-https PUBLIC_URL.
cd apps/tv-android
gradle assembleDebug # Gradle 8, or open the folder in Android Studio
adb connect <tv-ip>:5555 && adb install -r app/build/outputs/apk/debug/app-debug.apkIt opens the TV page full screen, keeps the screen on, and retries on its own if the TV's network or DNS hiccups.
- 2D games draw on a
<canvas>at 1280ร720 and scale to the TV. 3D games use three.js with a lite mode for weak TVs. - Quality tiers (
lite/high/ultra) are picked from the TV's GPU and memory, and adjust if frames drop. Glow, shadows and particles scale down on 1 GB TVs, so frame time stays inside the budget in docs/performance.md. - Art is drawn in code or rendered from Blender scripts in
tools/blender/(pnpm assets:sprites,pnpm assets:glb). Everything is original or CC0; third-party assets are listed in ASSETS.md. - Music is composed as patterns and played by a small in-browser synthesiser (
games/beat-blade/music.ts). There are no recordings, so no copyright problems, and a whole song costs a few hundred bytes.
- Animation runs on
requestAnimationFramewith fixed-step physics (1/60 s), so a game behaves the same on a 30 fps TV and a 120 fps laptop.
We want 100+ games made by the community, and you don't have to be a programmer to help:
| You canโฆ | Start here |
|---|---|
| ๐ต Write a song or a dance routine (plain text) | apps/web/src/games/beat-blade/songs.ts, games/groove/songs.ts |
| โ Write a trivia pack (JSON) | content/trivia/ + pnpm content:check |
| ๐ฎ Build a whole game | docs/building-games.md |
| ๐ฑ Test on your phone or TV | docs/real-device-test.md, then add a row to docs/compatibility.md |
| ๐ Report a bug or idea | Open an issue |
Read CONTRIBUTING.md first. Every pull request runs typecheck, unit tests, e2e and the weak-TV performance gate, so a new game can't slow down the others.
![]() Abishek Sivakumar Creator ยท maintainer |
![]() Pradeep (@pradeeplogu0) Core contributor ยท embedded & sensors |
Thanks to everyone who has played, tested on their TV, or sent a song. See all contributors.
- No accounts, emails or phone numbers. The only thing a player gives is a display name, kept with match history.
- Each browser (phone or TV) keeps a random anonymous install id in localStorage (
pwtv.device). It is sent when a TV opens a room or a phone joins one, so the admin console can count new and returning devices. No IP address, fingerprint or personal data is attached to it, and clearing site data resets it. - The admin console (
/admin,ADMIN_TOKEN) shows live TVs/phones online (updated every 2 s, with a 60-minute graph and the day's peak), daily new/returning users, top games and security events. - Camera games process video on the phone; frames are never uploaded.
- Report vulnerabilities privately; see SECURITY.md.
Code: MIT ยฉ Leadup Technologies and the Play With TV contributors. Trivia content, fonts and other assets keep their own licences (CC BY 4.0, CC0, SIL OFL), listed in ASSETS.md.


