{"@context":"https:\/\/schema.org","@type":"Periodical","version":"1.0","generatedAt":"2026-07-26T14:08:29+00:00","magazine":{"id":"8832250e97409a98814b7ec892d4e0458ac4709901d4eafeede91bdf82f836d6","slug":"decent-newsroom-documentation-1f07d7","title":"Decent Newsroom Documentation","summary":"Project documentation","image":"https:\/\/images.pexels.com\/photos\/357514\/pexels-photo-357514.jpeg","language":null,"pubkey":"c89e5eb6d9ab087e36d122a1674167053179200226cbf082bca1c492e858ffac","createdAt":"2026-05-16T13:26:34+00:00","url":"https:\/\/www.decentnewsroom.com\/mag\/decent-newsroom-documentation-1f07d7"},"categories":[{"slug":"nostr-implementation-possibilities-c7f417","title":"Nostr Implementation Possibilities","summary":"Documentation of what may be implemented by Nostr-compatible relay and client software","image":null,"url":"https:\/\/www.decentnewsroom.com\/mag\/decent-newsroom-documentation-1f07d7\/cat\/nostr-implementation-possibilities-c7f417","articleCount":8,"articles":[{"title":"NIP-A3","slug":"nip-a3-n2y0o0","summary":"This NIP standardizes payment and tip invocations using the RFC-8905 `payto:` URI scheme.","content":"# payto: Payment Targets (RFC-8905)\n\n## Event Kind\n\nThis NIP defines `kind:10133` for payment target events. This kind is **replaceable**.\n\n`optional`\n\nThis NIP standardizes payment and tip invocations using the [RFC-8905 (payto:) URI scheme](https:\/\/www.rfc-editor.org\/rfc\/rfc8905.html) for payment targets.\n\n## Broadcasting\n\nClients *may* allow users to specify payment targets consisting of `type` and `authority` values to generate a kind `10133` event with `payto` tags for payment or tip invocations.\n\n**Client Implementation:**\n1. Allow users to input `type` and `authority` pairs\n2. Validate inputs according to the rules below\n3. Optionally warn users if a `type` is not recognized (but allow submission)\n4. Broadcast the event with `payto` tags\n\n### Tag Format\n\nPayment targets are specified using `payto` tags with the following structure:\n\n```text\n[\u0022payto\u0022, \u0022\u003Ctype\u003E\u0022, \u0022\u003Cauthority\u003E\u0022, \u0022\u003Coptional_extra_1\u003E\u0022, \u0022\u003Coptional_extra_2\u003E\u0022, ...]\n```\n\nWhere:\n- The first element is always the literal string `\u0022payto\u0022`\n- The second element is the payment `type` (e.g., `\u0022bitcoin\u0022`, `\u0022lightning\u0022`)\n- The third element is the `authority` (e.g., address, username)\n- Additional elements are optional and reserved for future RFC-8905 features\n\nClients **must** understand elements 0\u20132; they **may ignore** any additional elements for forward compatibility.\n\n### Validation\n\n- `type`: Lowercase letters (a-z), digits (0-9), and hyphens (-). Types are case-insensitive; normalize to lowercase.\n- `authority`: URL-safe; URL-encode special characters. Format depends on the payment system.\n- Clients may perform additional payment-system-specific validation for recognized types.\n\n## Broadcasting Example\n\n```json\n{\n  \u0022pubkey\u0022: \u0022afc93622eb4d79c0fb75e56e0c14553f7214b0a466abeba14cb38968c6755e6a\u0022,\n  \u0022kind\u0022: 10133,\n  \u0022content\u0022: \u0022\u0022,\n  \u0022tags\u0022: [\n    [\u0022payto\u0022, \u0022bitcoin\u0022, \u0022bc1qxq66e0t8d7ugdecwnmv58e90tpry23nc84pg9k\u0022],\n    [\u0022payto\u0022, \u0022nano\u0022, \u0022nano_1dctqbmqxfppo9pswbm6kg9d4s4mbraqn8i4m7ob9gnzz91aurmuho48jx3c\u0022],\n    [\u0022payto\u0022, \u0022unknowntype\u0022, \u0022l7tbta5b9xze6ckkfc99uohzxd009b0r\u0022]\n  ],\n  ...\n}\n```\n\n## Recommended Payment Target Types\n\n| Payment Target Type | Long Stylization  | Short Stylization | Symbol | References |\n| :------------------ | :---------------- | :---------------- | :----- | :--------- |\n| bitcoin             | Bitcoin           | BTC               | \u20bf      | https:\/\/bitcoin.design\/ |\n| cashme              | Cash App          | Cash App          | $,\u00a3    | https:\/\/cash.app\/press |\n| ethereum            | Ethereum          | ETH               | \u039e      | https:\/\/ethereum.org\/assets\/#brand |\n| lightning           | Lightning Network | LBTC              | \u4e30     | https:\/\/github.com\/shocknet\/bitcoin-lightning-logo |\n| monero              | Monero            | XMR               | \u0271      | https:\/\/www.getmonero.org\/press-kit\/ |\n| nano                | Nano              | XNO               | \u04fe      | https:\/\/nano.org\/en\/currency |\n| revolut             | Revolut           | Revolut           | N\/A    | https:\/\/revolut.me |\n| venmo               | Venmo             | Venmo             | $      | https:\/\/venmo.com\/pay |\n\n## Observation\n\nFor each `payto` tag in kind `10133` events, clients *should* assemble a `payto:\/\/\u003Ctype\u003E\/\u003Cauthority\u003E` URI and render it as a button or link.\n\n**Client Implementation:**\n1. Parse each `payto` tag from the event\n2. Optionally validate `type` and `authority` fields and filter invalid tags\n3. Assemble full `payto:\/\/\u003Ctype\u003E\/\u003Cauthority\u003E` URIs\n4. For **recognized** types, render with associated icons and stylization from the table above\n5. For **unrecognized** types, either ignore or use generic stylization\n6. If multiple targets exist, render the first one, all of them, or a dropdown selector\n\n## Observation Example\n\n```json\n{\n  \u0022pubkey\u0022: \u0022afc93622eb4d79c0fb75e56e0c14553f7214b0a466abeba14cb38968c6755e6a\u0022,\n  \u0022kind\u0022: 10133,\n  \u0022content\u0022: \u0022\u0022,\n  \u0022tags\u0022: [\n    [\u0022payto\u0022, \u0022bitcoin\u0022, \u0022bc1qxq66e0t8d7ugdecwnmv58e90tpry23nc84pg9k\u0022],\n    [\u0022payto\u0022, \u0022nano\u0022, \u0022nano_1dctqbmqxfppo9pswbm6kg9d4s4mbraqn8i4m7ob9gnzz91aurmuho48jx3c\u0022],\n    [\u0022payto\u0022, \u0022unknowntype\u0022, \u0022l7tbta5b9xze6ckkfc99uohzxd009b0r\u0022]\n  ],\n  ...\n}\n```\n\nAssembled URIs:\n- `payto:\/\/bitcoin\/bc1qxq66e0t8d7ugdecwnmv58e90tpry23nc84pg9k` (recognized)\n- `payto:\/\/nano\/nano_1dctqbmqxfppo9pswbm6kg9d4s4mbraqn8i4m7ob9gnzz91aurmuho48jx3c` (recognized)\n- `payto:\/\/unknowntype\/l7tbta5b9xze6ckkfc99uohzxd009b0r` (unrecognized)\n\n# Implementation Notes\n\n## Integration with NIP-57 Zaps\n\nClients may use `payto` lightning entries as an alternative or complement to `lud16` for zap functionality. The `authority` field should contain a Lightning address (e.g., `user@wallet.example.com`) or LNURL.\n\nExample:\n\n```json\n[\n  {\n    \u0022kind\u0022: 0,\n    \u0022content\u0022: \u0022{\\\u0022lud16\\\u0022:\\\u0022user@wallet.example.com\\\u0022}\u0022,\n    \u0022pubkey\u0022: \u0022...\u0022\n  },\n  {\n    \u0022kind\u0022: 10133,\n    \u0022content\u0022: \u0022\u0022,\n    \u0022tags\u0022: [\n      [\u0022payto\u0022, \u0022lightning\u0022, \u0022user@wallet.example.com\u0022],\n      [\u0022payto\u0022, \u0022bitcoin\u0022, \u0022bc1q...\u0022]\n    ],\n    \u0022pubkey\u0022: \u0022...\u0022\n  }\n]\n```\n","image":null,"pubkey":"c89e5eb6d9ab087e36d122a1674167053179200226cbf082bca1c492e858ffac","kind":30023,"createdAt":"2026-05-24T19:08:42+00:00","publishedAt":"2026-05-24T19:08:42+00:00","topics":["nips","nostr","dev","digital","payments"],"url":"https:\/\/www.decentnewsroom.com\/mag\/decent-newsroom-documentation-1f07d7\/cat\/nostr-implementation-possibilities-c7f417\/d\/nip-a3-n2y0o0"},{"title":"NIP-19","slug":"nip-19-9e6ih1","summary":"This NIP standardizes bech32-formatted strings that can be used to display keys, ids and other information in clients as shareable identifiers with extra metadata.","content":"# bech32-encoded entities\n\n`draft` `optional`\n\nThis NIP standardizes bech32-formatted strings that can be used to display keys, ids and other information in clients. These formats are not meant to be used anywhere in the core protocol, they are only meant for displaying to users, copy-pasting, sharing, rendering QR codes and inputting data.\n\nIt is recommended that ids and keys are stored in either hex or binary format, since these formats are closer to what must actually be used the core protocol.\n\n## Bare keys and ids\n\nTo prevent confusion and mixing between private keys, public keys and event ids, which are all 32 byte strings. bech32-(not-m) encoding with different prefixes can be used for each of these entities.\n\nThese are the possible bech32 prefixes:\n\n- `npub`: public keys\n- `nsec`: private keys\n- `note`: note ids\n\n\nExample: the hex public key `3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d` translates to `npub180cvv07tjdrrgpa0j7j7tmnyl2yr6yr7l8j4s3evf6u64th6gkwsyjh6w6`.\n\nThe bech32 encodings of keys and ids are not meant to be used inside the standard NIP-01 event formats or inside the filters, they\u0027re meant for human-friendlier display and input only. Clients should still accept keys in both hex and npub format for now, and convert internally.\n\n## Shareable identifiers with extra metadata\n\nWhen sharing a profile or an event, an app may decide to include relay information and other metadata such that other apps can locate and display these entities more easily.\n\nFor these events, the contents are a binary-encoded list of `TLV` (type-length-value), with `T` and `L` being 1 byte each (`uint8`, i.e. a number in the range of 0-255), and `V` being a sequence of bytes of the size indicated by `L`.\n\nThese are the possible bech32 prefixes with `TLV`:\n\n- `nprofile`: a nostr profile\n- `nevent`: a nostr event\n- `naddr`: a nostr _addressable event_ coordinate\n- `nrelay`: a nostr relay (deprecated)\n\n\nThese possible standardized `TLV` types are indicated here:\n\n- `0`: `special`\n- depends on the bech32 prefix:\n- for `nprofile` it will be the 32 bytes of the profile public key\n- for `nevent` it will be the 32 bytes of the event id\n- for `naddr`, it is the identifier (the `\u0022d\u0022` tag) of the event being referenced. For normal replaceable events use an empty string.\n- `1`: `relay`\n- for `nprofile`, `nevent` and `naddr`, _optionally_, a relay in which the entity (profile or event) is more likely to be found, encoded as ascii\n- this may be included multiple times\n- `2`: `author`\n- for `naddr`, the 32 bytes of the pubkey of the event\n- for `nevent`, _optionally_, the 32 bytes of the pubkey of the event\n- `3`: `kind`\n- for `naddr`, the 32-bit unsigned integer of the kind, big-endian\n- for `nevent`, _optionally_, the 32-bit unsigned integer of the kind, big-endian\n\n\n## Examples\n\n- `npub10elfcs4fr0l0r8af98jlmgdh9c8tcxjvz9qkw038js35mp4dma8qzvjptg` should decode into the public key hex `7e7e9c42a91bfef19fa929e5fda1b72e0ebc1a4c1141673e2794234d86addf4e` and vice-versa\n- `nsec1vl029mgpspedva04g90vltkh6fvh240zqtv9k0t9af8935ke9laqsnlfe5` should decode into the private key hex `67dea2ed018072d675f5415ecfaed7d2597555e202d85b3d65ea4e58d2d92ffa` and vice-versa\n- `nprofile1qqsrhuxx8l9ex335q7he0f09aej04zpazpl0ne2cgukyawd24mayt8gpp4mhxue69uhhytnc9e3k7mgpz4mhxue69uhkg6nzv9ejuumpv34kytnrdaksjlyr9p` should decode into a profile with the following TLV items:\n- pubkey: `3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d`\n- relay: `wss:\/\/r.x.com`\n- relay: `wss:\/\/djbas.sadkb.com`\n\n\n## Notes\n\n- `npub` keys MUST NOT be used in NIP-01 events or in NIP-05 JSON responses, only the hex format is supported there.\n- When decoding a bech32-formatted string, TLVs that are not recognized or supported should be ignored, rather than causing an error.","image":null,"pubkey":"c89e5eb6d9ab087e36d122a1674167053179200226cbf082bca1c492e858ffac","kind":30023,"createdAt":"2026-05-19T13:28:20+00:00","publishedAt":"2026-05-16T10:42:26+00:00","topics":["nips","nostr","dev","digital","nip19"],"url":"https:\/\/www.decentnewsroom.com\/mag\/decent-newsroom-documentation-1f07d7\/cat\/nostr-implementation-possibilities-c7f417\/d\/nip-19-9e6ih1"},{"title":"NIP-09","slug":"nip-09-k7hy5t","summary":"Event Deletion Requests define how Nostr users can ask relays and clients to stop showing events they authored.","content":"## Event Deletion Request\n\n`draft` `optional` `relay`\n\nA special event with kind `5`, meaning \u0022deletion request\u0022 is defined as having a list of one or more `e` or `a` tags, each referencing an event the author is requesting to be deleted. Deletion requests SHOULD include a `k` tag for the kind of each event being requested for deletion.\n\nThe event\u0027s `content` field MAY contain a text note describing the reason for the deletion request.\n\nFor example:\n\n```\n{\n  \u0022kind\u0022: 5,\n  \u0022pubkey\u0022: \u003C32-bytes hex-encoded public key of the event creator\u003E,\n  \u0022tags\u0022: [\n    [\u0022e\u0022, \u0022dcd59..464a2\u0022],\n    [\u0022e\u0022, \u0022968c5..ad7a4\u0022],\n    [\u0022a\u0022, \u0022\u003Ckind\u003E:\u003Cpubkey\u003E:\u003Cd-identifier\u003E\u0022],\n    [\u0022k\u0022, \u00221\u0022],\n    [\u0022k\u0022, \u002230023\u0022]\n  ],\n  \u0022content\u0022: \u0022these posts were published by accident\u0022,\n  \/\/ other fields...\n}\n```\n\n\nRelays SHOULD delete or stop publishing any referenced events that have an identical `pubkey` as the deletion request.  Clients SHOULD hide or otherwise indicate a deletion request status for referenced events.\n\nRelays SHOULD continue to publish\/share the deletion request events indefinitely, as clients may already have the event that\u0027s intended to be deleted. Additionally, clients SHOULD broadcast deletion request events to other relays which don\u0027t have it.\n\nWhen an `a` tag is used, relays SHOULD delete all versions of the replaceable event up to the `created_at` timestamp of the deletion request event.\n\n## Client Usage\n\nClients MAY choose to fully hide any events that are referenced by valid deletion request events.  This includes text notes, direct messages, or other yet-to-be defined event kinds.  Alternatively, they MAY show the event along with an icon or other indication that the author has \u0022disowned\u0022 the event.  The `content` field MAY also be used to replace the deleted events\u0027 own content, although a user interface should clearly indicate that this is a deletion request reason, not the original content.\n\nA client MUST validate that each event `pubkey` referenced in the `e` tag of the deletion request is identical to the deletion request `pubkey`, before hiding or deleting any event.  Relays can not, in general, perform this validation and should not be treated as authoritative.\n\nClients display the deletion request event itself in any way they choose, e.g., not at all, or with a prominent notice.\n\nClients MAY choose to inform the user that their request for deletion does not guarantee deletion because it is impossible to delete events from all relays and clients.\n\n## Relay Usage\n\nRelays MAY validate that a deletion request event only references events that have the same `pubkey` as the deletion request itself, however this is not required since relays may not have knowledge of all referenced events.\n\n## Deletion Request of a Deletion Request\n\nPublishing a deletion request event against a deletion request has no effect.  Clients and relays are not obliged to support \u0022unrequest deletion\u0022 functionality.","image":null,"pubkey":"c89e5eb6d9ab087e36d122a1674167053179200226cbf082bca1c492e858ffac","kind":30023,"createdAt":"2026-05-16T10:25:28+00:00","publishedAt":"2026-05-16T10:25:28+00:00","topics":["nips","nostr","dev","digital","nip09"],"url":"https:\/\/www.decentnewsroom.com\/mag\/decent-newsroom-documentation-1f07d7\/cat\/nostr-implementation-possibilities-c7f417\/d\/nip-09-k7hy5t"},{"title":"NIP-07","slug":"nip-07-cml0s7","summary":"NIP-07 defines the browser interface that lets Nostr web apps talk to user signers. It standardizes the optional window.nostr object, usually provided by a browser extension, so websites can request a user\u2019s public key and ask the signer to sign Nostr events without ever handling the user\u2019s private key directly.","content":"## `window.nostr` capability for web browsers\n\n`draft` `optional`\n\nThe `window.nostr` object may be made available by web browsers or extensions and websites or web-apps may make use of it after checking its availability.\n\nThat object must define the following methods:\n\n```\nasync window.nostr.getPublicKey(): string \/\/ returns a public key as hex\nasync window.nostr.signEvent(event: { created_at: number, kind: number, tags: string[][], content: string }): Event \/\/ takes an event object, adds `id`, `pubkey` and `sig` and returns it\n```\n\n\nAside from these two basic above, the following functions can also be implemented optionally:\n```\nasync window.nostr.nip04.encrypt(pubkey, plaintext): string \/\/ returns ciphertext and iv as specified in nip-04 (deprecated)\nasync window.nostr.nip04.decrypt(pubkey, ciphertext): string \/\/ takes ciphertext and iv as specified in nip-04 (deprecated)\nasync window.nostr.nip44.encrypt(pubkey, plaintext): string \/\/ returns ciphertext as specified in nip-44\nasync window.nostr.nip44.decrypt(pubkey, ciphertext): string \/\/ takes ciphertext as specified in nip-44\n```\n\n\n### Recommendation to Extension Authors\nTo make sure that the `window.nostr` is available to nostr clients on page load, the authors who create Chromium and Firefox extensions should load their scripts by specifying `\u0022run_at\u0022: \u0022document_end\u0022` in the extension\u0027s manifest.\n\n\n### Implementation\n\nSee [https:\/\/github.com\/aljazceru\/awesome-nostr#nip-07-browser-extensions](https:\/\/github.com\/aljazceru\/awesome-nostr#nip-07-browser-extensions).","image":null,"pubkey":"c89e5eb6d9ab087e36d122a1674167053179200226cbf082bca1c492e858ffac","kind":30023,"createdAt":"2026-05-16T10:21:55+00:00","publishedAt":"2026-05-16T10:21:55+00:00","topics":["nips","nostr","dev","digital","nip07"],"url":"https:\/\/www.decentnewsroom.com\/mag\/decent-newsroom-documentation-1f07d7\/cat\/nostr-implementation-possibilities-c7f417\/d\/nip-07-cml0s7"},{"title":"NIP-05","slug":"nip-05-v450p8","summary":"This NIP defines a mapping of Nostr keys to DNS-based internet identifiers.\n","content":"# Mapping Nostr keys to DNS-based internet identifiers\n\n`final` `optional`\n\nOn events of kind `0` (`user metadata`) one can specify the key `\u0022nip05\u0022` with an [internet identifier](https:\/\/datatracker.ietf.org\/doc\/html\/rfc5322#section-3.4.1) (an email-like address) as the value. Although there is a link to a very liberal \u0022internet identifier\u0022 specification above, NIP-05 assumes the `\u003Clocal-part\u003E` part will be restricted to the characters `a-z0-9-_.`, case-insensitive.\n\nUpon seeing that, the client splits the identifier into `\u003Clocal-part\u003E` and `\u003Cdomain\u003E` and use these values to make a GET request to `https:\/\/\u003Cdomain\u003E\/.well-known\/nostr.json?name=\u003Clocal-part\u003E`.\n\nThe result should be a JSON document object with a key `\u0022names\u0022` that should then be a mapping of names to hex formatted public keys. If the public key for the given `\u003Cname\u003E` matches the `pubkey` from the `user metadata` event, the client then concludes that the given pubkey can indeed be referenced by its identifier.\n\n## Example\n\nIf a client sees an event like this:\n\n```\n{\n  \u0022pubkey\u0022: \u0022b0635d6a9851d3aed0cd6c495b282167acf761729078d975fc341b22650b07b9\u0022,\n  \u0022kind\u0022: 0,\n  \u0022content\u0022: \u0022{\\\u0022name\\\u0022: \\\u0022bob\\\u0022, \\\u0022nip05\\\u0022: \\\u0022bob@example.com\\\u0022}\u0022\n  \/\/ other fields...\n}\n```\n\n\nIt will make a GET request to `https:\/\/example.com\/.well-known\/nostr.json?name=bob` and get back a response that will look like\n\n```\n{\n  \u0022names\u0022: {\n    \u0022bob\u0022: \u0022b0635d6a9851d3aed0cd6c495b282167acf761729078d975fc341b22650b07b9\u0022\n  }\n}\n```\n\n\nor with the **recommended** `\u0022relays\u0022` attribute:\n\n```\n{\n  \u0022names\u0022: {\n    \u0022bob\u0022: \u0022b0635d6a9851d3aed0cd6c495b282167acf761729078d975fc341b22650b07b9\u0022\n  },\n  \u0022relays\u0022: {\n    \u0022b0635d6a9851d3aed0cd6c495b282167acf761729078d975fc341b22650b07b9\u0022: [ \u0022wss:\/\/relay.example.com\u0022, \u0022wss:\/\/relay2.example.com\u0022 ]\n  }\n}\n```\n\n\nIf the pubkey matches the one given in `\u0022names\u0022` (as in the example above) that means the association is right and the `\u0022nip05\u0022` identifier is valid and can be displayed.\n\nThe recommended `\u0022relays\u0022` attribute may contain an object with public keys as properties and arrays of relay URLs as values. When present, that can be used to help clients learn in which relays the specific user may be found. Web servers which serve `\/.well-known\/nostr.json` files dynamically based on the query string SHOULD also serve the relays data for any name they serve in the same reply when that is available.\n\n## Finding users from their NIP-05 identifier\n\nA client may implement support for finding users\u0027 public keys from _internet identifiers_, the flow is the same as above, but reversed: first the client fetches the _well-known_ URL and from there it gets the public key of the user, then it tries to fetch the kind `0` event for that user and check if it has a matching `\u0022nip05\u0022`.\n\n## Notes\n\n### Identification, not verification\n\nThe NIP-05 is not intended to _verify_ a user, but only to _identify_ them, for the purpose of facilitating the exchange of a contact or their search.\nExceptions are people who own (e.g., a company) or are connected (e.g., a project) to a well-known domain, who can exploit NIP-05 as an attestation of their relationship with it, and thus to the organization behind it, thereby gaining an element of trust.\n\n### User discovery implementation suggestion\n\nA client can use this to allow users to search other profiles. If a client has a search box or something like that, a user may be able to type \u0022bob@example.com\u0022 there and the client would recognize that and do the proper queries to obtain a pubkey and suggest that to the user.\n\n### Clients must always follow public keys, not NIP-05 addresses\n\nFor example, if after finding that `bob@bob.com` has the public key `abc...def`, the user clicks a button to follow that profile, the client must keep a primary reference to `abc...def`, not `bob@bob.com`. If, for any reason, the address `https:\/\/bob.com\/.well-known\/nostr.json?name=bob` starts returning the public key `1d2...e3f` at any time in the future, the client must not replace `abc...def` in his list of followed profiles for the user (but it should stop displaying \u0022bob@bob.com\u0022 for that user, as that will have become an invalid `\u0022nip05\u0022` property).\n\n### Public keys must be in hex format\n\nKeys must be returned in hex format. Keys in NIP-19 `npub` format are only meant to be used for display in client UIs, not in this NIP.\n\n### Showing just the domain as an identifier\n\nClients may treat the identifier `_@domain` as the \u0022root\u0022 identifier, and choose to display it as just the `\u003Cdomain\u003E`. For example, if Bob owns `bob.com`, he may not want an identifier like `bob@bob.com` as that is redundant. Instead, Bob can use the identifier `_@bob.com` and expect Nostr clients to show and treat that as just `bob.com` for all purposes.\n\n### Reasoning for the `\/.well-known\/nostr.json?name=\u003Clocal-part\u003E` format\n\nBy adding the `\u003Clocal-part\u003E` as a query string instead of as part of the path, the protocol can support both dynamic servers that can generate JSON on-demand and static servers with a JSON file in it that may contain multiple names.\n\n### Allowing access from JavaScript apps\n\nJavaScript Nostr apps may be restricted by browser [CORS][] policies that prevent them from accessing `\/.well-known\/nostr.json` on the user\u0027s domain. When CORS prevents JS from loading a resource, the JS program sees it as a network failure identical to the resource not existing, so it is not possible for a pure-JS app to tell the user for certain that the failure was caused by a CORS issue. JS Nostr apps that see network failures requesting `\/.well-known\/nostr.json` files may want to recommend to users that they check the CORS policy of their servers, e.g.:\n\n```\n$ curl -sI https:\/\/example.com\/.well-known\/nostr.json?name=bob | grep -i ^Access-Control\nAccess-Control-Allow-Origin: *\n```\n\n\nUsers should ensure that their `\/.well-known\/nostr.json` is served with the HTTP header `Access-Control-Allow-Origin: *` to ensure it can be validated by pure JS apps running in modern browsers.\n\n[CORS]: https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/HTTP\/CORS\n\n### Security Constraints\n\nThe `\/.well-known\/nostr.json` endpoint MUST NOT return any HTTP redirects.\n\nFetchers MUST ignore any HTTP redirects given by the `\/.well-known\/nostr.json` endpoint.","image":null,"pubkey":"c89e5eb6d9ab087e36d122a1674167053179200226cbf082bca1c492e858ffac","kind":30023,"createdAt":"2026-03-12T12:00:01+00:00","publishedAt":"2026-03-12T12:00:01+00:00","topics":["nips","nostr","dev","digital","nip05"],"url":"https:\/\/www.decentnewsroom.com\/mag\/decent-newsroom-documentation-1f07d7\/cat\/nostr-implementation-possibilities-c7f417\/d\/nip-05-v450p8"},{"title":"NIP-03","slug":"nip-03-2h2naa","summary":"This NIP defines an event that can contain an OpenTimestamps proof for any other event.","content":"# OpenTimestamps Attestations for Events\n\n`draft` `optional`\n\nThis NIP defines an event with `kind:1040` that can contain an [OpenTimestamps](https:\/\/opentimestamps.org\/) proof for any other event:\n\n```\n{\n  \u0022kind\u0022: 1040\n  \u0022tags\u0022: [\n    [\u0022e\u0022, \u003Ctarget-event-id\u003E, \u003Crelay-url\u003E],\n    [\u0022k\u0022, \u0022\u003Ctarget-event-kind\u003E\u0022]\n  ],\n  \u0022content\u0022: \u003Cbase64-encoded OTS file data\u003E\n}\n```\n\n\n- The OpenTimestamps proof MUST prove the referenced `e` event id as its digest.\n- The `content` MUST be the full content of an `.ots` file containing at least one Bitcoin attestation. This file SHOULD contain a **single** Bitcoin attestation (as not more than one valid attestation is necessary and less bytes is better than more) and no reference to \u0022pending\u0022 attestations since they are useless in this context.\n\n\n## Example OpenTimestamps proof verification flow\n\nUsing [`nak`](https:\/\/github.com\/fiatjaf\/nak), [`jq`](https:\/\/jqlang.github.io\/jq\/) and [`ots`](https:\/\/github.com\/fiatjaf\/ots):\n\n```\n~\u003E nak req -i e71c6ea722987debdb60f81f9ea4f604b5ac0664120dd64fb9d23abc4ec7c323 wss:\/\/nostr-pub.wellorder.net | jq -r .content | ots verify\n\u003E using an esplora server at https:\/\/blockstream.info\/api\n- sequence ending on block 810391 is valid\ntimestamp validated at block [810391]\n```","image":null,"pubkey":"c89e5eb6d9ab087e36d122a1674167053179200226cbf082bca1c492e858ffac","kind":30023,"createdAt":"2026-01-25T19:10:21+00:00","publishedAt":"2026-01-25T19:10:21+00:00","topics":["nips","nostr","dev","digital","client","relay","opentimestamps","attestations"],"url":"https:\/\/www.decentnewsroom.com\/mag\/decent-newsroom-documentation-1f07d7\/cat\/nostr-implementation-possibilities-c7f417\/d\/nip-03-2h2naa"},{"title":"NIP-02","slug":"nip-02-utznwt","summary":"A special event with kind 3, meaning \u0022follow list\u0022 is defined as having a list of p tags, one for each of the followed\/known profiles one is following.","content":"# Follow List\n\n`final` `optional`\n\nEach tag entry should contain the key for the profile, a relay URL where events from that key can be found (can be set to an empty string if not needed), and a local name (or \u0022petname\u0022) for that profile (can also be set to an empty string or not provided), i.e., `[\u0022p\u0022, \u003C32-bytes hex key\u003E, \u003Cmain relay URL\u003E, \u003Cpetname\u003E]`.\n\nThe `.content` is not used.\n\nFor example:\n\n```\n{\n  \u0022kind\u0022: 3,\n  \u0022tags\u0022: [\n    [\u0022p\u0022, \u002291cf9..4e5ca\u0022, \u0022wss:\/\/alicerelay.com\/\u0022, \u0022alice\u0022],\n    [\u0022p\u0022, \u002214aeb..8dad4\u0022, \u0022wss:\/\/bobrelay.com\/nostr\u0022, \u0022bob\u0022],\n    [\u0022p\u0022, \u0022612ae..e610f\u0022, \u0022ws:\/\/carolrelay.com\/ws\u0022, \u0022carol\u0022]\n  ],\n  \u0022content\u0022: \u0022\u0022,\n  \/\/ other fields...\n}\n```\n\n\nEvery new following list that gets published overwrites the past ones, so it should contain all entries. Relays and clients SHOULD delete past following lists as soon as they receive a new one.\n\nWhenever new follows are added to an existing list, clients SHOULD append them to the end of the list, so they are stored in chronological order.\n\n## Uses\n\n### Follow list backup\n\nIf one believes a relay will store their events for sufficient time, they can use this kind-3 event to backup their following list and recover on a different device.\n\n### Profile discovery and context augmentation\n\nA client may rely on the kind-3 event to display a list of followed people by profiles one is browsing; make lists of suggestions on who to follow based on the follow lists of other people one might be following or browsing; or show the data in other contexts.\n\n### Relay sharing\n\nA client may publish a follow list with good relays for each of their follows so other clients may use these to update their internal relay lists if needed, increasing censorship-resistance.\n\n### Petname scheme\n\nThe data from these follow lists can be used by clients to construct local [\u0022petname\u0022](http:\/\/www.skyhunter.com\/marcs\/petnames\/IntroPetNames.html) tables derived from other people\u0027s follow lists. This alleviates the need for global human-readable names. For example:\n\nA user has an internal follow list that says\n\n```\n[\n  [\u0022p\u0022, \u002221df6d143fb96c2ec9d63726bf9edc71\u0022, \u0022\u0022, \u0022erin\u0022]\n]\n```\n\n\nAnd receives two follow lists, one from `21df6d143fb96c2ec9d63726bf9edc71` that says\n\n```\n[\n  [\u0022p\u0022, \u0022a8bb3d884d5d90b413d9891fe4c4e46d\u0022, \u0022\u0022, \u0022david\u0022]\n]\n```\n\n\nand another from `a8bb3d884d5d90b413d9891fe4c4e46d` that says\n\n```\n[\n  [\u0022p\u0022, \u0022f57f54057d2a7af0efecc8b0b66f5708\u0022, \u0022\u0022, \u0022frank\u0022]\n]\n```\n\n\nWhen the user sees `21df6d143fb96c2ec9d63726bf9edc71` the client can show _erin_ instead;\nWhen the user sees `a8bb3d884d5d90b413d9891fe4c4e46d` the client can show _david.erin_ instead;\nWhen the user sees `f57f54057d2a7af0efecc8b0b66f5708` the client can show _frank.david.erin_ instead.","image":null,"pubkey":"c89e5eb6d9ab087e36d122a1674167053179200226cbf082bca1c492e858ffac","kind":30023,"createdAt":"2026-01-25T18:55:55+00:00","publishedAt":"2026-01-25T18:55:55+00:00","topics":["nips","nostr","dev","digital","client","relay","follow list","follows","contacts"],"url":"https:\/\/www.decentnewsroom.com\/mag\/decent-newsroom-documentation-1f07d7\/cat\/nostr-implementation-possibilities-c7f417\/d\/nip-02-utznwt"},{"title":"NIP-01","slug":"nip-01-5agk64","summary":"This NIP defines the basic protocol that should be implemented by everybody. New NIPs may add new optional (or mandatory) fields and messages and features to the structures and flows described here.","content":"# Basic protocol flow description\n\n`draft` `mandatory` `relay`\n\n## Events and signatures\n\nEach user has a keypair. Signatures, public key, and encodings are done according to the [Schnorr signatures standard for the curve `secp256k1`](https:\/\/bips.xyz\/340).\n\nThe only object type that exists is the `event`, which has the following format on the wire:\n\n```\n{\n  \u0022id\u0022: \u003C32-bytes lowercase hex-encoded sha256 of the serialized event data\u003E,\n  \u0022pubkey\u0022: \u003C32-bytes lowercase hex-encoded public key of the event creator\u003E,\n  \u0022created_at\u0022: \u003Cunix timestamp in seconds\u003E,\n  \u0022kind\u0022: \u003Cinteger between 0 and 65535\u003E,\n  \u0022tags\u0022: [\n    [\u003Carbitrary string\u003E...],\n    \/\/ ...\n  ],\n  \u0022content\u0022: \u003Carbitrary string\u003E,\n  \u0022sig\u0022: \u003C64-bytes lowercase hex of the signature of the sha256 hash of the serialized event data, which is the same as the \u0022id\u0022 field\u003E\n}\n```\n\n\nTo obtain the `event.id`, we `sha256` the serialized event. The serialization is done over the UTF-8 JSON-serialized string (which is described below) of the following structure:\n\n```\n[\n  0,\n  \u003Cpubkey, as a lowercase hex string\u003E,\n  \u003Ccreated_at, as a number\u003E,\n  \u003Ckind, as a number\u003E,\n  \u003Ctags, as an array of arrays of non-null strings\u003E,\n  \u003Ccontent, as a string\u003E\n]\n```\n\n\nTo prevent implementation differences from creating a different event ID for the same event, the following rules MUST be followed while serializing:\n- UTF-8 should be used for encoding.\n- Whitespace, line breaks or other unnecessary formatting should not be included in the output JSON.\n- The following characters in the content field must be escaped as shown, and all other characters must be included verbatim:\n- A line break (`0x0A`), use `\\n`\n- A double quote (`0x22`), use `\\\u0022`\n- A backslash (`0x5C`), use `\\\\`\n- A carriage return (`0x0D`), use `\\r`\n- A tab character (`0x09`), use `\\t`\n- A backspace, (`0x08`), use `\\b`\n- A form feed, (`0x0C`), use `\\f`\n\n\n### Tags\n\nEach tag is an array of one or more strings, with some conventions around them. Take a look at the example below:\n\n```\n{\n  \u0022tags\u0022: [\n    [\u0022e\u0022, \u00225c83da77af1dec6d7289834998ad7aafbd9e2191396d75ec3cc27f5a77226f36\u0022, \u0022wss:\/\/nostr.example.com\u0022],\n    [\u0022p\u0022, \u0022f7234bd4c1394dda46d09f35bd384dd30cc552ad5541990f98844fb06676e9ca\u0022],\n    [\u0022a\u0022, \u002230023:f7234bd4c1394dda46d09f35bd384dd30cc552ad5541990f98844fb06676e9ca:abcd\u0022, \u0022wss:\/\/nostr.example.com\u0022],\n    [\u0022alt\u0022, \u0022reply\u0022],\n    \/\/ ...\n  ],\n  \/\/ ...\n}\n```\n\n\nThe first element of the tag array is referred to as the tag _name_ or _key_ and the second as the tag _value_. So we can safely say that the event above has an `e` tag set to `\u00225c83da77af1dec6d7289834998ad7aafbd9e2191396d75ec3cc27f5a77226f36\u0022`, an `alt` tag set to `\u0022reply\u0022` and so on. All elements after the second do not have a conventional name.\n\nThis NIP defines 3 standard tags that can be used across all event kinds with the same meaning. They are as follows:\n\n- The `e` tag, used to refer to an event: `[\u0022e\u0022, \u003C32-bytes lowercase hex of the id of another event\u003E, \u003Crecommended relay URL, optional\u003E, \u003C32-bytes lowercase hex of the author\u0027s pubkey, optional\u003E]`\n- The `p` tag, used to refer to another user: `[\u0022p\u0022, \u003C32-bytes lowercase hex of a pubkey\u003E, \u003Crecommended relay URL, optional\u003E]`\n- The `a` tag, used to refer to an addressable or replaceable event\n- for an addressable event: `[\u0022a\u0022, \u0022\u003Ckind integer\u003E:\u003C32-bytes lowercase hex of a pubkey\u003E:\u003Cd tag value\u003E\u0022, \u003Crecommended relay URL, optional\u003E]`\n- for a normal replaceable event: `[\u0022a\u0022, \u0022\u003Ckind integer\u003E:\u003C32-bytes lowercase hex of a pubkey\u003E:\u0022, \u003Crecommended relay URL, optional\u003E]` (note: include the trailing colon)\n\n\nAs a convention, all single-letter (only english alphabet letters: a-z, A-Z) key tags are expected to be indexed by relays, such that it is possible, for example, to query or subscribe to events that reference the event `\u00225c83da77af1dec6d7289834998ad7aafbd9e2191396d75ec3cc27f5a77226f36\u0022` by using the `{\u0022#e\u0022: [\u00225c83da77af1dec6d7289834998ad7aafbd9e2191396d75ec3cc27f5a77226f36\u0022]}` filter. Only the first value in any given tag is indexed.\n\n### Kinds\n\nKinds specify how clients should interpret the meaning of each event and the other fields of each event (e.g. an `\u0022r\u0022` tag may have a meaning in an event of kind 1 and an entirely different meaning in an event of kind 10002). Each NIP may define the meaning of a set of kinds that weren\u0027t defined elsewhere. [NIP-10](10.md), for instance, specifies the `kind:1` text note for social media applications.\n\nThis NIP defines one basic kind:\n\n- `0`: **user metadata**: the `content` is set to a stringified JSON object `{name: \u003Cnickname or full name\u003E, about: \u003Cshort bio\u003E, picture: \u003Curl of the image\u003E}` describing the user who created the event. [Extra metadata fields](24.md#kind-0) may be set. A relay may delete older events once it gets a new one for the same pubkey.\n\n\nAnd also a convention for kind ranges that allow for easier experimentation and flexibility of relay implementation:\n\n- for kind `n` such that `1000 \u003C= n \u003C 10000 || 4 \u003C= n \u003C 45 || n == 1 || n == 2`, events are **regular**, which means they\u0027re all expected to be stored by relays.\n- for kind `n` such that `10000 \u003C= n \u003C 20000 || n == 0 || n == 3`, events are **replaceable**, which means that, for each combination of `pubkey` and `kind`, only the latest event MUST be stored by relays, older versions MAY be discarded.\n- for kind `n` such that `20000 \u003C= n \u003C 30000`, events are **ephemeral**, which means they are not expected to be stored by relays.\n- for kind `n` such that `30000 \u003C= n \u003C 40000`, events are **addressable** by their `kind`, `pubkey` and `d` tag value -- which means that, for each combination of `kind`, `pubkey` and the `d` tag value, only the latest event MUST be stored by relays, older versions MAY be discarded.\n\n\nIn case of replaceable events with the same timestamp, the event with the lowest id (first in lexical order) should be retained, and the other discarded.\n\nWhen answering to `REQ` messages for replaceable events such as `{\u0022kinds\u0022:[0],\u0022authors\u0022:[\u003Chex-key\u003E]}`, even if the relay has more than one version stored, it SHOULD return just the latest one.\n\nThese are just conventions and relay implementations may differ.\n\n## Communication between clients and relays\n\nRelays expose a websocket endpoint to which clients can connect. Clients SHOULD open a single websocket connection to each relay and use it for all their subscriptions. Relays MAY limit number of connections from specific IP\/client\/etc.\n\n### From client to relay: sending events and creating subscriptions\n\nClients can send 3 types of messages, which must be JSON arrays, according to the following patterns:\n\n- `[\u0022EVENT\u0022, \u003Cevent JSON as defined above\u003E]`, used to publish events.\n- `[\u0022REQ\u0022, \u003Csubscription_id\u003E, \u003Cfilters1\u003E, \u003Cfilters2\u003E, ...]`, used to request events and subscribe to new updates.\n- `[\u0022CLOSE\u0022, \u003Csubscription_id\u003E]`, used to stop previous subscriptions.\n\n\n`\u003Csubscription_id\u003E` is an arbitrary, non-empty string of max length 64 chars. It represents a subscription per connection. Relays MUST manage `\u003Csubscription_id\u003E`s independently for each WebSocket connection. `\u003Csubscription_id\u003E`s are not guaranteed to be globally unique.\n\n`\u003CfiltersX\u003E` is a JSON object that determines what events will be sent in that subscription, it can have the following attributes:\n\n```\n{\n  \u0022ids\u0022: \u003Ca list of event ids\u003E,\n  \u0022authors\u0022: \u003Ca list of lowercase pubkeys, the pubkey of an event must be one of these\u003E,\n  \u0022kinds\u0022: \u003Ca list of a kind numbers\u003E,\n  \u0022#\u003Csingle-letter (a-zA-Z)\u003E\u0022: \u003Ca list of tag values, for #e \u2014 a list of event ids, for #p \u2014 a list of pubkeys, etc.\u003E,\n  \u0022since\u0022: \u003Can integer unix timestamp in seconds. Events must have a created_at \u003E= to this to pass\u003E,\n  \u0022until\u0022: \u003Can integer unix timestamp in seconds. Events must have a created_at \u003C= to this to pass\u003E,\n  \u0022limit\u0022: \u003Cmaximum number of events relays SHOULD return in the initial query\u003E\n}\n```\n\n\nUpon receiving a `REQ` message, the relay SHOULD return events that match the filter. Any new events it receives SHOULD be sent to that same websocket until the connection is closed, a `CLOSE` event is received with the same `\u003Csubscription_id\u003E`, or a new `REQ` is sent using the same `\u003Csubscription_id\u003E` (in which case a new subscription is created, replacing the old one).\n\nFilter attributes containing lists (`ids`, `authors`, `kinds` and tag filters like `#e`) are JSON arrays with one or more values. At least one of the arrays\u0027 values must match the relevant field in an event for the condition to be considered a match. For scalar event attributes such as `authors` and `kind`, the attribute from the event must be contained in the filter list. In the case of tag attributes such as `#e`, for which an event may have multiple values, the event and filter condition values must have at least one item in common.\n\nThe `ids`, `authors`, `#e` and `#p` filter lists MUST contain exact 64-character lowercase hex values.\n\nThe `since` and `until` properties can be used to specify the time range of events returned in the subscription. If a filter includes the `since` property, events with `created_at` greater than or equal to `since` are considered to match the filter. The `until` property is similar except that `created_at` must be less than or equal to `until`. In short, an event matches a filter if `since \u003C= created_at \u003C= until` holds.\n\nAll conditions of a filter that are specified must match for an event for it to pass the filter, i.e., multiple conditions are interpreted as `\u0026\u0026` conditions.\n\nA `REQ` message may contain multiple filters. In this case, events that match any of the filters are to be returned, i.e., multiple filters are to be interpreted as `||` conditions.\n\nThe `limit` property of a filter is only valid for the initial query and MUST be ignored afterwards. When `limit: n` is present it is assumed that the events returned in the initial query will be the last `n` events ordered by the `created_at`. Newer events should appear first, and in the case of ties the event with the lowest id (first in lexical order) should be first. Relays SHOULD use the `limit` value to guide how many events are returned in the initial response. Returning fewer events is acceptable, but returning (much) more should be avoided to prevent overwhelming clients.\n\n### From relay to client: sending events and notices\n\nRelays can send 5 types of messages, which must also be JSON arrays, according to the following patterns:\n\n- `[\u0022EVENT\u0022, \u003Csubscription_id\u003E, \u003Cevent JSON as defined above\u003E]`, used to send events requested by clients.\n- `[\u0022OK\u0022, \u003Cevent_id\u003E, \u003Ctrue|false\u003E, \u003Cmessage\u003E]`, used to indicate acceptance or denial of an `EVENT` message.\n- `[\u0022EOSE\u0022, \u003Csubscription_id\u003E]`, used to indicate the _end of stored events_ and the beginning of events newly received in real-time.\n- `[\u0022CLOSED\u0022, \u003Csubscription_id\u003E, \u003Cmessage\u003E]`, used to indicate that a subscription was ended on the server side.\n- `[\u0022NOTICE\u0022, \u003Cmessage\u003E]`, used to send human-readable error messages or other things to clients.\n\n\nThis NIP defines no rules for how `NOTICE` messages should be sent or treated.\n\n- `EVENT` messages MUST be sent only with a subscription ID related to a subscription previously initiated by the client (using the `REQ` message above).\n- `OK` messages MUST be sent in response to `EVENT` messages received from clients, they must have the 3rd parameter set to `true` when an event has been accepted by the relay, `false` otherwise. The 4th parameter MUST always be present, but MAY be an empty string when the 3rd is `true`, otherwise it MUST be a string formed by a machine-readable single-word prefix followed by a `:` and then a human-readable message. Some examples:\n- `[\u0022OK\u0022, \u0022b1a649ebe8...\u0022, true, \u0022\u0022]`\n- `[\u0022OK\u0022, \u0022b1a649ebe8...\u0022, true, \u0022pow: difficulty 25\u003E=24\u0022]`\n- `[\u0022OK\u0022, \u0022b1a649ebe8...\u0022, true, \u0022duplicate: already have this event\u0022]`\n- `[\u0022OK\u0022, \u0022b1a649ebe8...\u0022, false, \u0022blocked: you are banned from posting here\u0022]`\n- `[\u0022OK\u0022, \u0022b1a649ebe8...\u0022, false, \u0022blocked: please register your pubkey at https:\/\/my-expensive-relay.example.com\u0022]`\n- `[\u0022OK\u0022, \u0022b1a649ebe8...\u0022, false, \u0022rate-limited: slow down there chief\u0022]`\n- `[\u0022OK\u0022, \u0022b1a649ebe8...\u0022, false, \u0022invalid: event creation date is too far off from the current time\u0022]`\n- `[\u0022OK\u0022, \u0022b1a649ebe8...\u0022, false, \u0022pow: difficulty 26 is less than 30\u0022]`\n- `[\u0022OK\u0022, \u0022b1a649ebe8...\u0022, false, \u0022restricted: not allowed to write.\u0022]`\n- `[\u0022OK\u0022, \u0022b1a649ebe8...\u0022, false, \u0022error: could not connect to the database\u0022]`\n- `[\u0022OK\u0022, \u0022b1a649ebe8...\u0022, false, \u0022mute: no one was listening to your ephemeral event and it wasn\u0027t handled in any way, it was ignored\u0022]`\n- `CLOSED` messages MUST be sent in response to a `REQ` when the relay refuses to fulfill it. It can also be sent when a relay decides to kill a subscription on its side before a client has disconnected or sent a `CLOSE`. This message uses the same pattern of `OK` messages with the machine-readable prefix and human-readable message. Some examples:\n- `[\u0022CLOSED\u0022, \u0022sub1\u0022, \u0022unsupported: filter contains unknown elements\u0022]`\n- `[\u0022CLOSED\u0022, \u0022sub1\u0022, \u0022error: could not connect to the database\u0022]`\n- `[\u0022CLOSED\u0022, \u0022sub1\u0022, \u0022error: shutting down idle subscription\u0022]`\n- The standardized machine-readable prefixes for `OK` and `CLOSED` are: `duplicate`, `pow`, `blocked`, `rate-limited`, `invalid`, `restricted`, `mute` and `error` for when none of that fits.","image":null,"pubkey":"c89e5eb6d9ab087e36d122a1674167053179200226cbf082bca1c492e858ffac","kind":30023,"createdAt":"2026-01-25T15:27:48+00:00","publishedAt":"2026-01-25T15:27:48+00:00","topics":["nips","nostr","dev","digital","client","relay","tag","kind"],"url":"https:\/\/www.decentnewsroom.com\/mag\/decent-newsroom-documentation-1f07d7\/cat\/nostr-implementation-possibilities-c7f417\/d\/nip-01-5agk64"}]},{"slug":"nkbip-53fa4c","title":"NKBIP","summary":"Nostr Knowledge Base Implementation Possibilities","image":null,"url":"https:\/\/www.decentnewsroom.com\/mag\/decent-newsroom-documentation-1f07d7\/cat\/nkbip-53fa4c","articleCount":2,"articles":[{"title":"NKBIP-01: Curated Publications Specification","slug":"nkbip-01-curated-publications-specification-ar6dui","summary":"This is the minimum specification for curated publications: ordered, optionally-hierarchical assemblies of Nostr events.","content":"Publications provide a standard way to organize and present related content, similar to how books organize chapters or journals organize articles.\n# Event Kinds\nThis NIP defines two primary event kinds:\n\n- `30040`: Publication Index\n- `30041`: Publication Content\n\n\n## KIND 30040: Publication Index\nA publication index defines the structure and metadata of a publication. It serves as a table of contents that references the actual content sections.\n\n### Requirements:\n\n- The `content` field MUST be empty\n- MUST include a `title` tag containing the full title of the publication\n- MUST be uniquely identifiable by the combination of:\n- `d` tag (normalized to lowercase letters, numbers, and hyphens, analog to [[NIP-54]].\n- `pubkey`\n- `kind`\n- MUST include `a` tags listing the events in desired display order.\n- Format: `[\u0022a\u0022, \u0022\u003Ckind:pubkey:dtag\u003E\u0022, \u0022\u003Crelay hint\u003E\u0022, \u0022\u003Cevent id\u003E\u0022]`\n- Optional event ID field enables version tracking while maintaining updateable references\n- Referenced events SHOULD be kind 30041 sections or nested kind 30040 indices\n- Additional event kinds MAY be supported, especially 30818 and 30023\n- MUST include an `auto-update` tag specifying update behavior:\n- Format: `[\u0022auto-update\u0022, \u0022\u003Cyes|ask|no\u003E\u0022]`\n- Controls whether clients should automatically update to newer versions\n- For derivative works:\n- MUST include a `p` tag identifying the original author\n- MUST include an `E` tag referencing the original event immediately after the `p` tag\n- MAY contain the tag \u0022source\u0022, which defines a URL which contains the location of the original text, and\/or an `i` tag.\n- MAY contain the tag \u0022version\u0022, which describes the edition.\n- MAY contain the tag \u0022type\u0022 indicates how the publication should be displayed in the viewer\/reader. Some suggested types are:\n- book (default)\n- illustrated\n- magazine\n- documentation\n- academic\n- blog\n\n\n### Example Index:\n\n```\n{\n    \u0022id\u0022: \u0022\u003Cevent_id\u003E\u0022,\n    \u0022pubkey\u0022: \u0022\u003Cevent_originator_pubkey\u003E\u0022,\n    \u0022created_at\u0022: 1725087283,\n    \u0022kind\u0022: 30040,\n    \u0022tags\u0022: [\n        [\u0022d\u0022, \u0022aesop\u0027s-fables-by-aesop\u0022],\n        [\u0022title\u0022, \u0022Aesop\u0027s Fables\u0022],\n        [\u0022author\u0022, \u0022Aesop\u0022],\n        [\u0022i\u0022, \u0022isbn:9780765382030\u0022],\n        [\u0022t\u0022, \u0022fables\u0022],\n        [\u0022t\u0022, \u0022classical\u0022],\n        [\u0022t\u0022, \u0022literature\u0022],\n        [\u0022source\u0022, \u0022https:\/\/booksonline.org\/\u0022],\n        [\u0022type\u0022, \u0022book\u0022],\n        [\u0022version\u0022, \u00223rd edition\u0022],\n        [\u0022published_on\u0022, \u00222003-05-13\u0022],\n        [\u0022published_by\u0022, \u0022public domain\u0022],\n        [\u0022image\u0022, \u0022https:\/\/imageserver.com\/piclink.jpg\u0022],\n        [\u0022summary\u0022, \u0022Collection of selected fables from the ancient Greek philosopher, known as Aesop.\u0022],\n        [\u0022a\u0022, \u0022\u003Ckind:pubkey:dtag\u003E\u0022, \u0022\u003Crelay hint\u003E\u0022, \u0022\u003Cevent id\u003E\u0022],\n        [\u0022a\u0022, \u0022\u003Ckind:pubkey:dtag\u003E\u0022, \u0022\u003Crelay hint\u003E\u0022, \u0022\u003Cevent id\u003E\u0022],\n        [\u0022auto-update\u0022, \u0022\u003Cyes|ask|no\u003E\u0022],\n        [\u0022p\u0022, \u0022\u003Cpubkey_0\u003E\u0022],\n        [\u0022E\u0022, \u0022\u003Coriginal_event_id\u003E\u0022, \u0022\u003Crelay_url\u003E\u0022, \u0022\u003Cpubkey\u003E\u0022]\n    ],\n    \u0022sig\u0022: \u0022\u003Cevent_signature\u003E\u0022\n}\n```\n\n\n## KIND 30041: Publication Content\n\nAlso known as sections, zettels, episodes, or chapters contain the actual content that makes up a publication.\n\n### Requirements:\n\n- MUST include a `d` tag\n- MUST include a `title` tag describing the section (e.g., \u0022Introduction\u0022, \u0022Chapter 1\u0022, etc.)\n- The `content` field:\n- MUST contain text meant for display to the end user\n- MAY contain AsciiDoc markup\n- MAY contain wikilinks (denoted by double brackets)\n\n\n### Example Section:\n\n```\n{\n    \u0022id\u0022: \u0022\u003Cevent_id\u003E\u0022,\n    \u0022pubkey\u0022: \u00228ae74c618a4713f32129...\u0022,\n    \u0022created_at\u0022: 1708083476,\n    \u0022kind\u0022: 30041,\n    \u0022tags\u0022: [\n        [\u0022title\u0022, \u0022The Farmer and The Snake\u0022],\n        [\u0022d\u0022, \u0022aesop\u0027s-fables-by-aesop-the-farmer-and-the-snake\u0022],\n        [\u0022wikilink\u0022, \u0022fable\u0022, \u0022\u003Cpubkey\u003E\u0022, \u0022wss:\/\/thecitadel.nostr1.com\u0022, \u0022\u003Cevent id\u003E\u0022]\n    ],\n    \u0022content\u0022: \u0022The Farmer and The Snake\\nA [[fable]], by Aesop.\\nONE WINTER a Farmer found a Snake stiff and frozen with cold. He had compassion on it, and taking it up, placed it in his bosom. The Snake was quickly revived by the warmth, and resuming its natural instincts, bit its benefactor, inflicting on him a mortal wound. \u0027Oh,\u0027 cried the Farmer with his last breath, \u0027I am rightly served for pitying a scoundrel.\u0027\\nThe greatest kindness will not bind the ungrateful.\u0022,\n    \u0022sig\u0022: \u002249cab8c75fb35cec71d07258...\u0022\n}\n```\n\n\n# Extensions\nPublications are flexible and can be extended for different types of content. Examples include:\n\n- Books\n- Academic journals\n- Course materials\n- Documentation\n- Blogs, including those from different npubs\n\n\nAdditional tags relevant to the specific content type MAY be included in both index and section events.\n\n## Bookstr Macro\n\nThe [Wikistr](https:\/\/wikistr.imwald.eu) implementation can find `30041` events using a the _bookstr_ macro, which is a variation of the _wikistr_ macro.\n\nIt is structured:\n\n`[ [type:book chapter:verse | version] ]`\n\nand is a form common to Bible notations. For example:\n\n`[ [bible: John 3:16 | KJV] ]`","image":null,"pubkey":"c89e5eb6d9ab087e36d122a1674167053179200226cbf082bca1c492e858ffac","kind":30023,"createdAt":"2026-04-26T16:59:28+00:00","publishedAt":"2026-04-26T16:59:28+00:00","topics":["nips","nostr","dev","nip","nkbip","knowledge-base","publications"],"url":"https:\/\/www.decentnewsroom.com\/mag\/decent-newsroom-documentation-1f07d7\/cat\/nkbip-53fa4c\/d\/nkbip-01-curated-publications-specification-ar6dui"},{"title":"NKBIP-02: Vector-Embedding Specification","slug":"nkbip-02-vector-embedding-specification-i95bly","summary":"Proposing a format for publishing reusable vector embeddings of existing events so clients can support semantic search, recommendation, clustering, and other AI-driven use cases.","content":"![Vector embedding graph](https:\/\/i.nostr.build\/ijZF6rJ3MM0wiVjZ.png)\n\n# Embedded Content\n\nAllowing rich content to be embedded within Nostr events opens up new possibilities for applications built on the protocol. This is highly synergistic with [NKBIP-01](nostr:naddr1qqexu6mzd9cz6vp3943h2unpw3jkgttsw43xc6trv96xjmmwwvkhxur9vd5kv6trv96xjmmw94chze3nx9hsygxgne0tdkdtpplrd5fz59n5zec9x9ujqq3xe0cg909pcjfwsk8l4spsgqqqw4rsgxx6hg)\/NIP-62, where we can decompose existing events into their most semantically closed forms as defined either by the author or the analyst for precise semantic embeddings, but this process can be applied to any other event. Embeddings are also typically computationally expensive, which makes it beneficial to compute them once and store them for reuse.\n\n# Motivation\n\nHashtags and labels already exist as one way to classify content, embeddings allow for a fine grained resolution of content. Every embedding model has tradeoffs, so if you need something more specific than what is available, use your model.\n\nNostr events are public, therefore it is to be expected that any event can be analyzed. Given this fact, it only makes sense to formalize and allow anyone to work with it. Embeddings are useful for various applications, including:\n\n1. Semantic search across Nostr events\n2. Content recommendation systems\n3. Clustering similar content\n4. Multimodal AI application\n\n\n# Specification\n\nThe `1987` event are embedding specific labels for an event.\n\nRequired tags:\n\n- `e` - The id of the original event being embedded\n- `model` - The name and version of the model used to create the embedding and if possible, a link to download\/source\n- `type` - The type of content being embedded (e.g., \u0022text\u0022, \u0022image\u0022, \u0022audio\u0022, \u0022video\u0022)\n- `vector` - The embedding vector, represented as a comma-separated list of floating-point numbers\n\n\nOptional tags:\n\n- `dims` - The dimensions of the embedding vector (integer)\n- `norm` - Boolean attribute whether the vector is normalized to range [0,1]\n- If there is a download link, use the tags `hash` and `hash_type` to verify the model being used.\n- `source` - Original data source that is being embedded. Mainly suited for text. This allows the original data to be attained without fetching the original event.\n- All other tags and labeling conventions may also apply such as specified in [NKBIP-01](nostr:naddr1qqexu6mzd9cz6vp3943h2unpw3jkgttsw43xc6trv96xjmmwwvkhxur9vd5kv6trv96xjmmw94chze3nx9hsygxgne0tdkdtpplrd5fz59n5zec9x9ujqq3xe0cg909pcjfwsk8l4spsgqqqw4rsgxx6hg) and NIP-32.\n\n\nExample event:\n\n```\n{\n  \u0022id\u0022: \u0022\u003Cevent_id\u003E\u0022,\n  \u0022pubkey\u0022: \u0022\u003Cpubkey\u003E\u0022,\n  \u0022created_at\u0022: 1234567890,\n  \u0022kind\u0022: 1987,\n  \u0022tags\u0022: [\n    [\u0022e\u0022, \u0022\u003Coriginal_event_id\u003E\u0022, \u0022\u003Crelay_uri\u003E\u0022],\n    [\u0022model\u0022, \u0022openai\/text-embedding-ada-002\u0022, \u0022\u003Coptional download link\u003E\u0022],\n    [\u0022type\u0022, \u0022text\u0022],\n    [\u0022vector\u0022, [-0.006929,-0.005135,0.003592,...,0.004543]],\n    [\u0022dims\u0022, 1536],\n    [\u0022norm\u0022, true],\n    [\u0022source\u0022, \u0022This is a snippet of the original text content\u0022],\n    [\u0022hash\u0022, \u0022\u003Cstring\u003E\u0022],\n    [\u0022hash_type\u0022, \u0022\u003Cstring\u003E\u0022]\n  ],\n  \u0022content\u0022: \u0022\u0022,\n  \u0022sig\u0022: \u0022\u003Csignature\u003E\u0022\n}\n```\n\n\n## Guidelines\n\n1. For non-text embeddings (images, audio, video), the `source` tag may contain a URL or identifier for the original content.\n2. The `model` tag should be as specific as possible, including version information and location to download if available. This ensures that clients can properly interpret and compare embeddings.\n3. Multiple embedding events can reference the same original event, allowing for different embedding models or content types for the same source material.","image":null,"pubkey":"c89e5eb6d9ab087e36d122a1674167053179200226cbf082bca1c492e858ffac","kind":30023,"createdAt":"2026-03-14T15:08:43+00:00","publishedAt":"2026-03-14T15:08:43+00:00","topics":["nips","nostr","dev","nip","nkbip","knowledge-base","embedding"],"url":"https:\/\/www.decentnewsroom.com\/mag\/decent-newsroom-documentation-1f07d7\/cat\/nkbip-53fa4c\/d\/nkbip-02-vector-embedding-specification-i95bly"}]}],"chapters":[],"stats":{"totalCategories":2,"totalArticles":10,"totalChapters":0}}