← back home colophon · how it's built
Colophon
What runs xmr.club, why we picked it, and what we deliberately rejected. Public so anyone auditing the site (or wanting to fork it) doesn't have to guess.
Runtime
- Cloudflare Workers — request-time SSR + JSON APIs at the edge.
- Cloudflare D1 — SQLite at the edge. Providers, audit log, reviews, sponsorships, onion-probe results.
- Cloudflare KV + R2 — hot caches + logo/OG storage + the public /data.json snapshot (CC-BY-4.0).
- Tor hidden service — independent container proxying to xmr.club, adding an
X-Onion-Origin header so the worker can rewrite outbound links to provider .onions. Fingerprint at /transparency.
Frontend
- SSR-first (Astro). Every public page renders meaningful HTML before any JS executes. Tested with Tor's safest mode + Lynx + curl. React only as islands where interactivity is needed (search, admin).
- No CSS framework. One hand-rolled stylesheet. Monochrome on bg + a single accent. Light / dark / auto themes.
- No analytics, no fingerprinting. No GA, no Plausible, no Cloudflare Web Analytics. We measure traffic via Cloudflare's request logs.
Data + content
- Provider records live in D1, edited via the admin worker. Every state change writes an audit row (visible at /audit) and busts the relevant edge cache key.
- Long-form guides — TypeScript modules under <code>lib/guides.ts</code>. Type-checked cross-links, schema.org HowTo blocks, per-guide JSON-LD without a build step.
- Onion verification runs on a daily cron. Drift is surfaced at /onion-audit.
- Open data.
/data.json + per-feed JSON twins. CC-BY-4.0.
AI-engine surface
- /llms.txt + /llms-full.txt — RFC-style index of every public surface for LLM crawlers.
- Per-page plain-text twins —
/llm/<page>.txt - JSON Feed v1.1 at /feed.json alongside Atom — preferred by modern crawlers.
Editorial bot
- @xmrclub_bot on Telegram — separate Cloudflare Worker at
bot.xmr.club, one-way notify webhook only. DM forwards into a private support group; replies relay back. The curator's personal Telegram is not exposed. - Submissions, corrections, and sponsorship inquiries all flow through the bot or /submit.
What we deliberately rejected
- No paywall, no signup, no email gate. Authority comes from being public-checkable. A gated directory cannot be cross-verified.
- No third-party tracking. No GA, no Hotjar, no Sentry session-replay. The price of a tracker is a privacy directory that doesn't believe its own thesis.
- No build-step CMS lock-in. Content edits land in D1 and appear within one edge-cache TTL. The renderer (now Astro SSR) is replaceable; the data layer is the source of truth.
- No "AI-generated reviews". Every review is hand-written by the curator. We use AI tools to draft schemas and audit code; we do not let an LLM grade a provider.
Stack we'd recommend to a fork
- If you're starting from scratch and want the same shape: Cloudflare Workers + D1 + KV. ~$5/month all-in until you cross 10M req/day.
- If you don't want Cloudflare: Bun + SQLite + Caddy works identically. SSR-first means edge isn't load-bearing — it's a latency optimisation.
- If you want a static fork (no D1): export /data.json, render with anything. License is CC-BY-4.0 with attribution.
Operating cost (transparency)
We deliberately do not publish a fixed "monthly bill" number. The runtime is Cloudflare Workers + D1 + KV + R2; the largest cost driver is D1 read pricing, which shifts with query patterns — a single month with unindexed scans can spike into the hundreds of dollars before the index lands. Real fixed costs (domain, .onion vanity prefix, onion-mirror VPS) are small; engineering + curator time dwarfs infra. See /transparency for the funding model.
Credits
See /heroes for the open-source projects and ecosystem actors xmr.club depends on. See /peers for the independent directories we cross-reference against.