Chapter B0 - Web Content
B0
Nostr Implementation Possibility - Hex № B0

Web Bookmarking

Save any web page as an editable, addressable Nostr event that anyone can find by its URI.

1 Overview

A web bookmark is a saved reference to one web page. This NIP defines kind:39701 for web bookmarks. Each bookmark is one event. The bookmarked URI lives in the event's d tag.

Kind 39701 sits in the addressable range of NIP-01. A relay keeps only the latest event per pubkey + kind + d value. A user can therefore edit a bookmark. The user publishes a new event with the same d value, and the old version goes away.

Because the d value is the URI itself, clients can query bookmarks by URI. One #d filter returns every user's bookmark of the same page. This turns private bookmarking into a shared, social index of the web.

Hint!

Do not confuse this NIP with the bookmark lists of NIP-51. A NIP-51 list stores many references inside one event. A NIP-B0 bookmark is one standalone event per URI, with its own description, topics, and comments.

Alice Bob Relay kind 39701 Reader EVENT #d query
Fig. B0-1 — Bookmarks as a shared index. Alice and Bob each publish a bookmark of the same page. A reader queries the d value and gets both.

2 The Bookmark Event

A web bookmark is a normal signed event with kind:39701. The content field holds a detailed description of the bookmark. The description can be an empty string. The d tag is required. All other tags are optional metadata.

Wire format - kind 39701 web bookmark
{
  "kind": 39701,
  "content": <description of the bookmark, may be "">,
  "tags": [
    ["d", <URI of the bookmarked page>],      // required
    ["published_at", <unix seconds, string>], // optional
    ["title", <title of the bookmark>],       // optional
    ["t", <topic>], ...                        // optional, repeatable
  ],
  // plus the standard id, pubkey, created_at, sig fields
}
Field reference
FieldRule
kindAlways 39701. Addressable per NIP-01: relays keep the latest event per pubkey + kind + d value.
contentA detailed description of the web bookmark. An empty string is allowed.
tagsMust contain one d tag. May contain the metadata tags of §4.

3 The d Tag: One URI per Bookmark

The d tag value is the URI of the bookmarked page. One rule shapes the value. If the scheme is https, omit all characters before the hostname. Drop https:// and start the value at the hostname. For any other scheme, keep the URI as it is.

Deriving the d value
https://alice.blog/post      →  "alice.blog/post"   // https scheme dropped
http://old.example/page      →  "http://old.example/page"
gemini://caps.example/doc    →  "gemini://caps.example/doc"

This rule makes the d value predictable. Clients query web bookmark events by the d tag. A filter such as {"kinds": [39701], "#d": ["alice.blog/post"]} returns every bookmark of that page, from every user, on that relay.

URL https://a.blog/post Normalize drop https:// Sign kind 39701 Relay latest wins
Fig. B0-2 — The d value pipeline. Normalize the URL, sign the event, publish. Republishing the same d value edits the bookmark.
Tech Note

The spec defines no URI normalization beyond dropping the https:// prefix. It does not say how to treat trailing slashes, www. prefixes, query strings, or fragments. Two clients can derive different d values for the same page, and those bookmarks will not match in a #d query. The spec also does not state which HTML link attribute the title tag maps to.

4 Metadata Tags

Metadata fields can be added to the event as tags when necessary. This NIP names three:

Metadata tags
TagValuePurpose
ttopic stringA tag or hashtag: a topic about which the event might be of relevance. Repeat the tag for each topic.
published_atunix seconds, stringifiedThe timestamp of the first time the bookmark was published. Later edits keep this value.
titletitle stringA title for the bookmark. It can serve as an attribute for the HTML link element.

5 Replies and Comments

Replies to a kind:39701 bookmark must use kind:1111 comment events, as defined in NIP-22. Do not reply with plain kind-1 notes. The NIP-22 comment carries scope tags that point back to the bookmark's address, so threads stay attached to the bookmark even after edits.

6 Worked Example

Alice bookmarks a blog post at https://alice.blog/post. The scheme is https, so the d value starts at the hostname. She adds a title, two topics, and a first-publication timestamp.

Full event - kind 39701
{
  "kind": 39701,
  "id": "d7a92714f81d0f712e715556aee69ea6da6bfb287e6baf794a095d301d603ec7",
  "pubkey": "2729620da105979b22acfdfe9585274a78c282869b493abfa4120d3af2061298",
  "created_at": 1738869705,
  "tags": [
    // required tags
    ["d", "alice.blog/post"],
    // optional tags
    ["published_at", "1738863000"],
    ["title", "Blog insights by Alice"],
    ["t", "post"],
    ["t", "insight"]
  ],
  "content": "A marvelous insight by Alice about the nature of blogs and posts.",
  "sig": "36d34e6448fe0223e9999361c39c492a208bc423d2fcdfc2a3404e04df7c22dc65bbbd62dbe8a4373c62e4d29aac285b5aa4bb9b4b8053bd6207a8b45fbd0c98"
}

A reader now queries the relay for every bookmark of that page. Later, Alice edits her description. She republishes with the same d value, and the relay replaces the old event.

Session transcript - wss://relay.example.com
-- Alice publishes the bookmark --
→ ["EVENT", {"kind":39701, "id":"d7a92714…", "tags":[["d","alice.blog/post"], …], …}]
← ["OK", "d7a92714…", true, ""]

-- a reader looks the page up by its d value --
→ ["REQ", "bm", {"kinds":[39701], "#d":["alice.blog/post"]}]
← ["EVENT", "bm", {"kind":39701, "pubkey":"2729620d…", "content":"A marvelous insight…", …}]
← ["EOSE", "bm"]

-- Alice edits: same d value, newer created_at --
→ ["EVENT", {"kind":39701, "id":"4c01afe2…", "created_at":1738900000,
     "tags":[["d","alice.blog/post"], ["published_at","1738863000"], …],
     "content":"Updated notes on Alice's post.", …}]
← ["OK", "4c01afe2…", true, ""]  // relay now serves only this version

7 Version History

NIP-B0 is young and small. Its one substantive revision fixed how schemes are handled in the d value. Notable changes, newest first:

  • 20262026-07Fixed the URI scheme ambiguity: only the https scheme is omitted from the d value; other schemes stay verbatim. A misapplied suggestion from the same change was corrected the same day.
  • 2025-262025-08Wording cleanup and code-fence relabeling passes.
  • 20252025-04Renamed to the uppercase B0.md filename shortly after merge.
  • Origin2025-04-24Sebastian Hagens proposed kind:39701 web bookmarks in PR #1849.

Original Proposal - Credits

AuthorSebastian Hagens
First commit2025-04-24 — “adding more info / requirements for using kind 39701 for web bookmarks (NIP-B0)” (PR #1849)
Statusdraft - optional
SourceB0.md on GitHub - full change history

8 See Also

  • NIP-01 — addressable events, the d tag, and #d filters that this NIP relies on.
  • NIP-22 — kind:1111 comments; the mandatory reply format for bookmarks.
  • NIP-51 — bookmark lists (kind:10003); many references in one event, instead of one event per URI.
  • NIP-73 — external content IDs; another way to reference web URLs from events.