Through the Looking Glass
Permanent direct links for RabbitHole Burrows. Announce your server's self-certifying Ed25519 descriptor and it becomes reachable at yourname.glass.rabbit.direct — live, verified, no DNS of your own required.
Generate an Identity
Your Burrow's identity is an Ed25519 keypair. The public key is your registration — the first announce claims your name and subdomain, bound to that key.
Sign & Announce
POST a signed descriptor to tracker.rabbit.direct/api/announce on an interval (default every 120s). No account, no token — the signature is the auth. Announces flow into the shared rabbithole.directory index in the same transaction.
Your Link Goes Live
Visitors to yourname.glass.rabbit.direct get a live connect card with your endpoints, verified in-browser against your key. Stop announcing and it goes dark.
Announce Protocol
Everything a Burrow needs to keep its direct link alive. Machine-readable version: GET tracker.rabbit.direct/api/announce
POST https://tracker.rabbit.direct/api/announce publish a signed availability descriptor GET https://tracker.rabbit.direct/api/resolve?slug=NAME resolve a burrow descriptor (JSON) GET https://tracker.rabbit.direct/api/burrows all active burrows (tracker + community glasses) GET https://NAME.glass.rabbit.direct human-readable connect card GET https://rabbithole.directory/api/burrows aggregated multi-glass directory index
{
"descriptor": {
"name": "alice@wonderland", // required: handle@host
"publicKey": "7d6c…f4a1", // required: raw Ed25519 key, 64 hex chars
"timestamp": 1783148188721, // required: epoch ms, ±300s of server time
"ttl": 120, // optional: announce interval seconds (30–3600)
"slug": "wonderland", // optional: subdomain label (default: host part of name)
"sysop": "Alice Liddell",
"description": "The flagship sanctuary Burrow.",
"plan": "Down the rabbit hole we go.",
"listeners": ["quic", "ws", "telnet"],
"endpoints": {
"quic": "quic://wonderland.co:4653",
"ws": "ws://wonderland.co:4654"
}
},
"signature": "base64 or hex Ed25519 signature over canonical JSON of descriptor"
}
- Canonical JSON: object keys sorted recursively at every level, no insignificant whitespace, UTF-8. Sign those bytes with your Ed25519 key.
- Liveness: announce at least every ttl seconds. Your link shows OFFLINE after 2Ă—ttl of silence and is pruned entirely after 7 days.
- Ownership: your name and slug bind to your public key on first announce — nobody else can claim them while you keep announcing (or for 7 days after you stop).
- Freshness: each announce must carry a newer timestamp than the last (replay protection), within ±300s of server time.
# one-shot announce (generates ./burrow-key.json on first run) node examples/announce.mjs --name alice@wonderland \ --endpoint quic=quic://wonderland.co:4653 \ --endpoint ws=ws://wonderland.co:4654 \ --listeners quic,ws --sysop "Alice Liddell" # keep the link alive from your server node examples/announce.mjs --name alice@wonderland \ --endpoint quic=quic://wonderland.co:4653 --interval 60