Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions content/getting-started.mdx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# Getting Started

`zig-nostr` is a Nostr protocol library for [Zig](https://ziglang.org). It
targets Zig **0.16** and is **early** (`v0.3.8`).
targets Zig **0.16** and is in **active development** (`v0.12.0`).

## Install

Fetch the library into your project's `build.zig.zon`:

```sh
zig fetch --save https://github.com/zig-nostr/nostr/archive/refs/tags/v0.3.8.tar.gz
zig fetch --save https://github.com/zig-nostr/nostr/archive/refs/tags/v0.12.0.tar.gz
```

Then wire the module in `build.zig`:
Expand Down
4 changes: 2 additions & 2 deletions content/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ title: The Nostr protocol, natively in Zig

<div className="zn-stats">
<div className="zn-stat"><div className="num">0.28&nbsp;ms</div><div className="label">500-note feed query @ 100k events</div></div>
<div className="zn-stat"><div className="num">135k/s</div><div className="label">event ingest</div></div>
<div className="zn-stat"><div className="num">149k/s</div><div className="label">event ingest</div></div>
<div className="zn-stat"><div className="num">19/19</div><div className="label">BIP-340 test vectors</div></div>
</div>

Expand Down Expand Up @@ -116,7 +116,7 @@ title: The Nostr protocol, natively in Zig
</p>

```sh
zig fetch --save https://github.com/zig-nostr/nostr/archive/refs/tags/v0.3.8.tar.gz
zig fetch --save https://github.com/zig-nostr/nostr/archive/refs/tags/v0.12.0.tar.gz
```

```zig
Expand Down
4 changes: 2 additions & 2 deletions content/nips.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ rather than library surface.
## Planned, and where it lands

These are the specs the [roadmap](/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
against the milestone that delivers it. Three rows have a half already written, and say so;
the rest are untouched. 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 |
Expand Down
22 changes: 12 additions & 10 deletions content/plaza.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ Followers is not: nothing on your disk can know who follows a person, and the
honest options are an indexer's figure or none. Plaza does not print numbers it
cannot check.

Private messages are a milestone away.
Private messages are two milestones out on the [roadmap](/roadmap).

## Where the feed comes from

Expand Down Expand Up @@ -159,18 +159,20 @@ than an app that does nothing at all.

The feed is a windowed list: it builds only the rows near the viewport, so its
cost follows the window rather than the length of the feed. Measured on the
ReleaseFast build while scrolling hard through a live feed:
build that ships (ReleaseFast), scrolling hard through a fixed feed of 240
notes the harness seeds into a store of its own, so a run means the same thing
twice:

| Stage | p90 | Budget |
| --- | --- | --- |
| Rebuild | 54&micro;s | 400&micro;s |
| Layout | 432&micro;s | 1500&micro;s |
| Patch | 19&micro;s | 200&micro;s |

A 120&nbsp;Hz frame is 8333&micro;s, so a hard scroll spends about a tenth of
one. Sixty notes mount 63 widget nodes rather than roughly 500. The numbers are
reproducible: `scripts/frame-budget.sh` in the repo measures them and fails on a
regression.
| Rebuild | 275&micro;s | 600&micro;s |
| Layout | 1360&micro;s | 2200&micro;s |
| Patch | 55&micro;s | 150&micro;s |

A 120&nbsp;Hz frame is 8333&micro;s, so a hard scroll spends about a quarter of
one. A long feed mounts around 460 widget nodes rather than one per note. The
numbers are reproducible: `scripts/frame-budget.sh` in the repo measures them
and fails on a regression.

See [performance](/performance) for the library numbers underneath.

Expand Down
2 changes: 1 addition & 1 deletion content/roadmap.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ Then the ordinary parts. Pictures, which is one absence with three symptoms: no
photo, no avatar, no banner. Uploading is [Blossom](https://github.com/hzrd149/blossom)
rather than a NIP: BUD-02 `PUT /upload`, authorised by a signed kind 24242 event (BUD-11),
aimed at the servers in your kind 10063 list (BUD-03), with a NIP-92 `imeta` tag so they
render elsewhere. A profile with more than three fields, because Plaza reads eight out of a
render elsewhere. A profile with more than three fields, because Plaza reads nine out of a
kind 0 and lets you edit three, and `lud16` is not one of them, so an account set up only in
Plaza cannot receive a zap at all. Zaps you can send, not only verify. Finding a person, both
locally over the profiles already on your disk and through NIP-50 where a relay supports it.
Expand Down
19 changes: 13 additions & 6 deletions content/signer.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ before it happens, and the key never leaves the daemon.
## What it does

<div className="zn-shots">
<img src="/notary/panel-setup.jpg" alt="The key never arrives: it is created and held by the signer, and this window only forwards your passphrase" />
<img src="/notary/panel-setup.jpg" alt="Your key is created and held by the signer: this window forwards a passphrase, or the nsec you choose to import" />
<img src="/notary/panel-serving.jpg" alt="One URL, any client: paste the bunker link into any Nostr app and you are connected" />
<img src="/notary/panel-request.jpg" alt="Nothing signs quietly: every request names itself, and waits, before anything is signed" />
</div>
Expand All @@ -32,8 +32,10 @@ before it happens, and the key never leaves the daemon.
- A headless **daemon** holds the key (encrypted at rest with NIP-49) and speaks
NIP-46 over relays.
- A native **approval GUI** shows each incoming request (`sign_event`,
`nip44_encrypt`, and so on) and forwards your approve/deny decision over a
loopback channel. The GUI never sees the key.
`nip44_encrypt`, and so on) and forwards your answer over a loopback channel:
allow once, for a day, always, or deny. The key is generated and decrypted in
the daemon; the GUI sends it a passphrase, and an nsec only when you import an
existing key on the setup screen.
- Clients connect with a `bunker://` URL. It works end-to-end over public
relays, including those that require NIP-42 authentication.

Expand All @@ -49,10 +51,15 @@ The installer resolves the latest release, verifies its SHA-256, installs

## Supported operations

`sign_event` · `get_public_key` · `nip44_encrypt` · `nip44_decrypt` · `ping`
`connect` · `sign_event` · `ping` · `get_public_key` · `nip44_encrypt` · `nip44_decrypt` · `logout`

Each is gated by a per-request approval policy with method and event-kind
allowlists, so you decide exactly what a connected client may ask for.
Only the three that touch the key reach you; `connect`, `ping`,
`get_public_key` and `logout` are bookkeeping and are answered without waking
anybody. A static allowlist of methods and event kinds is the first gate, and
your answer carries a duration: once, for a day, or always, keyed by client,
method and event kind, so a client that signs in a loop is not a prompt in a
loop. A refusal stands for an hour, and a request nobody answers is not written
down at all.

## Why it matters

Expand Down
Binary file modified public/plaza/panel-places.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading