ronak-create/LapDeck: Turn your phone into a remote deck for your Windows laptop — app launcher, touchpad, keyboard, live

github.com · 2026-07-22 · by Long Nguyen ·github
Turn your phone into a remote deck for your Windows laptop — app launcher, touchpad, keyboard, live screen view, media & power. One Node process, zero cloud. - ronak-create/LapDeck

ronak-create/LapDeck

Turn your phone into a remote deck for your Windows laptop — app launcher, touchpad, keyboard, live screen view, media & power. One Node process, zero cloud. - ronak-create/LapDeck

1 stars · 0 forks · JavaScript Topics: nodejs, android, windows, remote-control, pwa, websocket, touchpad, remote-desktop, tailscale

README

LapDeck

Turn your phone into a remote deck for your Windows laptop. App launcher · touchpad · keyboard · live screen view · media & volume · brightness · lock/sleep/shutdown — all from the phone in your hand, over your own Wi-Fi. One Node.js process on the laptop, a PWA on the phone, zero cloud, zero accounts. Phone (browser / installed PWA) ── Wi-Fi / Tailscale ──► LapDeck agent (Node.js on Windows)

Lying in bed and want to pause the movie, nudge the volume, or shut the laptop down? Presenting and need a remote touchpad? LapDeck is a single npm start away.

Features

App launcher — tiles for apps, folders, files, and websites. Add/remove tiles from the phone; pick which browser opens a site. Touchpad — relative pointer with acceleration, tap-to-click, two-finger scroll, two-finger tap = right-click, double-tap-drag. Pointer speed slider. Keyboard — type live into the laptop (IME-safe diffing, so swipe-typing works), plus common shortcuts and your own custom shortcut buttons (any chord like ctrl+shift+p, or sequences like ctrl+k,ctrl+o). Live screen view — MJPEG stream with tap-to-click where you tap, a realtime client-predicted cursor overlay, a magnifier loupe, and quality presets. Media & system — play/pause/next/prev, volume, mute, brightness, battery readout. Power — lock, sleep, restart, shutdown, each with confirm + an abort window (grace period is configurable). Settings screen — everything below is tweakable from the phone itself. PWA — add to home screen and it feels like a native app. Works from anywhere, not just home Wi-Fi — optional: add Tailscale (free) and control your laptop from the other side of the world, no port forwarding, no config. The agent detects it and shows a remote QR/URL automatically.

Quick start Requirements: Windows 10/11, Node.js ≥ 20, phone on the same Wi-Fi. git clone https://github.com/ronak-create/LapDeck.git cd LapDeck npm install npm start The terminal prints a QR code. Scan it with your phone — the UI opens already paired (the token rides in the link and is stored on the phone; you scan once). Then use your browser menu → Add to Home screen.

Phone can't connect? Allow Node.js through Windows Firewall on private networks — the prompt appears on first run. That's the #1 cause.

Run automatically at login (hidden, no console) powershell -ExecutionPolicy Bypass -File scripts\install-autostart.ps1 Drops a tiny launcher into your Startup folder (no admin needed). Manage it with scripts\stop-agent.ps1 and scripts\uninstall-autostart.ps1. Autostart runs after you log in, because input injection and screen capture need your interactive session. Customization Open the ⚙ Settings screen on the phone (or edit data/settings.json on the laptop — see docs/CONFIGURATION.md for every key):

Setting What it does

Device name Title shown in the app

Accent color Theme, synced to every paired phone

Feature switches Turn screen view / input / media / power / file browsing off entirely — enforced by the agent, not just hidden

Power permissions Allow/deny sleep, shutdown, restart individually; shutdown grace period (0–60 s)

Custom shortcuts Your own buttons on the Keyboard screen

Stream presets fps / width / JPEG quality of the Low/Med/High screen presets (file only)

Port / bind address settings.json or LC_PORT / LC_BIND env vars

Per-phone prefs Haptics, natural scrolling, pointer speed (stored on the phone)

Security model

Pairing is a random 256-bit token, generated on first run and embedded in the QR link. Every command requires it — over WebSocket (first message must authenticate, 3 s or the socket drops) and on the MJPEG stream. Token comparison is constant-time. Destructive actions (sleep/shutdown/restart) additionally require a confirm flag, must be enabled in settings, and shutdown/restart honor a grace period during which one tap aborts. Feature switches are enforced server-side: a disabled feature's commands are refused even if a client sends them. To re-pair from scratch (rotate the token), delete data/secret.json and restart. Transport is plain HTTP/WS on your LAN. That's fine for a home network you trust; for anything else use Tailscale, which encrypts end-to-end (WireGuard) and gives you a valid-HTTPS URL via MagicDNS. Never port-forward the agent to the open internet.

Use it from anywhere (remote access) Out of the box LapDeck works on your local network — phone and laptop on the same Wi-Fi, nothing leaves your house. Want to control the laptop from work, a friend's place, or another country? Install Tailscale (free for personal use) on the laptop and phone with the same account. That's the entire setup — no port forwarding, no dynamic DNS, no server to rent. Tailscale puts both devices on a private WireGuard-encrypted network, and LapDeck detects it automatically: the agent prints a second "remote" QR, and the UI's Remote access panel offers a one-tap switch plus an HTTPS URL (via MagicDNS/tailscale cert) that makes the PWA installable as a real app from anywhere. Tailscale is entirely optional — LapDeck never needs the internet and has no cloud component. Any WireGuard/VPN setup that puts your phone on your home network works too; Tailscale is just the zero-config way. What you should not do is expose the agent's port directly to the internet — see the security model above. Project layout src/ index.js HTTP + WebSocket server, QR pairing settings.js defaults + data/settings.json (the customization layer) config.js pairing token, launcher entries auth.js constant-time token guards router.js command dispatch + feature-switch enforcement stream.js shared MJPEG capture loop (nut.js + sharp) handlers/ one module per command namespace (apps, input, media, …) win/ all Windows-specific PowerShell/CLI helpers public/ the phone PWA (vanilla HTML/CSS/JS) scripts/ autostart install/stop/uninstall (PowerShell) data/ created at runtime: token, settings, launcher (gitignored)

The full WebSocket protocol is documented in docs/PROTOCOL.md — it's deliberately simple JSON envelopes, so alternative clients (a native Android app, a CLI, an automation script) are easy to build. FAQ Why Windows-only? All the OS glue (volume, brightness, power, capture) lives behind src/win/. Ports to macOS/Linux are welcome — the protocol and UI are OS-agnostic. Sleep hibernates instead? Windows quirk: if hibernation is enabled, SetSuspendState hibernates. powercfg /h off if you prefer S3 sleep. Screen view shows the primary display only — multi-monitor selection is on the wishlist. Does it work without internet? Yes — everything is LAN-local. Internet is only involved if you use Tailscale. Contributing Issues and PRs welcome — see CONTRIBUTING.md. Keep it dependency-light: plain modern JavaScript (ESM, Node ≥ 20), no TypeScript, no build step. Found a security problem? Please report it privately — see SECURITY.md. License MIT © Ronak Parmar

source

github.com · 8 images · 120 links

Comments (0)

No comments yet