NIP Support
Nostr is defined by its NIPs : Nostr
Implementation Possibilities. Here’s where zig-nostr stands. Every “done” NIP
is covered by tests, and the cryptographic ones are verified against their
official specification vectors.
| NIP | Title | Status |
|---|---|---|
| 01 | Basic protocol: events, signatures, subscriptions, kind:0 profiles and kind:1 notes | ✅ done |
| 06 | Key derivation from a BIP-39 mnemonic, path m/44'/1237'/<account>'/0/0 | ✅ done |
| 09 | Event deletion, kind:5 (ingestion) | ✅ done |
| 19 | bech32-encoded entities: npub, nsec, note, nprofile, nevent, naddr | ✅ done |
| 21 | nostr: URI scheme | ✅ done |
| 42 | Client-to-relay authentication | ✅ done |
| 44 | Encrypted payloads (v2) | ✅ done |
| 46 | Nostr Connect, remote signing over kind:24133 | ✅ done |
| 49 | Private key encryption (ncryptsec) | ✅ done |
| 65 | Relay list metadata, kind:10002, what people call the outbox model | ✅ done |
That is the library surface, and all of it is done. What the roadmap commits to next is further down this page.
In the apps
The library gives an app the protocol. These are implemented above it, in Plaza, and are listed separately because they are client behaviour rather than library surface.
| NIP | Title | Where |
|---|---|---|
| 02 | Contact lists, kind:3 | reading and writing your follows |
| 05 | DNS identifiers, /.well-known/nostr.json | the name@domain handle on a profile, checked against the domain |
| 10 | Reply threading, marked e tags | threads, and replies you post |
| 18 | Reposts, kind:6 and kind:16 | counted on a note, and a row in notifications |
| 25 | Reactions, kind:7 | likes, in the feed and notifications |
| 27 | nostr: mentions in content | names instead of raw base32 |
| 89 | Application handlers | the client tag on notes you post |
| 92 | Media attachments, imeta | dimensions read off the tag, so an image reserves its box before it loads |
| 57 | Zaps, kind:9735 receipts | receipts are read and shown. Sending is a milestone away |
Planned, and where it lands
These are the specs the roadmap commits to, in roadmap order, each against the milestone that delivers it. None of it is written yet, which is what the status column says on every row. A spec named here is a promise: if one is missing, it is because I have not made that promise, not because I forgot it.
| Spec | Title | Milestone | Status |
|---|---|---|---|
| NIP-65 | Per-author routing on other people’s kind:10002 lists. The library side is done above, the routing is not | Reach | 🚧 planned |
| NIP-24 | Extra kind:0 fields (display_name, website, banner, bot, birthday), carried through untouched when I rewrite a profile | Your identity, and your key | 🚧 planned |
| NIP-50 | Search, which is a relay-side feature: a search string on an ordinary filter | Find anything, and keep it clean | 🚧 planned |
| NIP-51 | Lists: bookmarks (kind:10003) and the mute list (kind:10000) | Find anything, and keep it clean | 🚧 planned |
| NIP-24 | The t tag: a hashtag is a lowercase t, and NIP-01 single-letter indexing is what makes #t queryable | Find anything, and keep it clean | 🚧 planned |
| Blossom BUD-02 | Blob upload, PUT /upload. This is the step that puts the bytes of a picture on a server | Media worth looking at | 🚧 planned |
| Blossom BUD-03 | User Server List, kind:10063: which servers hold your blobs, most trusted first | Media worth looking at | 🚧 planned |
| Blossom BUD-11 | Authorization for those requests: a signed kind:24242 event carrying the verb and an expiry | Media worth looking at | 🚧 planned |
| NIP-92 | imeta written onto a note I post, not only read off one. It is what makes the picture render in someone else’s client | Media worth looking at | 🚧 planned |
| NIP-B7 | Finding a blob again: when a media URL ends in a sha256, retry it against the author’s kind:10063 servers and check the hash | Media worth looking at | 🚧 planned |
| NIP-71 | Video events: kind:21, and kind:22 for short portrait video | Media worth looking at | 🚧 planned |
| NIP-57 | Zaps you can send: a kind:9734 request to the recipient’s LNURL callback, and the kind:9735 receipt that follows the payment | Money, carefully | 🚧 planned |
| NIP-47 | Nostr Wallet Connect, so that invoice is paid in the app: a nostr+walletconnect:// link, over kinds 13194, 23194 and 23195 | Money, carefully | 🚧 planned |
| NIP-61 | Nutzaps: Cashu ecash sent straight to a pubkey (kind:9321), gated on a kind:10019 naming the mints you trust. No LNURL provider in the path, which is what makes a brand-new account payable | Money, carefully | 🚧 planned |
| NIP-60 | The wallet that holds what arrives: kind:17375 wallet, kind:7375 tokens, kind:7376 spending history, which NIP-61 reuses to mark a nutzap redeemed | Money, carefully | 🚧 planned |
| NIP-17 | Private direct messages: kind:14 chat, kind:15 files, and the kind:10050 relay list they are delivered to | Private messages | 🚧 planned |
| NIP-59 | Gift wrap, which does the wrapping NIP-17 defers: a kind:13 seal signed by me, inside a kind:1059 wrap signed by a throwaway key | Private messages | 🚧 planned |
| NIP-29 | Groups, which live on one relay: an h tag on every event, relay-published metadata (kind:39000), and join and leave requests (kind:9021, kind:9022) | Groups | 🚧 planned |
Blossom is not a NIP. It is a separate protocol with its own repository, hzrd149/blossom , and its documents are called BUDs rather than NIPs. It sits in this table because it is where file upload actually happens. A media list without it would be a list that cannot post a picture.
NIP-B7 is the Nostr side of the same story, and it is easy to mistake for the
upload spec. It is not one. It only says how to find a blob again, so a client
that implemented it and nothing else could not upload anything at all. The older
upload NIP, NIP-96 ,
is marked unrecommended in the NIPs repo and replaced by Blossom. I do not
implement it.
Zaps lean on something that is not a NIP either. The recipient’s LNURL pay
endpoint hands back the invoice, and it is that server, not my app, that signs
and publishes the kind:9735 receipt. A pubkey whose LNURL endpoint has not
opted into Nostr cannot be zapped at all.
That last sentence is the reason nutzaps are on the list rather than filed as a
duplicate of zaps. Lightning zaps only reach somebody who signed up with an
LNURL provider before you tried to pay them, so the people least likely to be
paid are the ones who just arrived. Ecash carries its own cost in exchange: a
mint is a custodian holding real value, both specs are draft and optional,
and client support is still thin. That belongs on screen when somebody picks a
mint, not buried in a setting.
Three milestones name no spec, and inventing one for them would be dishonest. Notifications is assembled out of NIPs already on this page: NIP-10 replies, NIP-18 reposts, NIP-25 reactions, NIP-27 mentions and NIP-57 zap receipts. Packaging, updates and diagnostics are not protocol work. Neither is a light theme, keyboard operation, or type that scales.
Named, and not doing
Refusing is a promise too, and these are the ones I get asked about. The roadmap has the rest.
- NIP-77 , set reconciliation. Relay support is thin and the protocol is easy to get subtly wrong. Per-relay cursors capture most of the benefit against a store that already answers a feed query in under a millisecond.
- NIP-96 , HTTP
file storage. Marked
unrecommendedin the NIPs repo and replaced by Blossom. Media goes through Blossom instead. - NIP-13 , proof
of work. No milestone needs it, and no mainstream relay I have checked
advertises a
min_pow_difficultyabove zero in its NIP-11 document. If that changes, reading the number and mining to it is a small piece of work, and I would rather do it then than promise it now.