Minimal examples for the TLTV Federation Protocol. Small, single-file implementations to help you understand the protocol and start building.
A channel server is the simplest TLTV node -- it generates a keypair, signs metadata, and serves an HLS stream. Each example below is a complete, conforming TLTV v1 channel in a single file.
| Example | Runtime | External Deps | Size |
|---|---|---|---|
| server/node/ | Node.js 18+ | None | ~90 lines |
| server/python/ | Python 3.9+ | cryptography |
~80 lines |
| server/go/ | Go 1.22+ | None | ~130 lines |
# 1. Generate test HLS content (requires ffmpeg)
server/generate-stream.sh server/node/media
# 2. Run a server
cd server/node && node server.mjs
# 3. Optionally verify with tltv-cli (https://github.com/tltv-org/cli)
tltv node localhost:8000 --local
tltv fetch TV...@localhost:8000 --local
tltv stream TV...@localhost:8000 --localNode.js (zero dependencies):
cd server/node && node server.mjsPython (one dependency):
pip install cryptography
cd server/python && python server.pyGo (zero dependencies):
cd server/go && go run main.goEvery example is a conforming TLTV v1 node:
- Generates an Ed25519 keypair on first run (saved to
channel.key) GET /.well-known/tltv-- Node discovery infoGET /tltv/v1/channels/{id}-- Signed channel metadataGET /tltv/v1/channels/{id}/stream.m3u8-- HLS manifestGET /tltv/v1/channels/{id}/*.ts-- HLS segmentsGET /tltv/v1/peers-- Peer exchange (empty list)- CORS headers and JSON error responses on all endpoints
| Env Var | Default | Description |
|---|---|---|
PORT |
8000 |
Listen port |
CHANNEL_NAME |
(varies) | Channel display name |
MEDIA_DIR |
./media |
Directory containing HLS files |
Generate a 30-second test pattern with ffmpeg:
server/generate-stream.sh <example>/mediaWithout a stream, the server still works -- metadata and node info are served
normally, and the stream endpoint returns 503 stream_unavailable.
A relay caches and re-serves public channels from an upstream origin. Unlike a channel server, a relay holds no private key -- it verifies signed metadata from upstream and serves it verbatim. Any node can relay a public channel without permission.
| Example | Runtime | External Deps | Size |
|---|---|---|---|
| relay/node/ | Node.js 18+ | None | ~110 lines |
| relay/python/ | Python 3.9+ | cryptography |
~170 lines |
| relay/go/ | Go 1.22+ | None | ~230 lines |
# 1. Start an origin server (terminal 1)
server/generate-stream.sh server/node/media
cd server/node && node server.mjs
# 2. Start a relay pointing at the origin (terminal 2)
cd relay/node && UPSTREAM=localhost:8000 node relay.mjs
# 3. Verify the relay (terminal 3)
tltv node localhost:9000 --localNode.js (zero dependencies):
UPSTREAM=localhost:8000 node relay/node/relay.mjsPython (one dependency):
pip install cryptography
UPSTREAM=localhost:8000 python relay/python/relay.pyGo (zero dependencies):
cd relay/go && UPSTREAM=localhost:8000 go run main.goEvery example is a conforming TLTV v1 relay node:
- Discovers channels from upstream's
/.well-known/tltv - Verifies Ed25519 signatures on metadata (no private key)
GET /.well-known/tltv-- Lists relayed channels (underrelaying, notchannels)GET /tltv/v1/channels/{id}-- Cached signed metadata, served verbatimGET /tltv/v1/channels/{id}/stream.m3u8-- Cached HLS manifestGET /tltv/v1/channels/{id}/*.ts-- Cached HLS segmentsGET /tltv/v1/peers-- Peer exchange (empty list)- Polls upstream for metadata (60s) and HLS content (2s)
- Stops relaying channels that go private, on-demand, or retired
- CORS headers and JSON error responses on all endpoints
| Env Var | Default | Description |
|---|---|---|
PORT |
9000 |
Listen port |
UPSTREAM |
localhost:8000 |
Upstream origin host:port |
All examples store keys as hex-encoded 32-byte Ed25519 seeds in channel.key.
This is the same format tltv-cli keygen produces, so keys are interchangeable.
- Protocol Spec -- Full TLTV v1 specification
- tltv-cli -- CLI for interacting with the network
MIT -- see LICENSE.