Web Teleprompter — Self-Hosted PWA with Browser-Only Adaptive Scroll
A privacy-first teleprompter: paste a script, hand it to any device via QR, and let the microphone keep the scroll in sync with your voice
Speakers and creators needed a teleprompter they could run on their own machine, take offline, and hand a script to a second device without an account. Existing tools were either cloud-dependent, multi-device-incompatible, or both.
I built a privacy-first PWA: scripts live in the browser, the relay server forgets everything in five minutes, and the "adaptive" scroll that follows your voice uses only the browser's audio APIs — your mic never leaves the device.
The Problem
The user need was concrete: prepare a script on a laptop, send it to a phone or tablet, and present from that device in fullscreen — without installing an app, creating an account, or trusting a SaaS with the script.
Three constraints made the existing market useless. (1) Cloud tools stop working offline. (2) Multi-device tools require a shared backend, which means an account, which means the script lives on someone's server. (3) Voice-following teleprompters all used cloud speech-to-text, which streams your audio to a vendor — a non-starter for anyone who presents confidential material.
The Approach
A Vite + React 19 PWA for the editor and player, a tiny FastAPI service for the ephemeral relay, Redis for the relay store (5-minute TTL, delete-on-read), and Caddy as the reverse proxy with full security headers. No database, by design.
Four handoff modes with automatic fallback, because one size doesn't fit: - Single QR — payload embedded in a URL fragment ('#tp=v1.*'), never sent to the server. - Chunked multi-QR — for scripts past the 3,360-char QR limit (8KB compressed threshold), scan codes in any order. - LAN link — same Wi-Fi, no server hop at all. - Relay + OTP — for very large scripts (up to 256KB), the server holds the payload briefly with a one-time password.
The adaptive teleprompter was the interesting part. Voice-activity detection runs in the browser via the AudioContext 'AnalyserNode'. Stage directions, blockquotes, and '[DATACARD]' lines are detected and traversed at 3× while you're not speaking, then scroll pauses while you are. No cloud STT, no WebRTC, no audio upload — the raw audio never leaves the device. The spec explicitly excluded Web Speech API and cloud STT from v1 to protect that guarantee.
Markdown is rendered through markdown-it + DOMPurify with raw HTML stripped at input. A full GitHub Actions CI gate runs lint, typecheck, unit, and Compose validation in one job.
The Outcome
Shipped as v0.1.0, MIT-licensed, self-hostable in one 'docker compose up'. The player precaches via service worker so it works offline after the first load. Two e2e handoff scripts ('bin/e2e-handoff.sh', 'bin/e2e-offline.sh') gate every release.
The privacy posture turned out to be the feature people cited: "my mic never leaves the device" was the line that won the audience that wouldn't otherwise have touched a teleprompter.
Key Takeaway
Privacy isn't a feature you add at the end — it's an architecture constraint you commit to on day one. Deciding 'no cloud STT, no database, no account' in the spec is what made the rest of the design obvious.
Ready to Build Your Platform?
One 30-minute call to see if we're a fit. No pitch. No pressure. Just a conversation about what you need to build.
$20K–$25K for an MVP. $30K–$80K for a full platform. Fixed price, milestone-gated. 50% upfront.