Nostr.Event.Note (Nostr Lib v0.2.0) (event) (nip01) (nip10) (nip14) (nip30) (nip36)

View Source

Text notes and threads (Kind 1)

Implements NIP-01 (basic notes), NIP-10 (threading), and NIP-14 (subject tags).

NIP-10 Threading

Notes can reference other notes using e tags with markers:

  • root - The root event of the thread
  • reply - The direct parent event being replied to

For top-level replies (direct reply to root), only the root marker is used. For nested replies, both root and reply markers are used.

NIP-14 Subject Tags

Notes can have a subject tag for email-like threading display:

Note.create("Hello!", subject: "Introduction")

When replying, the subject is automatically replicated with "Re:" prefix.

Quoting Events

Notes can quote other events using q tags. Quoted events should be referenced in the content with NIP-21 URIs (e.g., nostr:nevent1...).

Examples

# Create a simple note
Note.create("Hello world!")

# Create a note with a subject
Note.create("Let's discuss this", subject: "Meeting Notes")

# Create a reply to a note
Note.reply("I agree!", parent_note)

# Create a note with a quote
Note.quote("Check this out: nostr:nevent1...", %{id: "abc123"})

See:

Summary

Types

Event reference with optional relay and author hints

Quote reference (q tag)

t()

Functions

Create a new Note event.

Check if this note quotes other events

Get the direct parent event ID (reply_to if present, otherwise root)

Parses a kind 1 event into a Note struct.

Create a note that quotes another event.

Create a reply to an existing note.

Check if this note is a reply (has root reference)

Get the thread root event ID

Check if this note is a top-level reply (direct reply to root, no intermediate parent)

Types

event_ref()

@type event_ref() :: %{
  id: binary(),
  relay: binary() | nil,
  pubkey: binary() | nil,
  marker: :root | :reply | nil
}

Event reference with optional relay and author hints

quote_ref()

@type quote_ref() :: %{id: binary(), relay: binary() | nil, pubkey: binary() | nil}

Quote reference (q tag)

t()

@type t() :: %Nostr.Event.Note{
  author: binary(),
  content_warning: Nostr.NIP36.warning(),
  emojis: %{required(binary()) => binary()},
  event: Nostr.Event.t(),
  is_legacy_format: boolean(),
  mentions: [event_ref()],
  note: String.t(),
  participants: [binary()],
  quotes: [quote_ref()],
  reply_to: event_ref() | nil,
  root: event_ref() | nil,
  subject: String.t() | nil
}

Functions

create(note, opts \\ [])

@spec create(note :: String.t(), opts :: Keyword.t()) :: t()

Create a new Note event.

Options

  • :pubkey - author pubkey
  • :created_at - timestamp
  • :tags - additional tags
  • :root - thread root event reference (map with :id, optional :relay, :pubkey)
  • :reply_to - direct parent event reference
  • :quotes - list of quoted event references
  • :participants - list of pubkeys to notify
  • :subject - NIP-14 subject tag for email-like threading (should be < 80 chars)
  • :emojis - NIP-30 custom emoji map %{"shortcode" => "url"}
  • :content_warning - NIP-36 content warning (string reason or true for no reason)

Examples

Note.create("Hello world!")

Note.create("Let's discuss this", subject: "Meeting Notes")

Note.create("This is a reply!", root: %{id: "abc123", relay: "wss://relay.example.com"})

Note.create("Hello :wave:!", emojis: %{"wave" => "https://example.com/wave.png"})

Note.create("Sensitive content", content_warning: "Spoilers")

has_quotes?(note)

@spec has_quotes?(t()) :: boolean()

Check if this note quotes other events

parent_id(note)

@spec parent_id(t()) :: binary() | nil

Get the direct parent event ID (reply_to if present, otherwise root)

parse(event)

@spec parse(event :: Nostr.Event.t()) :: t()

Parses a kind 1 event into a Note struct.

Extracts thread structure from e tags (with NIP-10 markers if present), quote references from q tags, and participants from p tags.

Events with marked e tags (root/reply) are parsed using the preferred NIP-10 format. Events without markers fall back to deprecated positional parsing.

quote_event(content, quoted, opts \\ [])

@spec quote_event(
  content :: String.t(),
  quoted :: quote_ref() | [quote_ref()],
  opts :: Keyword.t()
) :: t()

Create a note that quotes another event.

The quoted event should be referenced in the content with a NIP-21 URI.

Examples

Note.quote(
  "Check this out: nostr:nevent1...",
  %{id: "abc123", relay: "wss://relay.example.com", pubkey: "def456"}
)

Note.quote("Multiple quotes!", [%{id: "abc"}, %{id: "def"}])

reply(content, parent, opts \\ [])

@spec reply(content :: String.t(), parent :: t() | map(), opts :: Keyword.t()) :: t()

Create a reply to an existing note.

For top-level replies (direct reply to root), only the root marker is used. For nested replies, both root and reply markers are used.

Automatically collects participants from the parent note's author and participants.

Examples

# Reply to a root note
Note.reply("I agree!", root_note)

# Reply to a nested reply (preserves thread root)
Note.reply("Me too!", nested_reply)

reply?(note)

@spec reply?(t()) :: boolean()

Check if this note is a reply (has root reference)

thread_root_id(note)

@spec thread_root_id(t()) :: binary() | nil

Get the thread root event ID

top_level_reply?(note)

@spec top_level_reply?(t()) :: boolean()

Check if this note is a top-level reply (direct reply to root, no intermediate parent)