Developers
Architecture
How wrentv.com, the web player, the address service and Wren TV accounts are built.
This page describes the hosted parts of Wren TV. For the big picture, start with how Wren TV works.
The website and web player
wrentv.com and watch.wrentv.com are one Cloudflare Worker with static assets:
| Host | Serves |
|---|---|
wrentv.com | The landing page and these docs |
www.wrentv.com | A redirect to wrentv.com |
watch.wrentv.com | The web player, a single-page app |
The Worker only serves static files. It never sees accounts or media:
- Sign-in goes from the browser straight to Wren TV accounts.
- Server discovery reads the account's servers with the user's token. Row-level security returns only the servers
the account owns or that are shared with it, with each server's
public_url,local_urlsandremote_url. - Connecting probes every address's
/api/serverat once and checks that itsserverIdmatches. LAN addresses win when they answer, then the owner'spublic_url, then the automaticremote_url. On an HTTPS page onlyhttps://addresses are tried, because browsers block http media there. - Browsing and playback go straight to that server with the access token as a bearer token. Streams use the
server's
/stream/{session}/…URLs (direct play, or HLS through hls.js), so media goes from the server to the browser and never through Cloudflare.
Wren TV accounts
Accounts run on Supabase (Postgres with row-level security):
| Table | Holds |
|---|---|
profiles | Display name and email for each account |
servers | Claimed servers: owner, name, addresses, version, library names, last heartbeat |
server_shares | Who a server is shared with, and which libraries (null means all) |
share_invites | Invites by email, turned into shares by accept_invites() when the invitee signs in |
Servers authenticate with a per-server secret through a few security-definer functions: claim_server,
server_heartbeat and server_access (which answers "what may this user do here?"). The secret's hash is in a
private schema no client can read. The publishable key in the web player is public by design.
The address service
api.wrentv.net is a second Cloudflare Worker that gives claimed servers HTTPS names under wrentv.net, like Plex's
plex.direct. 192-168-1-20.<id>.wrentv.net resolves to 192.168.1.20. Servers call it with their server ID and secret:
| Endpoint | Does |
|---|---|
POST /v1/addresses {lan, port} | Sets the records for the server's LAN addresses, plus its public IPv4 address when a connection back to port succeeds |
POST /v1/acme {values} | Sets or clears the _acme-challenge TXT record for the Let's Encrypt DNS-01 challenge |
GET /v1/ip | The caller's IP address |
The server then holds its own wildcard certificate for *.<id>.wrentv.net. A daily job removes the records of servers
that stopped checking in. The Worker only writes DNS records: media never passes through it.
These docs
The docs are Markdown files in the website repository's docs/ folder. npm run docs builds them into static pages
under /docs/, with the sidebar, search index and page outline, and checks every internal link.