<oembed><type>rich</type><version>1.0</version><title>Innis wrote</title><author_name>Innis (npub1l3…5cxyz)</author_name><author_url>https://yabu.me/npub1l33660awkeycecn9grhrvzyn0fmes8245ke7k82y8njz8uqu3vlqk5cxyz</author_url><provider_name>njump</provider_name><provider_url>https://yabu.me</provider_url><html>Shipping two libraries today: nostr-relay-selection in TypeScript and PHP. They answer one question: given a Nostr event, which relays should it go to. Covers outbox publish routing, NIP-17 DMs, NIP-65 list parsing, author set-cover, e/p relay hints.&#xA;&#xA;Both libraries are pure functions. No state, no I/O, no caches, no fallback URLs, no tie-breaks by Math.random or time decay. Same inputs, same outputs, every time.&#xA;&#xA;The existing implementations (NDK&#39;s OutboxTracker, rust-nostr&#39;s gossip, go-nostr&#39;s sdk, welshman/router) are engines: stateful, heuristic, coupled to a pool. None are deterministic.&#xA;&#xA;These libraries take the opposite trade. They are a spec. The TypeScript and PHP ports share a JSON corpus of test vectors. A vector that passes in one passes in the other. A Go or Rust port joins the same compliance suite or it doesn&#39;t conform.&#xA;&#xA;If you&#39;re building a client, a relay, a bot, an indexer, the win is having routing live behind one auditable path. One place that knows the NIPs. One set of vectors that decide whether the answer is right. When NIP-65 grows a marker or NIP-17 tightens a rule, you update the library and every caller gets the new policy.&#xA;&#xA;Post-spec decisions belong in an adapter at the boundary. Onion-only routing for a privacy build, dropping unresponsive relays based on pool state, home-relay ordering, scoring by past success — whatever your runtime knows that the spec doesn&#39;t. The library returns the NIP-derived answer; the adapter overlays your application&#39;s intuition on top.&#xA;&#xA;In use across the rest of my Nostr stack, to be released soon. I&#39;m also putting these out because I want them stress-tested by people who have shipped more Nostr than I have. If you spot a corpus (Claude&#39;s favourite word right now) vector that&#39;s wrong, a NIP rule I&#39;ve misread, or a routing decision you&#39;d make differently, the issue tracker is open.&#xA;&#xA;deno add jsr:@innis/nostr-relay-selection&#xA;https://github.com/johninnis/nostr-relay-selection-ts&#xA;&#xA;composer require innis/nostr-relay-selection&#xA;https://github.com/johninnis/nostr-relay-selection-php&#xA;&#xA;MIT.&#xA;&#xA;#nostr #typescript #php #opensource #nostrdev</html></oembed>