Nostr (Notes and Other Stuff Transmitted by Relays) is a protocol, not a platform.
It’s built to be simple, extensible, and decentralized, relying on a few core components: keys, events, relays, and clients.
Together, these create a system that’s lightweight but capable of supporting everything from social networking to private messaging.
1. Cryptographic Keys: Your Identity
At the heart of Nostr is a public-private key pair, which serves as your identity. This is based on standard cryptography, specifically the secp256k1 curve (the same one Bitcoin uses). Here’s how it plays out:
Private Key: A 64-character hexadecimal string (e.g., nsec1...) that you keep secret. It’s used to sign your messages, proving they’re from you.
Public Key: A derived 64-character hex string (e.g., npub1...) that identifies you publicly. Anyone can use it to find or verify your content.
There’s no central registry tying keys to real-world identities—your key pair is your account. Lose your private key? You’re out of luck, just like a crypto wallet. This keeps things anonymous and user-controlled.
2. Events: The Building Blocks
Everything in Nostr is an event, a JSON object that carries data. Events are the protocol’s universal currency—whether it’s a tweet-like post, a profile update, or a direct message, it’s all formatted as an event. Here’s what an event looks like:
json
{
"id": "<32-byte SHA-256 hash of the serialized event>",
"pubkey": "<32-byte public key of the creator>",
"created_at": "<Unix timestamp in seconds>",
"kind": "<integer specifying event type>",
"tags": ["<array of tag arrays for metadata>"],
"content": "<string, often the message itself>",
"sig": "<64-byte Schnorr signature of the event>"
}
ID: A unique hash of the event, ensuring no duplicates.
Pubkey: Links it to the creator’s public key.
Kind: Defines the event type (e.g., 1 for text notes, 0 for profile metadata, 4 for encrypted DMs).
Tags: Flexible metadata, like mentions (["p", "<pubkey>"]) or hashtags.
Content: The payload—could be plain text, JSON, or encrypted data.
Signature: A Schnorr signature (also secp256k1) proving the event’s authenticity.
Events are immutable once signed. Want to update your profile? You send a new kind: 0 event with a later timestamp, and clients pick the latest one.
3. Relays: The Decentralized Backbone
Relays are the servers that store and distribute events. They’re the decentralized glue holding Nostr together. Here’s how they function:
Anyone can run a relay using open-source software (e.g., implementations in Rust, Go, or Python).
Clients connect to relays via WebSockets, a real-time communication standard.
You push events to a relay by sending them over the WebSocket, and the relay broadcasts them to connected clients who’ve subscribed to relevant filters (e.g., “give me all events from this pubkey”).
Relays don’t have to store everything forever—they can prune old events or filter content based on their own rules. You might connect to multiple relays for redundancy or to access different communities. For example:
Relay A might focus on free speech and keep all events.
Relay B might filter spam or only serve a niche group.
There’s no central coordination—relays don’t even need to talk to each other. This makes the system resilient but also means coverage depends on which relays you use.
4. Clients: The User Interface
Clients are the apps you interact with—think Damus, Primal, or Nostur. They handle the heavy lifting of:
Generating and managing your key pair.
Connecting to relays (often a user-configurable list).
Sending events (e.g., posting a note).
Subscribing to event streams (e.g., “show me notes from people I follow”).
Clients query relays with filters, like:
json
{"authors": ["<pubkey1>", "<pubkey2>"], "kinds": [1], "since": 1677654321}
This says, “Give me all text notes (kind: 1) from these users since this timestamp.” The relay responds with matching events in real time.
Clients also handle extras like rendering posts, decrypting messages (for kind: 4 events using NIP-04 encryption), or building a social graph from tags.
5. NIPs: Extending the Protocol
Nostr evolves through Nostr Improvement Proposals (NIPs), a community-driven process. These define standards for new features, like:
NIP-01: Core event structure.
NIP-04: Encrypted direct messages (using AES-CBC with a shared secret derived from key pairs).
NIP-05: Mapping public keys to human-readable names (e.g., alice@domain.com) via a verified domain.
NIPs keep Nostr flexible—developers can propose anything from group chats to payment integrations (e.g., with Lightning Network).
How It All Fits Together
Imagine you want to post “Hello, Nostr!”:
Your client generates an event: { "kind": 1, "content": "Hello, Nostr!", "pubkey": "<your-pubkey>", ... }.
It signs the event with your private key.
The client sends it to your chosen relays via WebSockets.
The relays store it and forward it to anyone subscribed to your pubkey.
Your friend’s client, subscribed to your pubkey, picks up the event and displays it.
No middleman, no single point of failure. If a relay goes down, others can still serve your event. If you’re censored on one, you switch to another.
Strengths and Trade-offs
Strengths: Decentralized, lightweight (events are tiny), and extensible. Cryptographic signing ensures trust without a central authority.
Trade-offs: No built-in global state—clients must piece together data from relays. Discovery (finding users) is harder without centralized search. Relays can see unencrypted data, so privacy depends on encryption or external tools.
Why It Works
Nostr’s architecture is a throwback to the early internet: simple protocols (like SMTP or IRC) that anyone can implement.
It ditches complexity for robustness, betting that a decentralized web beats a brittle, corporate one.
Whether it’s the future depends on adoption—but technically, it’s a lean, mean machine.