Deploy your own decentralized search index node.
A serverless SIP-01 search index relay — Nostr kind 39697 web-index observations on Cloudflare Workers + D1 + Durable Objects.
One shared decentralized index. Many independent indexers. Many independent search engines. No single owner.
WEB
│
┌─────▼──────┐ SIP-01 kind 39697 ┌────────────────┐
│ crawlers │ ─────────────────────▶ │ SIP-01 RELAYS │ ← this project
│ (Crawlstr, │ signed observations │ (Cloudflare) │
│ Indexstr) │ └───────┬────────┘
└────────────┘ │ NIP-50 / NIP-77
┌────────────────────┼─────────────────┐
┌─────▼─────┐ ┌───────▼──────┐ ┌──────▼─────┐
│ search │ │ other SIP-01 │ │ search │
│ engines │ │ relays sync │ │ nodes │
└───────────┘ └──────────────┘ └────────────┘
This is a fork of Nosflare (MIT) turned into the deployment layer for the SIP-01 ecosystem: anyone can run a validating, searchable, federating index relay with a Cloudflare account and a few clicks. See UPSTREAM.md.
- Validates at the door — every kind 39697 event is checked against the SIP-01 v1 schema: URL normalization (§7),
d↔uconsistency,x↔ content consistency, signatures, hard size caps. Invalid observations getOK false invalid: …and never reach the index. - Indexes for search — a document/observation/indexer model on top of the canonical event store: one document row per
d(URL identity), one observation row per live(pubkey, d), one indexer row per publishing key. Provenance is never merged. - NIP-50 search with web operators —
site:domain:url:inurl:title:topic:type:platform:category:network:country:mime:filetype:source:lang:before:after:distinct:domain, negations, plus relay-profileindexer:/x:/d:. - NIP-77 federation — negentropy set reconciliation so relays sync indexes efficiently:
["NEG-OPEN","sync",{"kinds":[39697]}, …]. - NIP-45 counts — cheap observation counts for dashboards and engines, including COUNT-with-search on kind 39697 and
distinct:authorindependent-indexer counts (relay-profile extension). - Crawler heartbeats — kind 16919 (indexstr/Crawlstr) accepted in
sip01mode, so the ecosystem's crawler-network health view works against this relay. - NIP-11 capability advertisement — including the
uncaged_indexSIP-01 block (SIP-01 §15). - Optional pay-to-relay — Bitcoin Lightning via Nostr zaps with cryptographically verified kind 9735 receipts. Payment is relay policy, never protocol.
- Optional hosted deploy service — sell relay deployments: customers sign in with Nostr, pay in sats (Lightning) or PRE (Presearch token on Base), and a stock relay is provisioned into their own Cloudflare account. Prices + receiving wallets are editable live from the owner's
/admindashboard. - Operator UI — landing page, live dashboard, search console, observation explorer with a client-side validator, indexer/document browsers, NIP-11 viewer, in-browser conformance tests, and a deployment wizard.
- Three modes —
sip01(dedicated index),hybrid(general relay + SIP-01),general(plain relay).
One click — Cloudflare clones the repo into your GitHub account, auto-provisions the D1 database + Durable Objects, builds, and deploys:
Or with the wrangler CLI (Node.js ≥ 20, wrangler ≥ 4.45 auto-provisions D1 on first deploy):
git clone https://github.com/NostrDanish/SIP-Booster-Relay.git
cd SIP-Booster-Relay
npm install
$EDITOR src/config.ts # relay name, mode, payment, indexer policy…
npx wrangler login
npx wrangler deployThen verify:
curl -H "Accept: application/nostr+json" https://your-relay.workers.dev
# → "uncaged_index": { "sip01": true, "nip50": true, "nip77": true, … }Point Crawlstr or indexstr at wss://your-relay.workers.dev and watch the dashboard fill with observations.
The full, non-technical walkthrough lives at the relay's own /deploy page (and in docs/DEPLOYMENT.md).
Read (any Nostr library, any SIP relay):
const events = await pool.query(relays, [{ kinds: [39697], '#t': ['nostr'], limit: 50 }]);
// group by d → count distinct pubkeys = independent indexer agreementSearch (NIP-50):
["REQ", "search", {
"kinds": [39697],
"search": "bitcoin privacy site:github.com lang:en after:2026-01-01",
"limit": 50
}]Sync (NIP-77 federation):
["NEG-OPEN", "sync", {"kinds": [39697]}, "<hex-encoded negentropy message>"]More: docs/API.md.
| Doc | Contents |
|---|---|
| docs/ARCHITECTURE.md | System design: Worker + DO mesh + D1 + SIP-01 tables |
| docs/DEPLOYMENT.md | Full deployment guide (wrangler, dashboard, git, button) |
| docs/CONFIGURATION.md | Every src/config.ts option |
| docs/SIP01.md | The relay's SIP-01 support profile |
| docs/NIP-COMPATIBILITY.md | Honest NIP support matrix |
| docs/SECURITY.md | Security model, threat surface, hardening |
| docs/FEDERATION.md | NIP-77 sync + relay discovery/registry |
| docs/OPERATIONS.md | Pruning, metrics, monitoring, capacity |
| docs/FREE-TIER.md | Cloudflare free-tier budgets: request/CPU/D1/DO limits, write math, tuning knobs |
| docs/TROUBLESHOOTING.md | Common problems and fixes |
| docs/API.md | WebSocket + HTTP API reference with examples |
| docs/TESTING.md | Conformance suite (browser + Node) |
| UPSTREAM.md | Nosflare lineage: inherited / modified / added |
npm test # canonical SIP-01 §13 vectors, NIP-50 parser, NIP-77 convergenceThe same suite runs in the browser at the relay's /tests page against the exact modules the Worker executes — one shared implementation (shared/), no drift.
Small community relays typically run inside Cloudflare's free tier; the design (hibernating Durable Objects, D1 read replication, compact index metadata) keeps large relays cheap. D1's size cap (5 GB free tier, hard-enforced) is handled by design: D1 holds compact searchable metadata, not the web. See docs/OPERATIONS.md.
MIT (see LICENSE). SIP-01 specification text is public domain.