Welcome back to our 10-part series on Nostr! We've covered the essentials so far: The intro in Post 1, history in Post 2, technical primer in Post 3, comparison to centralized media in Post 4, and beginner guide in Post 5. Links: 1, 2, 3, 4, 5. Now, we shift gears for developers. If you're a coder looking to build apps, bots, or integrations on Nostr, this post is your launchpad. We'll explore the protocol's dev-friendly design, key tools and SDKs (focusing on JavaScript and Rust as of 2026), and walk through first steps with code snippets. Nostr's simplicity means you can prototype quickly—no blockchain expertise required. Let's build something!
Nostr's protocol is dev heaven: Lightweight JSON over WebSockets, extensible via NIPs, and fully open-source. No API keys, rate limits, or vendor lock-in like Big Tech. Build clients, relays, bots, or niche tools (e.g., a zap-enabled newsletter). Key perks:
Challenges? Handling async comms and key management, but SDKs abstract that.
Start here:
For up-to-date tools (as of Jan 2026), use web searches or GitHub topics like "nostr-sdk".
Focus on popular, maintained ones:
JavaScript/TypeScript:
npm i nostr-tools.npm i @rust-nostr/nostr-sdk.Rust:
cargo add nostr-sdk (latest v0.XX as of Nov 2025).nostr crate: For low-level protocol impl.Other languages: nostr-sdk for Python, Go-nostr, etc.
nostr-tools/generatePrivateKey().wss://relay.damus.io.We'll use code examples. Note: These are simplified; error handling omitted for brevity. Test in your IDE.
This connects to a relay, publishes a note, and subscribes to events.
// Install: npm i nostr-tools
import { relayInit, generatePrivateKey, getPublicKey, finalizeEvent, verifyEvent } from 'nostr-tools';
async function nostrDemo() {
const privateKey = generatePrivateKey(); // Or use existing
const publicKey = getPublicKey(privateKey);
const relay = relayInit('wss://relay.damus.io');
await relay.connect();
relay.on('connect', () => console.log('Connected!'));
relay.on('error', () => console.log('Error!'));
// Publish a note (kind 1)
const event = finalizeEvent({
kind: 1,
created_at: Math.floor(Date.now() / 1000),
tags: [],
content: 'Hello from JS on Nostr!',
}, privateKey);
if (verifyEvent(event)) {
await relay.publish(event);
console.log('Published:', event);
}
// Subscribe to events
const sub = relay.sub([{ kinds: [1], authors: [publicKey], limit: 5 }]);
sub.on('event', event => console.log('Received:', event));
sub.on('eose', () => sub.unsub()); // End of stored events
}
nostrDemo();
Run in Node or browser. This uses NIP-01 basics.
Rust's async nature shines for performant apps.
// Cargo.toml: [dependencies] nostr-sdk = "0.26" (check latest)
use nostr_sdk::{prelude::*, Client, Options, RelayPoolNotification};
#[tokio::main]
async fn main() -> Result<()> {
let keys = Keys::generate(); // Or from secret
let opts = Options::new().wait_for_send(true);
let client = Client::with_opts(&keys, opts);
client.add_relay("wss://relay.damus.io").await?;
client.connect().await;
println!("Connected!");
// Publish a note
let event = EventBuilder::new_text_note("Hello from Rust on Nostr!", []).to_event(&keys)?;
client.send_event(event).await?;
println!("Published!");
// Subscribe
let filter = Filter::new().kind(Kind::TextNote).author(keys.public_key());
let sub_id = client.subscribe(vec![filter], None).await?;
// Handle notifications
client.handle_notifications(|notification| async {
if let RelayPoolNotification::Event { event, .. } = notification {
println!("Received: {:?}", event);
}
Ok(false) // Continue
}).await?;
Ok(())
}
This uses high-level Client; compile with cargo run.
In Copenhagen? Check local Bitcoin/Nostr meetups for collab.
With these tools, you're set to build. Fork a repo, submit a NIP, or create a bot. Nostr's dev community is welcoming—start small!
Next: "Top Nostr Clients and Apps: Reviews and Recommendations."
Hack away! Share your builds below or zap on Nostr.
What will you build first? Tell us!