# Build brief — a focused alternative to TeamViewer

> **Verdict:** Partly, if you narrow it · **Buildability:** 49/100 · **Category:** Dev Tools
> **Source:** https://www.canitbevibecoded.com/teamviewer
> Independent editorial assessment from Can It Be Vibe Coded? Not affiliated with, endorsed by, or derived from TeamViewer. Verify current pricing and capabilities before acting.

## Context

**TeamViewer** — Remote desktop control and remote support sessions across machines and platforms. It currently costs $24.90/mo.

If you only need to reach your own machines, most of TeamViewer's value is reproducible: screen capture, a WebRTC pipe, and synthetic mouse and keyboard events are all solved problems with libraries. An agent can wire that into a working host agent plus browser viewer in a focused implementation, and on your own LAN it will feel fine. What breaks is everything outside your control: connecting through hostile double NAT without your own TURN server, waking a sleeping box, keeping latency sane over mobile networks, and surviving OS permission prompts on macOS after every update. It also stops being a support tool, because the whole point of TeamViewer for helping your parents is that they can install one thing and read you a nine digit number. Build it for your own boxes, keep paying if you support other people's.

This brief describes a focused, single-operator replacement for the part of TeamViewer that is genuinely reproducible. It is deliberately narrower than the product it replaces, and it says so in writing. Build the useful core; do not pretend to have rebuilt the rest.

## What you are building

A host agent on each of your machines streams its screen over WebRTC to a password-protected browser viewer that injects your mouse and keyboard events back.

- Build the focused developer workflow you use repeatedly, with local configuration.
- A responsive interface with real empty, loading, success, and error states.

## Requirements

### Functional

- Node 20 on every machine you want to control.
- Ffmpeg installed on each host.
- A cheap always-on VPS for signaling and a coturn TURN server.
- Screen Recording and Accessibility permissions on macOS, or an X11/Wayland session that allows input injection on Linux.
- A domain with TLS, because getUserMedia and secure contexts will fight you otherwise.

### Non-functional

- Accessibility: semantic markup, labelled controls, visible focus, and reduced-motion support.
- Security: server-side secrets, validated input, and no credentials in the client bundle.
- Reliability: retries with backoff on external calls, and a clear failure state when a provider is down.
- Portability: the operator can export their data and leave without losing it.

## Implementation brief

Build a self-hosted personal remote desktop system: a host agent I run on machines I own, and a browser viewer I open to control them.

Stack, no substitutions:
- Node 20 + TypeScript for both host agent and signaling server.
- WebRTC via the werift library on the host side, plain browser WebRTC on the viewer side.
- ffmpeg (spawned as a child process) for screen capture and H.264 encoding.
- @nut-tree-fork/nut-js for mouse and keyboard injection on the host.
- Signaling over WebSocket (ws), single small server, no framework.
- Viewer is one static HTML file with vanilla JS and a canvas/video element. No React, no build step for the viewer.

Structure:
- /signal: WebSocket signaling server. Hosts register with an ID and a shared secret from .env. Viewers authenticate with the same secret, then get relayed SDP and ICE.
- /host: the agent. Captures the primary display with ffmpeg (avfoundation on macOS, gdigrab on Windows, x11grab on Linux), pipes encoded video into a WebRTC track, opens a data channel, and applies incoming input events with nut-js.
- /viewer: static page. Shows available hosts, connects, renders the video track, captures mouse move/down/up/wheel and keydown/keyup, normalizes coordinates to the remote resolution, sends them over the data channel.

Rules:
- All config in .env: SIGNAL_URL, SHARED_SECRET, HOST_ID, TURN_URL, TURN_USER, TURN_PASS. Ship .env.example. Never hardcode secrets.
- No accounts, no database, no telemetry, no cloud services beyond the signaling server and TURN that I run.
- Target 1080p at 25fps with a tunable bitrate and a keyframe interval short enough to recover fast. Prefer latency over quality.
- Data channel messages are small JSON objects, unordered, unreliable for mouse moves and ordered/reliable for clicks and keys.
- Include a --view-only flag on the host that ignores all input events.
- Log connection state transitions clearly so I can tell whether ICE failed or the encoder died.

Explicitly out of scope: file transfer, clipboard sync, multi-monitor selection, mobile clients, unattended wake, NAT traversal magic beyond standard STUN/TURN.

Deliverables: working code, one README with exact setup commands per OS, the macOS Screen Recording and Accessibility permissions steps, and a coturn config snippet I can drop on a VPS.

## Delivery standard

- Inspect the repository first, then write a short implementation plan before writing code.
- Deliver the smallest complete end-to-end workflow first; every primary control must work against persisted data.
- Use real validation and storage; never substitute fake dashboards, decorative controls, hard-coded success states, or mock integrations.
- Include responsive layouts plus genuine empty, loading, success, validation, and failure states.
- Keep secrets server-side in environment variables, provide .env.example, and never commit credentials or user data.
- Add structured logs around every external call and return actionable errors without leaking sensitive details.
- Write unit tests for the core logic and one automated test of the main user journey.
- Finish with a README covering setup, architecture, data location, backups, tests, deployment, and known limitations.

## Acceptance criteria

- [ ] A clean install starts the app using only the README and .env.example.
- [ ] The primary journey works from first visit through saved result, reload, edit, export, and deletion where applicable.
- [ ] Invalid input, missing configuration, provider failure, and an empty database each have a usable state.
- [ ] The interface works at 390px and 1440px, is keyboard navigable, and shows visible focus on every control.
- [ ] Tests, type checking, linting, and a production build all pass with no ignored failures.
- [ ] No part of the interface implies a live integration, security guarantee, or scale capability that was not actually built and verified.

## Non-goals

Do not build these, and do not claim to have replaced them:

- Connections that just work through carrier grade NAT, corporate firewalls, and proxies without you operating relay infrastructure.
- Native clients for Windows, macOS, Linux, iOS, and Android, plus mobile device support.
- The support workflow: a one-click download and a session code a non-technical person can read to you over the phone.
- Unattended access extras: wake on LAN, reboot and reconnect, multi-monitor switching, file transfer, session recording, printing.
- Commercial licensing, audit logs, and the corporate compliance story that makes IT allow it at all.

## What you still own after launch

- Run migrations, backups, restores, and dependency updates.
- Test the critical journey after every model, API, or hosting change.
- Monitor failures and fix the edge cases a first prompt will miss.

## Risk

**Operational risk.** The code is achievable; dependable data, integrations, and ongoing operations are the real cost.

Editorial confidence in this assessment: medium. No reviewed project implementation is linked yet.

---

Generated by [Can It Be Vibe Coded?](https://www.canitbevibecoded.com) · Full report: https://www.canitbevibecoded.com/teamviewer
