Skip to content

About

Nostr search engine

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

Β 

History

45 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

0xSearchstr

Decentralized search aggregator. Nostr first, web when needed. No backend required.

Live: https://0xSearchstr.shakespeare.wtf Β· nsite mirror: https://0xsearchstr.shakespeare.to

Nostr: npub1z2k4ttglmwgc75c5e856tngnt05mw3hxams4lkr3muf354nh6xvskk2ew6

Sister app: 0xPresearchstr β€” same engine, shared index (see Federation)

Edit with Shakespeare


How It Works

User Search
       β”‚
       β–Ό
 β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ All providers run in parallel ──────────────┐
 β”‚                                                             β”‚
 β”‚  Nostr (NIP-50)  SearXNG   Wikipedia   Hacker News   Tor   β”‚
 β”‚       β”‚              β”‚          β”‚           β”‚          β”‚    β”‚
 β”‚  Web Index     DuckDuckGo  Stack Overflow   Community      β”‚
 β”‚  Cache Index        β”‚          β”‚              Index         β”‚
 β”‚       β–Ό              β–Ό          β–Ό              β–Ό             β”‚
 β”‚   SearchResult[] from each provider                         β”‚
 β”‚                                                             β”‚
 β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                        β”‚
              Instant Answer? (calculator Β· npub Β· Wikipedia)
                        β”‚
                   Merge + Deduplicate + Rank
                        β”‚
                        β–Ό
                   Display Results
                        β”‚
                   Still nothing?
                        β”‚
                        β–Ό
              Trending cached queries + Browser Fallback Links

Instead of building another centralized search engine, 0xSearchstr is a search aggregator with a plugin-based provider architecture:

  1. Every source is a provider β€” each returns a universal SearchResult[]
  2. All providers run in parallel β€” results stream in as each completes
  3. Nostr scores highest β€” decentralized results are prioritized
  4. Auto-indexing β€” every search publishes discovered pages back to Nostr as document observations (never the query)
  5. Community-curated β€” any Nostr user can submit links to the shared index
  6. Never leaves you empty β€” trending cached queries + fallback links to privacy-respecting search engines

Everything runs in the browser. No backend, no crawler, no tracking.


Features

πŸ”¦ Honest Privacy (traffic-light indicator)

Every provider is classified by who can see your query, and a traffic-light indicator sits next to the search bar at all times:

Light Tier Providers Who sees the query
🟒 Nostr Cache Index, Nostr, Community Relay operators only (query + IP, no account linked)
🟑 Direct Wikipedia, Hacker News, Stack Overflow The API operator (query + IP in standard logs)
πŸ”΄ Proxied SearXNG, DuckDuckGo, Ahmia A CORS proxy and the destination service
  • Privacy Mode (Settings) β€” one switch to run Nostr-tier providers only. Zero third-party exposure, at the cost of fewer results.
  • The full, honest threat model lives on the About page. "No backend" β‰  "no one sees anything" β€” we document exactly who does.

⚑ Instant Answers

Direct answers above the result list, no waiting:

  • Calculator β€” 2^10, (3+4)*5, 15% of 80 β€” safe recursive-descent parser, computed locally, never sent anywhere
  • Nostr profiles β€” paste a bare npub1… / nprofile1… β†’ rich profile card (avatar, banner, NIP-05, bio)
  • Wikipedia summaries β€” strong title matches render the article's first paragraph + thumbnail (auto-disabled in Privacy Mode)

πŸ—‚ Community Index (curated by Nostr users)

The index isn't just a bot cache β€” any logged-in Nostr user can submit links (kind 30078, signed with their own key) via the Submit button. Submissions support https://, magnet:, ipfs://, and .onion links with automatic content-type detection (Torrent, IPFS, Video, Audio, PDF badges).

  • URL allowlist blocks javascript:/data: at parse time; onion submissions render behind a Tor warning interstitial
  • Independent project, credit where due: 0xSearchstr was built on its own, but the idea of letting every user curate the index β€” not just bots and crawlers β€” was adopted after we discovered Nostra Search, a project exploring the same territory. Thanks for the spark. Our implementation is our own, with an improved schema (unique per-URL d-tags fix their one-entry-per-author limitation)
  • Nostra read-interop: we also read Nostra Search's own index (nostra:index), including their AES-GCM obfuscated payloads β€” their community's curation shows up here, attributed as "Nostra Index"

🌐 Federation: One Index, Many Clients

The Search Index Protocol (kind 39697, canonical spec: SIP-01/SIP-01) is shared with 0xPresearchstr, the UNCAGED Index Relay, the Crawlstr + indexstr crawler network, and open to any fork or third-party engine. Every browser is its own indexer β€” there is no central signing key:

  • Per-device identity β€” each browser generates its own indexer keypair on first use (Settings β†’ Indexing). Pseudonymous, replaceable, exportable.
  • Independent observations β€” when indexer A and indexer B both see example.com, they publish separate events with the same d tag. Search nodes count distinct indexers per document β€” "7 independent indexers saw this page."
  • Any relay works β€” plain Nostr filters (#d, #t) on ordinary relays; NIP-50 is an optional acceleration, never a requirement.

The legacy query cache (kind 30078, 0xsearchstr:cache:*) remains federated with 0xPresearchstr during migration β€” readers trust both bot pubkeys, and old clients keep a warm cache. Full legacy spec in NIP.md.

πŸ” Explore the Index

/explore turns the index into discoverable content: recently indexed pages (with independent-indexer counts), trending terms, staked keywords, and aggregate stats. Every search becomes content.

πŸ’Ž Keyword Staking (Presearch-style, Nostr-native)

Stake your identity on a keyword instead of tokens: sign an addressable kind 30078 event (0xsearchstr:stake:<keyword>) binding a keyword to your link. Anyone searching that keyword β€” on any compatible client β€” sees your link as the top "Community Stake" placement. One stake per keyword per npub; re-staking replaces it. No tokens, no auction.

πŸ‘ Voting & Reporting

Every result card carries πŸ‘/πŸ‘Ž votes and a report flag:

  • Votes are NIP-25 reactions (kind 7; e tag for events, r tag with the SIP-01-normalized URL for pages). Anonymous by default β€” signed by this device's indexing identity, never your npub. Settings β†’ Indexing has an opt-in "vote with my npub" toggle.
  • Reports are NIP-56 kind 1984 events (0xsearchstr.abuse namespace), landing in the team's /admin inbox.

πŸ“ˆ Trending Terms (k-anonymity)

Trending searches with no plaintext queries anywhere: each device publishes only sha256(normalized query) under its indexing identity (0xsearchstr:term:*). A term's plaintext is revealed by the network only once 3+ independent devices searched it β€” the reveal is self-verifying (readers re-hash and compare). Rare or sensitive queries (NIP-19 ids, NIP-05 addresses, URLs, math) are never signaled at all.

πŸ›‘ Team Console (/admin)

A hidden, role-gated dashboard (not linked in nav β€” team members see "Admin console" in their account menu when logged in with a team key):

  • Stats β€” indexed pages, stakes, open reports, relay pool sizes
  • Reports β€” the NIP-56 abuse inbox, one-click "hide from results"
  • Moderation β€” team-signed NIP-32 labels (kind 1985, 0xsearchstr.moderation) hide URLs/event ids from every user's results; un-hiding publishes a NIP-09 deletion. Clients trust labels from the owner + role-list pubkeys only
  • Roles (owner) β€” add/remove admins & moderators by npub (owner-signed 0xsearchstr:admin-roles / 0xsearchstr:mod-roles addressable events)
  • Filter test β€” check whether a URL or event id is currently filtered

πŸ€– AI Answers (optional, off by default)

An AI answer layer sits on top of the federation: the top results become a numbered evidence pack, the model answers only from it, with clickable [n] citations. Ephemeral β€” never indexed into SIP-01. Tiers: your own key (BYOK β€” PPQ.ai, OpenRouter, Ollama, any OpenAI-compatible endpoint) β†’ a built-in free tier (shared rate-limited PPQ key, public by design). Privacy boundaries hold: NIP-19/05, URLs, and math keep their deterministic paths; Nostr results are excluded from evidence unless you opt in.

⌨️ Quality of Life

  • OpenSearch β€” add 0xSearchstr as a browser search engine (/opensearch.xml)
  • Keyboard shortcuts β€” Ctrl+K / Cmd+K or / focuses the search bar from anywhere
  • Shareable searches β€” ?q=query&source=web URL params
  • Smart snippets β€” Nostr notes show the relevant window around your query terms (Google-style), not just the note head; hashtag/link-stuffed spam is filtered out
  • Graceful degradation β€” a failing provider shows a muted "skipped" state instead of a red error when others delivered

Auto-Indexing (Shared Web Index)

The killer feature: every search grows the index.

When you search, useful web results are published to Nostr as document observations β€” one lightweight, addressable event per URL (kind 39697, SIP-01), signed by this browser's own dedicated indexing identity. No account, no login, no central signing key β€” and your search query is never published, only the pages' public metadata.

Search "best monero wallet"
       β”‚
       β”œβ”€β†’ Read the shared web index (kind 39697) + legacy cache (kind 30078)
       β”‚     └─→ HIT? β†’ instant results from Nostr
       β”‚
       β”œβ”€β†’ Run all providers in parallel
       β”‚     └─→ Merge + deduplicate + rank
       β”‚
       └─→ Index the useful pages (auto-index)
             β”œβ”€β†’ kind 39697 per URL, signed by your device's indexer key
             └─→ every compatible client can now find those pages

Indexing identity: each browser generates its own keypair on first use (Settings β†’ Indexing). It is pseudonymous, replaceable, exportable, and never linked to your personal Nostr identity. Key separation is guaranteed; network anonymity is not (relays see IP/timing β€” be honest about that).

The more people use any compatible client, the smarter every client gets. No crawler. No database. Just Nostr.

Migration note: the legacy query→results cache (kind 30078) is frozen legacy data (SIP-01 §17) — 0xSearchstr still reads it for backward compatibility with 0xPresearchstr and older clients, but no longer writes it. The only signer in this codebase is the per-device indexing identity.


Quick Start

git clone https://github.com/NostrDanish/0xSearchstr.git
cd 0xSearchstr
npm install
npm run dev

Open http://localhost:8080 and search.


Provider Architecture

src/lib/providers/
β”œβ”€β”€ types.ts          ← SearchResult, SearchProvider interface (privacy tiers!)
β”œβ”€β”€ web-index.ts      ← Shared web index β€” SIP-01 kind 39697 observations (reads first)
β”œβ”€β”€ cached-index.ts   ← Legacy federated query cache (kind 30078, read for compatibility)
β”œβ”€β”€ nostr.ts          ← NIP-50 relay search
β”œβ”€β”€ stakes.ts         ← Keyword stakes (Presearch-style top placements)
β”œβ”€β”€ community.ts      ← Community-curated index (+ Nostra Search interop + NIP-B0)
β”œβ”€β”€ git.ts            ← NIP-34 repos/issues/PRs (ngit/GRASP pool, read-only)
β”œβ”€β”€ wiki.ts           ← NIP-54 wiki articles (wikifreedia pool, read-only)
β”œβ”€β”€ brave.ts          ← Brave Search API (BYOK, off by default)
β”œβ”€β”€ searxng.ts        ← SearXNG meta-search with failover
β”œβ”€β”€ duckduckgo.ts     ← DuckDuckGo HTML scraper
β”œβ”€β”€ wikipedia.ts      ← MediaWiki API
β”œβ”€β”€ hacker-news.ts    ← Algolia HN Search API
β”œβ”€β”€ stackoverflow.ts  ← StackExchange API
β”œβ”€β”€ tor.ts            ← Ahmia.fi .onion search
β”œβ”€β”€ registry.ts       ← Provider catalog (+ per-engine enable/disable)
└── index.ts          ← Barrel export

src/lib/
β”œβ”€β”€ webIndex.ts        ← SIP-01 protocol: URL normalization, build/parse/verify
β”œβ”€β”€ indexerIdentity.ts ← Per-device anonymous indexer keypair
β”œβ”€β”€ keywordStakes.ts   ← Stake schema (0xsearchstr:stake:*)
β”œβ”€β”€ termSignals.ts     ← k-anonymity trending (0xsearchstr:term:*)
β”œβ”€β”€ votes.ts           ← NIP-25 result votes (device identity by default)
β”œβ”€β”€ reports.ts         ← NIP-56 abuse reports (0xsearchstr.abuse)
β”œβ”€β”€ moderation.ts      ← NIP-32 team labels (0xsearchstr.moderation) + roles
β”œβ”€β”€ queryClassify.ts   ← Query understanding (URL/nip19/nip05/math detection)
β”œβ”€β”€ resultRank.ts      ← Coverage-ranked result merging
└── ai/                ← Optional AI answer layer (BYOK + built-in free tier)

Adding a Provider

  1. Create src/lib/providers/my-provider.ts implementing SearchProvider
  2. Import it in registry.ts and add to ALL_PROVIDERS
  3. Done β€” the orchestrator picks it up automatically

SearchProvider Interface

interface SearchProvider {
  id: string;
  name: string;
  source: SearchSource;
  /** Extra tabs this provider also runs under (e.g. community runs under 'tor' too) */
  additionalSources?: SearchSource[];
  /** Privacy tier β€” who can observe the query. Drives the traffic-light + Privacy Mode. */
  privacy: 'nostr' | 'direct' | 'proxied';
  /** Honest one-liner about who sees the query (shown in the privacy popover). */
  privacyNote: string;
  search(options: SearchOptions): Promise<ProviderSearchResponse>;
}

Live Providers

Provider Source API Privacy Notes
Web Index Nostr kind 39697 WebSocket 🟒 Nostr Shared document observations from all indexers (SIP-01), integrity-verified (d↔u, x↔content)
Cache Index Federated Nostr index WebSocket 🟒 Nostr Legacy query cache, read-only (frozen) β€” off by default
Nostr NIP-50 relays WebSocket 🟒 Nostr UNCAGED + community default relays, fully user-editable
Keyword Stakes Nostr kind 30078 WebSocket 🟒 Nostr Community-staked keyword placements
Community Nostr kind 30078 + 39701 WebSocket 🟒 Nostr User-submitted links + NIP-B0 bookmarks + Nostra Search index
Git Repos ngit/GRASP relays (NIP-34) WebSocket, read-only 🟒 Nostr Repos, issues, PRs & patches β€” pool editable in Settings
Nostr Wiki Wiki relays (NIP-54) WebSocket, read-only 🟒 Nostr Wikifreedia corpus β€” pool editable in Settings
SearXNG Dynamic instance pool CORS proxy πŸ”΄ Proxied DDG, Brave, Wikipedia, and dozens more
DuckDuckGo HTML scraper CORS proxy πŸ”΄ Proxied Direct DDG fallback when SearXNG is slow
Brave Brave Search API CORS proxy πŸ”΄ Proxied Off by default β€” BYOK in Settings β†’ Engines
Wikipedia MediaWiki API Direct (CORS) 🟑 Direct Off by default β€” enable in Settings β†’ Engines
Hacker News Algolia API Direct (CORS) 🟑 Direct Stories with points/comments
Stack Overflow StackExchange API Direct (CORS) 🟑 Direct Off by default β€” enable in Settings β†’ Engines
Tor (Ahmia) HTML scraping CORS proxy πŸ”΄ Proxied Off by default β€” policy-compliant .onion search

Every engine can be toggled off in Settings β†’ Search Engines β€” off engines never run and never see your query. The tab bar is modular too: Settings β†’ Search Tabs picks visible tabs, order, and the default landing tab.

Dynamic SearXNG Instance Pool (searxist-style)

Instead of a hardcoded instance list, the SearXNG provider uses a self-healing dynamic pool (inspired by searxist):

β”Œβ”€β”€ Tier 1: Custom ──────┐   Your self-hosted / trusted instances (always first)
β”œβ”€β”€ Tier 2: Discovered ───   Live from searx.space, privacy-filtered:
β”‚                        β”‚     β€’ no analytics  β€’ clearnet  β€’ β‰₯80% search success
└── Tier 3: Seeds β”€β”€β”€β”€β”€β”€β”€β”˜   Hardcoded bootstrap fallback
  • Auto-discovery β€” the pool refreshes from searx.space every 24h, client-side
  • Quality-aware health tracking β€” per-instance success/failure/latency and result-count stats (EMA) in localStorage; failing or thin instances sink, fast and complete ones rise
  • Self-hosting friendly β€” add your own instance in Settings and it runs first on every search
  • Zero backend β€” discovery, health, and ranking all happen in the browser

Relay Management

Two layers, both manageable at /settings:

  • Your Relays (NIP-65) β€” your personal relay list with read/write flags; publishes kind 10002 when logged in. Defaults to the 0xSearchstr app relays for new users.
  • Search Relays (index pool) β€” the pool that powers Nostr search, the shared web index, and index publishing. Defaults: the UNCAGED index relay (relay-na1.metanomalist.com), community NIP-50 relays (ditto, jskitty.cat, nos.today, nostr.band, noswhere), Primal + Hifish for replication, and a Tor index relay (.onion). Every default is removable β€” removed defaults can be restored, and customs (including your own self-hosted NIP-50 relay) can be added. A built-in latency tester checks reachability and round-trip times. The .onion relay is only contacted when the app itself runs on a .onion origin β€” on clearnet it's skipped silently (a connection could never succeed, and on devices with a local Tor resolver the attempt trips Chrome/Brave's local-network permission prompt).

Incremental Results

All providers run in parallel. The UI shows live status:

βœ” Nostr (124ms)  βœ” Wikipedia (230ms)  ⏳ SearXNG...  ⏳ HN...

Results appear as each provider finishes β€” no waiting for the slowest one.


Search Tabs

The tab bar is fully modular β€” Settings β†’ Search Tabs lets every user pick which tabs show, reorder them, and star the tab a fresh visit starts on. Deep links (/?source=tor&q=…) keep working even for hidden tabs.

Tab Sources
Web Web Index (SIP-01) + Stakes + Community + SearXNG + DuckDuckGo + Brave (BYOK)
Index The community index only β€” SIP-01 observations + legacy cache
All All providers merged + ranked (stakes on top)
Nostr Profiles, notes, articles, Wikifreedia, files, torrents, code snippets
News Hacker News stories
Wiki Nostr wiki articles (NIP-54 pool); Wikipedia engine off until enabled
Code Git repos/issues/PRs (NIP-34 via ngit/GRASP) + NIP-C0 snippets; Stack Overflow off until enabled
Tor .onion hidden services via Ahmia + index-observed onion pages
I2P Eepsite directory links + index-observed eepsites

Self-Hosted Backend (Optional)

The backend/ directory contains a full self-hosted stack for when you want to run your own search infrastructure:

Service Description
Meilisearch Full-text search index engine
Nostr Crawler NIP-01 subscriber indexing kinds 0/1/30023/1063
Clearnet Crawler Polite web crawler (robots.txt, rate-limited)
Tor/I2P Crawler Hidden service crawler with content policy enforcement
NIP-50 Relay Search relay proxy bridging Meilisearch to Nostr
Abuse API REST search API + abuse report management
cp .env.example .env   # Edit MEILI_API_KEY + ABUSE_ADMIN_TOKEN
docker compose up -d

See the backend README and Content Policy for details.


Protocol Spec

The interoperable web-document index is specified by SIP-01 β€” canonical spec at github.com/SIP-01/SIP-01 (kind 39697) β€” designed so an independent developer can implement a compatible indexer, search node, or search engine without reading this codebase. 0xSearchstr's implementation is byte-compatible with the spec's Β§13 test vectors (see docs/SEARCH_INDEX_PROTOCOL.md).

App-specific legacy schemas β€” the federated query cache, community submissions, trusted indexer list, and Nostra Search interop β€” are documented in NIP.md.


Content Policy

The self-hosted backend enforces content policy modeled on Ahmia. Hard-blocked categories: CSAM, human trafficking, weapons sales, drug marketplace listings. See the Policy page for details.


Tech Stack

  • React 19 + TypeScript + Vite
  • TailwindCSS 4 + shadcn/ui
  • Nostrify β€” NIP-50 relay search
  • SearXNG β€” meta-search fallback
  • Wikipedia β€” MediaWiki API
  • Hacker News β€” Algolia search
  • TanStack Query β€” data fetching + caching

License

MIT


Vibed with Shakespeare

About

Nostr search engine

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages