Skip to content

Latest commit

 

History

11 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

RabbitHole Directory & Showcase 🕳️🐇

rabbit.direct — A modern Rust revival of the golden age of online communities: Hotline, KDX, BBSes, and AOL. One server, many doors.

This repository hosts the code for the RabbitHole Showcase & Looking Glass Directory (rabbit.direct), the central hub for the RabbitHole network. Built as a highly interactive, cyber-mystical Single-Page Application (SPA), it embodies the design language of Mirrorward and helps users discover active Burrows, download clients, and join the decentralized collective.

🌐 Production Site: rabbit.direct (Aliases: rabbithole.directory | rabbithole.direct)


Features

1. The Looking Glass Tracker Directory (LIVE)

A realtime, filterable status list of active, self-certifying Burrows, aggregated from Looking Glass publishes and streamed to every open browser via Server-Sent Events.

How data flows — the directory sits at the top of a two-tier gossip fabric:

Burrows ──(signed descriptors, RHP gossip)──▶ Looking Glass indexes ──(signed publishes, HTTPS)──▶ rabbithole.directory
          tracker.rabbit.direct:4650          official: tracker.rabbit.direct                      (this project)
                                              plus community-run glasses
  • Burrows never talk to this directory directly. They announce to a Looking Glass — the official coordinator at tracker.rabbit.direct (the glass.rabbit.direct project) via gossip_coordinators in burrow.toml.
  • Looking Glasses publish here. The official glass and any community-run glass POST their verified index views to POST /api/publish. Glass names are self-certifying Ed25519 identities (first-key-wins); the official glass is designated by name (tracker.rabbit.direct, overridable via the OFFICIAL_GLASS_NAMES env var) and labeled OFFICIAL in the UI — everyone else is COMMUNITY.
  • Double signature verification. Each publish is signed by the glass, and every relayed burrow entry carries the burrow's own signed descriptor envelope. The directory verifies both layers, so burrow identity continuity holds even across different glasses (first-key-wins per burrow name).
  • Realtime updates: the page subscribes to GET /api/events (SSE). New burrows appear, publishes flash rows, status flips online/offline without a reload, and gossip events print into the on-page terminal.
  • Real in-browser verification: for live burrows, "Verify Signature" re-verifies the actual relayed burrow envelope in your browser using WebCrypto Ed25519. The inspector also shows which glasses reported the burrow.
  • Observed uptime sparklines: live burrows get 7-day presence sparklines computed from report history (2-hour slots). A burrow is online if at least one fresh glass (~180s window) reports it online.

Directory API

Endpoint Description
POST /api/publish Looking Glass publish: { publish: { glass, burrows[] }, publicKey, signature }
GET /api/burrows Full directory snapshot (JSON): burrows, glasses, version, gossip log
GET /api/events SSE stream — emits a directory event (full snapshot) whenever the registry changes

Publish envelope — the outer signature is an Ed25519 signature (hex) over the canonical JSON of publish (keys sorted recursively, no whitespace); publicKey is the glass's raw 32-byte Ed25519 public key (hex). Each burrow entry independently carries the burrow's own key and signature over its descriptor:

{
  "publish": {
    "glass": {
      "name": "glass.example.net",   // required: hostname-like glass identity
      "ts": 1786500000000,           // required: unix ms, ±5 min of server time
      "operator": "Your Name",       // optional
      "url": "https://glass.example.net"  // optional
    },
    "burrows": [                     // ≤200 entries per publish
      {
        "descriptor": {
          "name": "alice@wonderland",   // persona@burrow
          "ts": 1786499990000,          // signed by the burrow ≤15 min ago
          "sysop": "Alice Liddell",
          "description": "",
          "plan": "",
          "listeners": ["quic", "ws"],  // subset of: quic ws tunnels telnet hotline finger radio nntp
          "quicUri": "quic://host:4653",
          "wsUri": "ws://host:4654"
        },
        "publicKey": "burrow key, 64-char hex",
        "signature": "burrow sig over descriptor, 128-char hex",
        "observed": { "status": "online" }   // optional glass-side observation
      }
    ]
  },
  "publicKey": "glass key, 64-char hex",
  "signature": "glass sig over publish, 128-char hex"
}

Publish every 60s; reports from a glass silent for ~180s go stale, and a burrow with no fresh online report is shown offline. Publishes are throttled to one per 10s per (glass, key). Invalid burrow entries are rejected individually (reported in the response) without failing the whole publish.

Run a community Looking Glass publisher with the zero-dependency reference client (generates and persists a glass Ed25519 identity in ~/.config/rabbithole/glass-keys/):

# Publish your glass's verified index (a JSON array of burrow envelopes):
node scripts/glass-publish.mjs --name glass.your-domain.net \
  --operator "You" --url https://glass.your-domain.net \
  --burrows ./verified-index.json --directory https://rabbithole.directory

# Or simulate a glass end-to-end (N locally-signed demo burrows):
node scripts/glass-publish.mjs --name glass.your-domain.net --demo 3 --once

Registry storage

The registry picks the best available backend at runtime (api/_lib/store.js):

  1. Upstash Redis (Vercel Marketplace) — durable, atomic. Attach with vercel integration add upstash/upstash-kv (requires one-time marketplace terms acceptance in the dashboard), then redeploy.
  2. Vercel Runtime Cache — used on deployments when Redis env vars are absent. Shared across functions per region but ephemeral (LRU) — the UI labels this EPHEMERAL STORE.
  3. Shared tmp file — local vercel dev fallback so full-stack dev works offline.

Seed showcase burrows (Wonderland/Matrix lore) populate the index on first boot and are labeled distinctly from live announcers; a real signed announce for a seed name takes the entry over.

2. In-Browser CLI Terminal Client

A fully simulated virtual CLI client mimicking the official rabbit client shell.

  • Burrow Connection Hook: Clicking "Connect via Console" on any active Burrow in the directory automatically scrolls to the console and initiates a connection prompt (ws://[burrow_uri]:4654).
  • Persona Authentication: Sign in (e.g. username alice, password wonderland) to enter the chat lobby and talk with virtual network personas (Neo, Morpheus, Hatter, Cheshire, etc.) specific to each Burrow.
  • Commands: Run standard commands like help, status, tunnels, warren, download, matrix, mirrors, and clear to control console themes and queries.

3. Architecture Showcase

Introduces the core concepts of the RabbitHole protocol (RHP):

  • Burrows: The self-hosted, sovereign node daemon written in Rust.
  • Tunnels: Peered server-to-server (S2S) secure replication links.
  • The Warren: Bao-verified, work-stealing P2P file swarming.
  • Legacy Doors: Backwards compatibility gate listeners for Telnet BBS (with ZMODEM & Door games), Hotline, Finger (RFC 1288), Icecast Radio (ICY DJ feeds), and NNTP/FidoNet newsfeeds.

Technology Stack

  • Structure: Semantic HTML5 (incorporating standard ARIA states and <dialog closedby="any"> for dismissible overlays)
  • Styling: Modern vanilla CSS (OKLCH color system, glassmorphism templates, CSS view timelines for scroll-driven reveals)
  • Logic: Vanilla ES Modules (canvas-based matrix rain, terminal emulator state engine, Gossip filter, EventSource live feed, WebCrypto Ed25519 verification)
  • API: Vercel Functions (api/) — signed-descriptor ingest, directory snapshots, SSE realtime stream
  • Storage: Upstash Redis via Vercel Marketplace (with Runtime Cache / tmp-file degraded modes)
  • Build System: Vite (asset bundling)
  • Deployment: Vercel

Local Development

Prerequisites

  • Node.js (v18+)
  • npm

Installation

  1. Clone the repository:

    git clone https://github.com/mirrorward/rabbit.direct.git
    cd rabbit.direct
  2. Install dependencies:

    npm install
  3. Spin up the full stack locally (static site + directory API + SSE):

    npx vercel dev

    (npm run dev runs the Vite static site only — the directory then runs in SHOWCASE mode without the live API.)

  4. Publish a simulated Looking Glass view against your local directory and watch its burrows appear live:

    node scripts/glass-publish.mjs --name glass.local-test.net \
      --demo 3 --directory http://localhost:3000 --once
  5. Build the optimized production assets:

    npm run build

Deployment & Domains

The project is configured for serverless hosting on Vercel:

  • Production CLI Deploy Command:

    npx vercel --prod
  • Configured Domains:

    • rabbithole.directory
    • rabbit.direct
    • rabbithole.direct
  • DNS Setup: To delegate your custom domain, set an A record pointing @ to 76.76.21.21.


Organization & Origin

RabbitHole is a flagship collective project under Mirrorward. Learn more about Mirrorward's cyber-mystical manifesto and software stack at:

🔗 mirrorward.co

Releases

Packages

Contributors

Languages