Skip to content

Code Snippets

This section contains a growing collection of code snippets demonstrating how to perform specific tasks with NDK. Each snippet is focused on a single, targeted use case to help you find solutions for common implementation needs.

Snippets are grouped by category. Some of them are listed in more than one category.

Events

Creating an event

ts
import NDK, { NDKEvent, NDKKind } from "@nostr-dev-kit/ndk";

const ndk = new NDK(/* initialization options for the ndk singleton */);

const event = new NDKEvent(ndk, {
    kind: NDKKind.Text,
    content: "Hello world",
});

Tagging users

ts
import NDK, { NDKEvent, NDKKind } from "@nostr-dev-kit/ndk";

const ndk = new NDK();
const event = new NDKEvent(ndk, {
    kind: NDKKind.Text,
    content:
        "Hello, nostr:npub1l2vyh47mk2p0qlsku7hg0vn29faehy9hy34ygaclpn66ukqp3afqutajft this is a test from an NDK snippet.",
});
await event.sign();

Signing events

ts
import NDK, { NDKEvent, NDKNip07Signer } from "@nostr-dev-kit/ndk";

const nip07signer = new NDKNip07Signer();
const ndk = new NDK({ signer: nip07signer });

const event = new NDKEvent(ndk);
event.kind = 1;
event.content = "Hello world";
await event.sign();

Interest (kind 10015) Event

Interest events are used to tell the network about your interest in a particular topic. Those events and are making use of the NIP-51 specification kind:10015 events.

ts
import NDK, { NDKInterestList, NDKPrivateKeySigner } from "@nostr-dev-kit/ndk";

const ndk = new NDK({
    explicitRelayUrls: ["wss://relay.damus.io", "wss://relay.primal.net"],
});

// Create a signer (in production, use proper key management)
const signer = NDKPrivateKeySigner.generate();
ndk.signer = signer;

await ndk.connect();

// Create a new interest list
const interestList = new NDKInterestList(ndk);

// Add individual interests
interestList.addInterest("nostr");
interestList.addInterest("bitcoin");
interestList.addInterest("technology");
interestList.addInterest("privacy");

// Set a title for the list (optional)
interestList.title = "My Interests";
interestList.description = "Topics I'm passionate about";

console.log("Has 'nostr'?", interestList.hasInterest("nostr"));
console.log("Has 'ethereum'?", interestList.hasInterest("ethereum"));

// Publish the list (which also signs)
await interestList.publish();

Connecting

Specific Relays

ts
// Import the package
import NDK from "@nostr-dev-kit/ndk";

// Create a new NDK instance with explicit relays
const ndk = new NDK({
    explicitRelayUrls: ["wss://relay.damus.io", "wss://nos.lol", "wss://relay.nostr.band"],
});

// Now connect to specified relays
await ndk.connect();

Adding Relays

ts
// Import the package
import NDK from "@nostr-dev-kit/ndk";

// Create a new NDK instance with explicit relays
const ndk = new NDK();

ndk.addExplicitRelay("wss://a.relay");
ndk.addExplicitRelay("wss://another.relay");

// Now connect to specified relays
await ndk.connect();

NIP-07 Relays

ts
// Import NDK + NIP07 signer
import NDK, { NDKNip07Signer } from "@nostr-dev-kit/ndk";

// Create a new NDK instance with signer
// (provided the signer implements the getRelays() method)
const nip07signer = new NDKNip07Signer();
const ndk = new NDK({ signer: nip07signer });

Dev Relays

ts
import NDK from "@nostr-dev-kit/ndk";

const ndk = new NDK({
    devWriteRelayUrls: ["wss://staging.relay", "wss://another.test.relay"],
});

await ndk.connect();

Relay Pools

ts
import NDK, { NDKPool, NDKRelay } from "@nostr-dev-kit/ndk";

const ndk = new NDK();

const largeRelays = new NDKPool([`wss://relay.damus.io`, "wss://premium.primal.net"], ndk);
largeRelays.addRelay(new NDKRelay("wss://nos.lol", undefined, ndk));

const nicheRelays = new NDKPool([`wss://asad`, "wss://premisadasdum.primal.net"], ndk);

nicheRelays.connect();

ndk.pools.length; // 2

Connection Events

ts
import NDK, { type NDKRelay } from "@nostr-dev-kit/ndk";

// Create a new NDK instance with explicit relays
const ndk = new NDK({
    explicitRelayUrls: ["wss://a.relay", "wss://another.relay"],
});

// Main pool events
ndk.pool.on("relay:connecting", (relay: NDKRelay) => {
    console.log(`⟳ [Main Pool] Connecting to relay: ${relay.url}`);
});

ndk.pool.on("relay:connect", (relay: NDKRelay) => {
    console.log(`✓ [Main Pool] Connected to relay: ${relay.url}`);
});

ndk.pool.on("relay:disconnect", (relay: NDKRelay) => {
    console.log(`✗ [Main Pool] Disconnected from relay: ${relay.url}`);
});

Subscribing

Simple Subscribe

ts
import NDK from "@nostr-dev-kit/ndk";

const ndk = new NDK();

ndk.subscribe(
    { kinds: [1] }, // Filters
    { closeOnEose: true }, // Options (no explicit relays specified)
);

Subscribe on relays

ts
import NDK, {NDKRelaySet} from "@nostr-dev-kit/ndk";

const ndk = new NDK();
const explicitRelaySet = NDKRelaySet.fromRelayUrls(["wss://explicit.relay"], ndk);
ndk.subscribe(
    {kinds: [7]}, // Filters
    {
        // Options object now includes relaySet
        closeOnEose: true,
        relaySet: explicitRelaySet,
    },
);

Event Handler

ts
import NDK, { type NDKEvent, type NDKRelay, type NDKSubscription } from "@nostr-dev-kit/ndk";

const ndk = new NDK();

ndk.subscribe(
    { kinds: [1] }, // Filters
    { closeOnEose: true }, // Options (no explicit relays specified)
    {
        // Direct handlers via autoStart parameter (now the 3rd argument)
        onEvent: (event: NDKEvent, relay?: NDKRelay) => {
            // Called for events received from relays after the initial cache load (if onEvents is used)
            console.log("Received event from relay (id):", event.id);
        },
        onEvents: (events: NDKEvent[]) => {
            // Parameter renamed to 'events'
            console.log(`Received ${events.length} events from cache initially.`);
        },
        onEose: (subscription: NDKSubscription) => {
            console.log("Subscription reached EOSE:", subscription.internalId);
        },
    },
);

Attaching Handlers

ts
import NDK from "@nostr-dev-kit/ndk";

const ndk = new NDK();

const subscription = ndk.subscribe(
    { kinds: [1] }, // Filters
    { closeOnEose: true }, // Options (no explicit relays specified)
);

// Attach handlers later
subscription.on("event", (event) => {
    console.log("Received event:", event.id);
});
subscription.on("eose", () => {
    console.log("Initial events loaded");
});

// Remember to stop the subscription when it's no longer needed
// setTimeout(() => subscription.stop(), 5000);

Exclusive Relays

ts
import NDK from "@nostr-dev-kit/ndk";

const ndk = new NDK();

// Subscription that ONLY accepts events from relay-a.com
const exclusiveSub = ndk.subscribe(
    {kinds: [7]},
    {
        relayUrls: ["wss://relay-a.com"],
        exclusiveRelay: true, // 🔑 Key option
    },
);

exclusiveSub.on("event", (event) => {
    console.log("Event from relay-a.com:", event.content);
    // This will ONLY fire for events from relay-a.com
    // Events from relay-b.com or relay-c.com are rejected
});

Signers

Signing events

ts
import NDK, { NDKEvent, NDKNip07Signer } from "@nostr-dev-kit/ndk";

const nip07signer = new NDKNip07Signer();
const ndk = new NDK({ signer: nip07signer });

const event = new NDKEvent(ndk);
event.kind = 1;
event.content = "Hello world";
await event.sign();

Sign with NSec

ts
import NDK, { NDKEvent, NDKPrivateKeySigner } from "@nostr-dev-kit/ndk";

const privateKeySigner = NDKPrivateKeySigner.generate();
const ndk = new NDK({ signer: privateKeySigner });

const event = new NDKEvent(ndk);
event.kind = 1;
event.content = "Hello world";
await event.sign();

Different signers

ts
import { NDKEvent, NDKPrivateKeySigner } from "@nostr-dev-kit/ndk";

const signer1 = NDKPrivateKeySigner.generate();
const pubkey1 = signer1.pubkey;

const event1 = new NDKEvent();
event1.kind = 1;
event1.content = "Hello world";
await event1.sign(signer1);

event1.pubkey === pubkey1; // true

const signer2 = NDKPrivateKeySigner.generate();
const pubkey2 = signer2.pubkey;

const event2 = new NDKEvent();
event2.kind = 1;
event2.content = "Hello world";
await event2.sign(signer2);

event2.pubkey === pubkey2; // true

Sign using bunker

ts
// provided by the user
import NDK, { NDKNip46Signer, NDKPrivateKeySigner } from "@nostr-dev-kit/ndk";

const signerConnectionString = "bunker://....";
const ndk = new NDK();

// local keypair generated when signer if first initialised
const clientKeypair = NDKPrivateKeySigner.generate(); //
const clientNsec = clientKeypair.nsec;

// initiate NIP-46 signer
const signer = NDKNip46Signer.bunker(ndk, signerConnectionString, clientNsec);

// promise will resolve once the `kind:24133` event is received
const user = await signer.blockUntilReady();

console.log("Welcome", user.npub);

Generate Keypair

ts
import { NDKPrivateKeySigner } from "@nostr-dev-kit/ndk";

// Generate a new private key
const signer = NDKPrivateKeySigner.generate();
const privateKey = signer.privateKey; // Get the hex private key
const publicKey = signer.pubkey; // Get the hex public key
const nsec = signer.nsec; // Get the private key in nsec format
const npub = signer.userSync.npub; // Get the public key in npub format

Encrypt/Decrypt Keypair

ts
import { NDKPrivateKeySigner } from "@nostr-dev-kit/ndk";

const signer = NDKPrivateKeySigner.generate();

// Encrypt with a password
const password = "user-chosen-password";
const ncryptsec = signer.encryptToNcryptsec(password);

// Store securely (e.g., localStorage)
localStorage.setItem("encrypted_key", ncryptsec);

const restoredButEncrypted = localStorage.getItem("encrypted_key");

if (restoredButEncrypted) {
    // Later, restore the signer
    const restoredSigner = NDKPrivateKeySigner.fromNcryptsec(restoredButEncrypted, password);

    console.log("Original pubkey:", signer.pubkey);
    console.log("Restored pubkey:", restoredSigner.pubkey);
}

NIP-49 encryption

ts
import {bytesToHex, hexToBytes} from "@noble/hashes/utils";
import {nip49} from "@nostr-dev-kit/ndk";

// Encrypt raw private key bytes
const privateKeyHex = "14c226dbdd865d5e1645e72c7470fd0a17feb42cc87b750bab6538171b3a3f8a";
const privateKeyBytes = hexToBytes(privateKeyHex);
const password = "my-password";

const ncryptsec = nip49.encrypt(privateKeyBytes, password, 16, 0x02);
console.log("Encrypted:", ncryptsec);

// Decrypt to raw bytes
const decryptedBytes = nip49.decrypt(ncryptsec, password);
const decryptedHex = bytesToHex(decryptedBytes);
console.log("Decrypted:", decryptedHex);

Publishing

Publish Event

ts
import NDK, { NDKEvent, NDKNip07Signer } from "@nostr-dev-kit/ndk";

const nip07signer = new NDKNip07Signer();
const ndk = new NDK({ signer: nip07signer });

const event = new NDKEvent(ndk);
event.kind = 1;
event.content = "Hello world";
await event.publish(); 

Replaceable Event

ts
import NDK from "@nostr-dev-kit/ndk";

const ndk = new NDK();
const existingEvent = await ndk.fetchEvent("574033c986bea1d7493738b46fec1bb98dd6a826391d6aa893137e89790027ec"); // fetch the event to replace

if (existingEvent) {
    existingEvent.tags.push(
        ["p", "fa984bd7dbb282f07e16e7ae87b26a2a7b9b90b7246a44771f0cf5ae58018f52"], // follow a new user
    );
    existingEvent.publish(); // this will NOT work
    existingEvent.publishReplaceable(); // this WILL work
}

Specify Relays

ts
import NDK, { NDKEvent, NDKRelaySet } from "@nostr-dev-kit/ndk";

const ndk = new NDK();

const event = new NDKEvent(ndk);
event.kind = 1;
event.content = "Hello world";

const customRelaySet = NDKRelaySet.fromRelayUrls(["wss://relay.snort.social", "wss://relay.primal.net"], ndk);
await event.publish(customRelaySet);

Track Publication Status

ts
import NDK, { NDKEvent, type NDKRelay, type NDKRelaySet } from "@nostr-dev-kit/ndk";

const ndk = new NDK({
    explicitRelayUrls: ["wss://relay.damus.io", "wss://relay.nostr.band", "wss://nos.lol"],
});

await ndk.connect();

const event = new NDKEvent(ndk, {
    kind: 1,
    content: "Hello Nostr!",
});

event.on("published", (data: { relaySet: NDKRelaySet; publishedToRelays: Set<NDKRelay> }) => {
    // Get all relays where the event was successfully published
    console.log("Published to:", data.publishedToRelays);
});

Handling Failures

ts
import NDK, { NDKEvent, type NDKPublishError } from "@nostr-dev-kit/ndk";

const ndk = new NDK({
    explicitRelayUrls: ["wss://relay.damus.io", "wss://relay.nostr.band", "wss://nos.lol"],
});

await ndk.connect();

const event = new NDKEvent(ndk, {
    kind: 1,
    content: "Hello Nostr!",
});

ndk.on(`event:publish-failed`, (event: NDKEvent, error: NDKPublishError, relays: WebSocket["url"][]) => {
    console.log("Event failed to publish on", relays, error);
});

Not migrated yet