Roadmap
zig-nostr is a protocol library in Zig, the native apps that prove it on real product surfaces, and the docs around both. This is what has shipped, and what comes next.
No dates.
Shipped
- Library core: secp256k1 keys and BIP-340 Schnorr signatures (bitcoin-core’s libsecp256k1), the NIP-01 event model, NIP-19/21 encoding, NIP-06 derivation, and NIP-49 key storage. Passes the full official BIP-340 test-vector suite.
- Transport and outbox: RFC 6455 WebSocket, a relay connection state machine with NIP-01 subscriptions, a live TCP/TLS dialer, and NIP-65 relay lists (kind 10002), the routing people call the outbox model, with zero hardcoded relays.
- Local-first store: a zero-copy, memory-mapped LMDB event store with a bounded, newest-first planner for NIP-01 filters. Sub-millisecond feeds that stay flat as the store grows.
- Signer protocol: NIP-44 v2 encryption, the NIP-46 remote-signing (“bunker”) protocol over kind 24133, and NIP-42 client authentication.
- Windows, search and fuzzing in the library: it builds for macOS, Linux and Windows, on
x86_64 and aarch64, with CI that builds and tests on all three. The filter carries the NIP-50
searchfield, which the local store applies too. The parsers that read bytes someone else wrote have fuzz targets, and the two crashes the first run found are fixed. - Notary, the native remote signer. Your key lives in a local daemon, it hands
you a
bunker://URL, and nothing gets signed quietly. A downloadable app for macOS and Linux. On macOS it stays in the menu bar and shows its window only when a request needs a decision. - deed, the fastest and smallest nostr command line: keys, events, NIP-19 codes, NIP-44, relay queries and publishing, and a local store that later runs read without a network. It builds for macOS, Linux and Windows.
- Plaza, the flagship client. Browse as a guest, sign in three ways (including a NIP-46 bunker), and read a follow feed (your kind 3 list) that renders from disk before the network answers. Reposts from people you follow appear in it, hashtags open a page of their notes, and relay hints are carried in the addresses it copies and the replies, quotes, reposts and likes it publishes. A long-form article (NIP-23) opens in a reader. Search finds people by name, from the profiles on your machine first and then from three NIP-50 search relays. A picture can be added from a file to a note, an avatar or a banner, and uploads go to a Blossom server from your list. A note marked sensitive (NIP-36) is covered until you press Show, and the composer can add a content warning. A relay that asks who you are (NIP-42) is answered once you allow it, per relay and per account. Every profile field is editable, deleting your own note is there, and something Plaza cannot draw shows a card naming its kind.
- Places: a link opens somebody’s corner of Nostr, their relays and what they serve, and while you are in one you see it rather than your own feed. Visit, enter to keep it on a rail, or leave. A community can carry several feeds and switch between them, and one that states a colour is drawn in it. The format is fiatjaf’s Hallway universe object, and the field names are his exactly, so a document written for one is read the same way by the other.
- Docs and benchmarks: this site, the NIP-support table, and reproducible performance numbers.
- Reach: following somebody means seeing them. Plaza reads the NIP-65 relay lists (kind 10002) of the people you follow, works out which relays reach the most of them, connects to the ones you are not already on, and asks each relay only about the people who write there. Anybody no chosen relay carries is asked of your own relays, so nobody falls through. What you post goes where your own list says it should, and scrolling past what is on disk asks the relays for older notes.
What comes next
The library from other languages
A C ABI over the library: keys, events, NIP-19, NIP-44, relay reads and the local store, with a C header. On top of it, Swift bindings published as a Swift package. The C ABI and the Swift package are both tested in CI.
Notary on Windows
Notary packaged for Windows, so the library, deed and Notary are each tested in CI on Windows, macOS and Linux.
deed for agents
deed mcp serves deed’s verbs over the Model Context Protocol, so an agent can read relays, query the local store and verify events. Anything that signs goes through a NIP-46 signer that asks first.
An app engine
I am extracting the non-visual parts of Plaza into an engine. That is sync (subscriptions, filling the local store, paging back), relay and outbox routing, and signer sessions, both embedded and remote NIP-46. It also holds a cache for profiles, follow lists and relay lists, and content parsing that turns a note into structured data: mentions, hashtags, links, media and nostr: references.
The engine has no views and no UI templates. An app receives data and draws its own interface. Plaza moves onto the engine, and each part gets a guide on this site.
More apps, and Plaza 1.0
New small apps on the engine, each with its own interface, unlike Plaza’s. And Plaza 1.0.
Android
A proof of concept that uses the library through the C ABI to read a feed into a local store on a phone. It is a proof of concept, not a store release.
Everything you do on the first day
Zaps you can send, not only verify. Plaza shows the receipts of other people’s zaps, and sending one is not built.
An app worth leaving open
Nothing Plaza knows leaves the window today: no notification reaches you, and once the people you follow run dry there is nothing else to read.
Notifications at the level of the system, which a native app holding live relay connections can do with no server in the middle. Feeds with more than one shape: a single relay, a saved relay set, follow packs as real events rather than a hardcoded list. A store you can see and reclaim, because Plaza keeps everything it has ever ingested and gives you no way to see how large that has grown. Muting a word, a hashtag or a thread, and for an afternoon rather than forever. An update path, so people who installed are not stranded on whatever version they downloaded. Keyboard operation of what Tab does not yet reach, a light theme, and type that scales.
Places go further: the entered list as an encrypted event so it follows you between machines, notifications labelled with which place they came from, a way to find a place that is not somebody handing you a link, and a publishing path the two clients share rather than a document somebody has to republish by hand. A place link does nothing on a machine without Plaza, so getplaza.social will resolve the same address in a browser.
And a NIP-47 wallet connection, with an approval surface in Notary so a payment is something you agree to rather than something that happens.
What the local store was for
Everything Plaza does reads from a database on your own disk, and the only thing it can search there today is people. Finding a note you read some time ago, by words you remember, with the network off, is the thing a client without a local store cannot offer.
Private messages: NIP-17, gift wrapped per NIP-59 (a kind 13 seal inside a kind 1059 wrap), on the local store, signing through Notary, published only to the recipient’s kind 10050 DM relays. The seal’s conversation key derives from the identity key, so the signer has to do the NIP-44 work; Notary and the library already do, and it is Plaza’s own NIP-46 client that has to learn to ask for it.
NIP-71 video that actually plays, which in a renderer with no browser means platform decode and compositing rather than an embed. And NIP-60 wallets with NIP-61 nutzaps, Cashu ecash sent to a pubkey: a Lightning zap needs an LNURL provider the recipient signed up for in advance, and an account four clicks old has none, so this is what makes a new person payable at all.
Groups, other machines, and the library at 1.0
Groups: NIP-29, on relays that support it. Every event carries an h tag with the group id,
joining is a kind 9021 request, and the relay hosting the group is the authority on who is in
it. Gated on what a relay declares in its NIP-11 document.
Other platforms. Linux ships, for x86_64 and aarch64, with the same one-line installer macOS has. Off macOS the toolkit renders through a software rasteriser with no platform text provider, so Plaza draws every glyph itself and carries its own colour emoji face; the two renderer gaps that made that unusable are fixed and filed upstream. What is still open there is coverage: the bundled faces carry Latin and Cyrillic, so every other script, Greek included, is drawn as a solid block until a broader face ships. Shaping is a second problem behind it: the reference rasteriser reads no GSUB or GPOS, so Arabic and the Indic scripts would still be wrong with a perfect face. Windows is covered by the library and by deed, which build there and are tested in CI. Notary for Windows is listed above. Plaza is not packaged for Windows.
And the library at 1.0. It has been pre-1.0 on purpose while the API moved underneath it. Everything above lands there first, so by the time the rest of this is done the parts worth freezing have stopped moving.
What this deliberately does not do
Naming these is half of a roadmap, because each looks obviously worth doing until you price it.
- Multi-account. It taxes every feature after it: per-account stores, relay pools, notification state, and switching without a reconnect storm. A read-only “view as” answers most of the real demand.
- Set-reconciliation sync (NIP-77) in Plaza. The library and deed already sync with it. In Plaza, relay support is thin and the protocol is easy to get subtly wrong, and per-relay cursors capture most of the benefit against a store that already answers a feed query in under a millisecond.
- A proof of work difficulty slider (NIP-13) in Plaza. The library mines, and deed’s
event --powuses it. Reading proof of work is cheap: count the leading zero bits of the event id and honour the target committed in thenoncetag. A slider is not, and none of the mainstream relays I checked ask for any difficulty, so the setting would buy background mining, a cancel path and per-kind policy for nothing. Mining when a relay actually asks, throughmin_pow_difficultyin its NIP-11 document or anOKrejection that startspow:, needs no setting at all. - NIP-96 HTTP file storage. Supporting both upload paths looks like broader
compatibility. NIP-96 carries an
unrecommendedbanner in its own spec and the NIPs index strikes it through as replaced by Blossom, so uploads go to Blossom and nowhere else. - Web-of-trust distance filtering. Computed over a store that holds only what you happened to sync, the graph is wrong in a way that changes between launches, so the same reply appears and disappears for reasons nobody can explain.