Skip to content

Commit 52a689a

Browse files
creationsofm7claude
andcommitted
docs: animated README with capsule-render, typing SVG, badges
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 18f0e12 commit 52a689a

1 file changed

Lines changed: 164 additions & 49 deletions

File tree

README.md

Lines changed: 164 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,73 +1,188 @@
1-
# LocalTV Remote
1+
<div align="center">
22

3-
Turn your phone into a wireless mouse, keyboard, and media remote for your
4-
Windows PC — over your local network, with no app store install on the phone
5-
(it's a PWA you open in the browser).
3+
<img src="https://capsule-render.vercel.app/api?type=waving&color=0:6366f1,100:a855f7&height=200&section=header&text=LocalTV%20Remote&fontSize=60&fontColor=ffffff&fontAlignY=38&animation=fadeIn&desc=Phone%20→%20Windows%20Remote%20Control&descSize=20&descAlignY=58&descColor=e2e8f0" width="100%" />
64

7-
This is the **open-source, remote-control-only** sibling of LocalTV. It contains
8-
**no embedded browser, no DRM, and no TV/streaming mode** — just the remote
9-
control daemon. As a result it runs as a single lightweight Node process instead
10-
of a full Electron/Chromium app.
5+
<a href="https://readme-typing-svg.demolab.com">
6+
<img src="https://readme-typing-svg.demolab.com?font=Fira+Code&size=20&pause=1000&color=6366F1&center=true&vCenter=true&width=620&lines=Turn+your+phone+into+a+Windows+remote;Scan+a+QR+code+%E2%80%94+no+app+install+needed;Mouse+%E2%80%A2+Keyboard+%E2%80%A2+Scroll+%E2%80%A2+Volume;LAN-only+%E2%80%94+no+cloud%2C+no+accounts%2C+no+Chromium" alt="Typing animation" />
7+
</a>
118

12-
## Why it's small
9+
<br/>
10+
<br/>
1311

14-
The original LocalTV is an Electron app (~410 MB packaged) because it embeds
15-
Chromium for DRM streaming. Remote control never needed any of that: it's an
16-
HTTP + WebSocket server plus Win32 `SendInput`. This project ships only that, so
17-
the runtime is a single Node process (~25–40 MB RAM at idle) and the download is
18-
dominated by the Node runtime (~50–90 MB) rather than a bundled browser.
12+
[![License](https://img.shields.io/badge/License-Apache%202.0-6366f1?style=for-the-badge)](LICENSE)
13+
[![Platform](https://img.shields.io/badge/Platform-Windows%2010%2F11-0078d4?style=for-the-badge&logo=windows&logoColor=white)](https://github.com/creationsofm7/localtv-remote/releases)
14+
[![Release](https://img.shields.io/github/v/release/creationsofm7/localtv-remote?style=for-the-badge&color=a855f7&label=Release)](https://github.com/creationsofm7/localtv-remote/releases/latest)
15+
[![Download](https://img.shields.io/github/downloads/creationsofm7/localtv-remote/total?style=for-the-badge&color=22c55e&label=Downloads)](https://github.com/creationsofm7/localtv-remote/releases/latest)
16+
[![Stars](https://img.shields.io/github/stars/creationsofm7/localtv-remote?style=for-the-badge&color=f59e0b)](https://github.com/creationsofm7/localtv-remote/stargazers)
1917

20-
The desktop pairing window uses the **system WebView2 runtime** (already present
21-
on Windows 10/11) — not a bundled Chromium — and falls back to your default
22-
browser if WebView2 isn't available.
18+
</div>
19+
20+
---
21+
22+
## What is this?
23+
24+
**LocalTV Remote** is a lightweight Windows daemon that turns your phone into a wireless remote — mouse, keyboard, scroll wheel, and volume control — over your local Wi-Fi. Your phone opens a PWA in the browser (no app store install). The PC runs a single Node process at ~25–40 MB RAM.
25+
26+
> This is the **open-source, remote-only** sibling of LocalTV. It contains no Chromium, no DRM, and no TV/streaming mode — just the remote control daemon.
27+
28+
---
29+
30+
## Features
31+
32+
| | |
33+
|---|---|
34+
| 🖱️ **Mouse control** | Move, click, right-click, scroll — with DPI-aware scaling |
35+
| ⌨️ **Keyboard input** | Type text and send key combos from your phone |
36+
| 🔊 **Volume control** | Accurate system volume via Windows Core Audio (COM) |
37+
| 📱 **PWA — no install** | Phone opens a web page, installs as a home-screen app |
38+
| 🔗 **QR pairing** | Scan once, token is remembered for future sessions |
39+
| 🔒 **LAN-only** | No cloud relay, no accounts, no data leaves your network |
40+
| 🪶 **Tiny footprint** | ~27 MB installer, ~25–40 MB RAM at idle, no Chromium |
41+
| 🖥️ **System tray** | Sits in the tray; optional start-on-login toggle |
42+
| 🔌 **Auto port** | Free-port fallback if 3000 is occupied — QR auto-updates |
43+
44+
---
45+
46+
## Install
47+
48+
### Option 1 — Installer (recommended)
49+
50+
Download **[LocalTVRemote-Setup-0.1.0.exe](https://github.com/creationsofm7/localtv-remote/releases/latest)** from the latest release and run it.
51+
52+
The setup wizard will:
53+
- Install to `%ProgramFiles%\LocalTV Remote`
54+
- Create a Start Menu shortcut
55+
- Add a Windows Firewall inbound rule (so your phone can reach the daemon without a popup)
56+
- Optionally create a desktop shortcut and enable start-on-login
57+
58+
### Option 2 — winget *(coming soon)*
59+
60+
```
61+
winget install LocalTV.Remote
62+
```
63+
64+
---
65+
66+
## How to use
67+
68+
1. **Launch** — double-click the tray icon or start from the Start Menu
69+
2. **Pair** — a pairing window opens with a QR code and a 6-digit PIN
70+
3. **Scan** — open your phone camera, scan the QR code
71+
4. **Control** — the phone browser opens the controller UI; swipe to move, tap to click
72+
73+
Your phone remembers the pairing token — next time it reconnects automatically.
74+
75+
---
2376

2477
## How it works
2578

26-
1. The daemon starts an Express + `ws` server on `0.0.0.0:3000`.
27-
2. It shows a pairing window with a QR code and a stable 6-digit code.
28-
3. On your phone (same Wi-Fi), scan the QR or open `http://<pc-ip>:3000` and
29-
enter the code.
30-
4. Input from the phone is injected OS-wide via koffi → Win32 `SendInput`.
79+
```
80+
Phone browser (PWA)
81+
│ WebSocket + HTTP (LAN)
82+
83+
LocalTVRemote.exe ←── Express + ws server on 0.0.0.0:3000
84+
85+
├── Mouse / Keyboard → koffi → Win32 SendInput
86+
├── Volume → PowerShell COM → IAudioEndpointVolume
87+
└── Pairing window → WebView2 (system runtime, not bundled Chromium)
88+
```
89+
90+
- Input is injected OS-wide via `SendInput` — works in any app including games and full-screen windows
91+
- Volume uses a persistent PowerShell STA process talking to Windows Core Audio COM directly — accurate to the system tray to within ±1%
92+
- The pairing window uses the **system WebView2 runtime** (pre-installed on Windows 11, auto-installed on Windows 10) — no bundled browser
3193

32-
### Security model
33-
- LAN-only; binds the local network interface.
34-
- Pairing requires a 6-digit code derived from the machine identity; trusted
35-
sessions resume via a stored token.
36-
- WebSocket upgrades are origin-checked; messages are rate-limited
37-
(500/sec/client) with auth + inactivity timeouts.
38-
- The pairing page (`/host`, `/api/state`, `/api/quit`) is restricted to
39-
loopback, so the pair code is never served to LAN peers.
94+
---
4095

41-
## Develop / run
96+
## Security
97+
98+
- **LAN-only** — binds `0.0.0.0` for control but restricts pairing routes (`/host`, `/api/state`) to loopback, so the PIN is never served to other devices on the network
99+
- **6-digit pairing PIN** derived from machine identity; trusted sessions resume via a stored token
100+
- **WebSocket origin checks** on every upgrade
101+
- **Rate limiting** — 500 messages/sec/client; idle clients are disconnected after inactivity
102+
- **Single-instance lock** — second launch exits cleanly instead of conflicting
103+
104+
---
105+
106+
## Build from source
107+
108+
**Requirements:** Node.js 22+, Windows 10/11
42109

43110
```bash
111+
git clone https://github.com/creationsofm7/localtv-remote
112+
cd localtv-remote
44113
npm install
45-
npm run build
46-
npm start
47114
```
48115

49-
Or for a quick dev loop: `npm run dev` (uses `tsx`).
116+
**Dev mode** (TypeScript, no build step):
117+
```bash
118+
npm run dev
119+
```
120+
121+
**Full production build** (SEA exe + payload):
122+
```bash
123+
npm run dist # typecheck + bundle + branded exe + payload
124+
npm run installer # compile Inno Setup → release/LocalTVRemote-Setup-x.y.z.exe
125+
```
50126

51-
Environment:
52-
- `LOCALTV_REMOTE_PORT` — server port (default `3000`).
53-
- `LOCALTV_REMOTE_STATIC_DIR` — override the controller PWA directory.
127+
**Environment variables:**
54128

55-
## Cross-platform
129+
| Variable | Default | Description |
130+
|---|---|---|
131+
| `LOCALTV_REMOTE_PORT` | `3000` | Preferred server port (auto-increments if occupied) |
132+
| `LOCALTV_REMOTE_STATIC_DIR` | `public/control` | Override the controller PWA directory |
56133

57-
Windows is the only supported target today. The input layer is abstracted behind
58-
`SystemInputBackend` (`src/core/main/input/backends/input-backend.ts`); adding
59-
macOS/Linux is a matter of implementing that interface and wiring it in
60-
`SystemInputRouter`.
134+
---
61135

62136
## Project layout
63137

64-
- `src/core/` — modules shared with the (proprietary) LocalTV TV app, decoupled
65-
from Electron. The server is typed against an `InputRouter` interface so it
66-
runs with or without Electron.
67-
- `src/daemon/` — the headless daemon: `SystemInputRouter`, the control server
68-
with the desktop pairing routes, the WebView2 window shell, and the tray.
69-
- `public/control/` — the phone controller PWA (served as-is).
138+
```
139+
src/
140+
├── core/
141+
│ ├── server/ # Express + WebSocket control server
142+
│ ├── main/
143+
│ │ ├── audio/ # Persistent PowerShell Core Audio host
144+
│ │ ├── input/ # SystemInputRouter + Win32 SendInput backend
145+
│ │ └── native/ # koffi FFI bindings, native-require loader
146+
│ └── shared/ # Protocol types, pairing logic
147+
└── daemon/
148+
├── index.ts # Entry: daemon mode or --webview child mode
149+
├── tray.ts # systray2 tray icon + menu
150+
└── startup.ts # Run-at-login registry toggle
151+
152+
public/control/ # Phone controller PWA (HTML/CSS/JS + SW + manifest)
153+
scripts/
154+
├── bundle.mjs # esbuild → build/localtv-remote.cjs
155+
├── build-sea.mjs # Node SEA blob + rcedit + PE subsystem flip
156+
├── assemble-payload.mjs # release/app/ with koffi stripped to win32_x64
157+
└── build-installer.mjs # Inno Setup compile → release/LocalTVRemote-Setup-*.exe
158+
installer/
159+
└── localtv-remote.iss # Inno Setup script
160+
```
161+
162+
---
163+
164+
## Cross-platform
165+
166+
Windows is the only supported target today. The input layer is abstracted behind `SystemInputBackend` (`src/core/main/input/backends/input-backend.ts`). Adding macOS/Linux means implementing that interface — contributions welcome.
167+
168+
---
169+
170+
## Contributing
171+
172+
1. Fork and clone
173+
2. `npm install && npm run dev`
174+
3. Make changes, run `npm run typecheck` to verify
175+
4. Open a PR — CI will typecheck on push
176+
177+
---
70178

71179
## License
72180

73-
MIT. Contains no Widevine/CastLabs/DRM code.
181+
Apache 2.0 — see [LICENSE](LICENSE).
182+
Copyright 2026 Mudit Pandey. Contains no Widevine/CastLabs/DRM code.
183+
184+
<div align="center">
185+
186+
<img src="https://capsule-render.vercel.app/api?type=waving&color=0:a855f7,100:6366f1&height=100&section=footer" width="100%" />
187+
188+
</div>

0 commit comments

Comments
 (0)