30817:nip-nostr-2-web
NIP-NOSTR-2-WEB
Canonical Web URLs for Replaceable Nostr Events
draft optional
Abstract
This NIP defines a standard mechanism for addressable and replaceable Nostr events (kind:10000-19999 and kind:30000-39999, such as NIP-23 long-form articles) to declare their original, authoritative HTTP(S) web URL using an indexed r tag with a canonical marker.
This enables web-based Nostr clients and gateways to inject HTML <link rel="canonical"> tags when rendering events, preventing search engine duplicate content penalties and preserving SEO attribution for the original publisher.
Motivation
Because Nostr events are public and replicated across many relays, a single long-form article (kind:30023) is often rendered into HTML by numerous independent web clients and gateways (e.g., YakiHonne, Habla, njump, Highlighter).
When an author publishes an article on their own web domain (e.g., https://jotstr.com/my-article) and syndicates it to Nostr, search engines indexing the wider web encounter dozens of identical copies across third-party Nostr web gateways. Without a canonical signal, search engines may de-index the author's original blog in favor of a higher-authority Nostr gateway, or penalize the content as duplicate spam.
By embedding an indexed canonical URL reference directly inside the signed Nostr event, authors can instruct web-based Nostr clients to attribute SEO authority back to the origin website, while also allowing relays to be queried for events matching a specific canonical URL.
Specification
Event Kind Restriction (Replaceable Events Only)
The canonical reference marker MUST only be used on replaceable (10000 <= kind < 20000) or addressable / parameterized replaceable (30000 <= kind < 40000) events, such as NIP-23 Long-Form Content (kind:30023).
It MUST NOT be used on regular immutable events (such as kind:1 notes), because web domains and URL structures change over time; an immutable event with a dead or migrated URL would create permanent broken canonical links across the network.
The r Tag Format
To declare an authoritative web URL for a replaceable event, the author MUST include an r (reference) tag in the event's tags array with "canonical" as the third element (marker):
["r", "<https-url>", "canonical"]
- Element 1 (
"r"): Standard single-letter reference tag, ensuring relays automatically index the URL for reverse lookups ({"#r": ["<https-url>"]}). - Element 2 (
"<https-url>"): MUST be a valid, absolutehttps://(orhttp://) URL pointing to the original web publication. It SHOULD omit tracking parameters (e.g.,utm_*) and fragment identifiers (#). - Element 3 (
"canonical"): Marks this specific URL reference as the authoritative canonical source of the event's content, distinguishing it from ordinary citations or links within the article.
An event MUST NOT contain more than one r tag with the "canonical" marker. If multiple are present, clients MUST only respect the first one.
Content Equivalence Requirement
Authors MUST only attach a canonical marker when the Nostr event contains the complete equivalent body content of the target web URL.
It MUST NOT be used on teaser posts, summaries, link-drops, or commentary that merely links to an external article, as search engines reject <link rel="canonical"> tags when the page body does not closely match the canonical target.
Example Event (NIP-23 Long-Form Content)
{
"id": "...",
"pubkey": "...",
"created_at": 1729340000,
"kind": 30023,
"tags": [
["d", "my-awesome-article"],
["title", "My Awesome Article"],
["published_at", "1729340000"],
["r", "https://jotstr.com/my-awesome-article", "canonical"],
["r", "https://example.com/referenced-study"]
],
"content": "Full markdown content of the article...",
"sig": "..."
}
Implementation Guidelines for Web Clients & Gateways
1. Search Engine Attribution (<link rel="canonical">)
When a web-based Nostr client, gateway, or SSR (Server-Side Rendered) portal renders an addressable Nostr event into an HTML document accessible to web crawlers, it SHOULD check for a verified ["r", "<url>", "canonical"] tag.
If verified and reachable, the web client SHOULD inject a standard HTML canonical link element into the <head> of the rendered page:
<!DOCTYPE html>
<html>
<head>
<title>My Awesome Article</title>
<link rel="canonical" href="https://jotstr.com/my-awesome-article" />
</head>
<body>
...
</body>
</html>
2. Reverse Lookup via Relays
Because the URL is stored in an indexed single-letter r tag, browser extensions and web clients visiting https://jotstr.com/my-awesome-article can query Nostr relays to discover the corresponding Nostr event even if the web page does not embed HTML discovery tags:
["REQ", "sub_id", {"kinds": [30023], "#r": ["https://jotstr.com/my-awesome-article"]}]
Clients performing a reverse lookup via #r MUST filter the returned events locally to ensure the matching r tag includes the "canonical" marker at index 2 and passes verification.
Security, Verification, and Edge Cases
Because any Nostr keypair can sign an event containing any URL in an r tag, clients and web gateways MUST NOT blindly trust an unverified canonical marker. Failure to verify ownership and URL validity exposes gateways and users to phishing, SEO hijacking, link rot, and Server-Side Request Forgery (SSRF).
1. Anti-Phishing (NIP-05 Domain Verification)
Malicious actors may publish copied articles with a canonical URL pointing to a phishing or malware domain so users click "Originally published at..." links in Nostr clients.
- Clients SHOULD verify that the event author's verified NIP-05 identifier domain (
name@jotstr.com) matches the hostname of the canonical URL (https://jotstr.com/...) before rendering trusted source badges or clickable canonical attribution links.
2. Anti-Hijacking (Bidirectional <link rel="alternate"> Handshake)
A spammer may copy a legitimate Nostr-native article onto a third-party website and republish the event under their own keypair with a canonical tag pointing to their scraper site, or point their event to a victim's domain.
- To cryptographically prove bidirectional ownership between the web page and the Nostr event, the origin web page SHOULD implement HTML Nostr Discovery in its
<head>:
<link rel="alternate" href="nostr:naddr1..." />
- When a Nostr client or gateway fetches the target web page and confirms that its
<link rel="alternate" href="nostr:...">decodes to the exact samepubkey,kind, anddtag (vianaddr) as the Nostr event claiming that URL ascanonical, bidirectional ownership is proven even if the author does not use NIP-05.
3. Link Rot Prevention (URL Existence Check)
Web domains expire or change URL slugs over time. If a Nostr web gateway injects <link rel="canonical"> pointing to a dead (404 or unreachable) URL, search engines may de-index the surviving Nostr copy.
- Before rendering
<link rel="canonical">or displaying a canonical link to users, gateways SHOULD verify that the target URL is reachable and returns an HTTP200 OKstatus (and optionally verify the<link rel="alternate">tag during the same request). - Verification results SHOULD be cached by the gateway (e.g., for 24–72 hours) so subsequent page views do not trigger repeated outbound HTTP checks. If the URL returns a
4xx/5xxerror or times out, the gateway MUST omit the<link rel="canonical">tag and serve its own URL as canonical.
4. SSRF (Server-Side Request Forgery) Mitigation
When a Nostr web gateway or backend service performs HTTP requests to verify URL existence or check <link rel="alternate"> tags, attackers may submit internal network addresses (e.g., http://127.0.0.1:8080, http://localhost, or cloud metadata endpoints like http://169.254.169.254).
- Strict SSRF Warning: Backend services fetching
canonicalURLs MUST validate the parsed URL and resolved DNS IP addresses before connecting: - Only allow
https://(or explicitly permittedhttp://) schemes on standard ports (80,443). - Block all private, loopback, link-local, and reserved IPv4/IPv6 ranges (
127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,169.254.0.0/16,::1,fc00::/7) both on initial resolution and across any HTTP301/302redirects. - Enforce strict request timeouts (e.g., 3–5 seconds) and maximum response body read limits (e.g., only reading the first 64 KB of HTML to parse the
<head>).
Discussion
Connect a key to comment.