30817:archiving-websites-on-nostr

Archiving Websites on Nostr

Aaro

published
2025-06-05

NIP-XX

Archiving Websites on Nostr

draft

Abstract

This NIP defines a mechanism for archiving websites on Nostr by storing website assets (HTML, CSS, JavaScript, images, etc.) as events on Nostr relays. It enables decentralized, tamper-resistant storage and retrieval of web content, eliminating reliance on centralized servers. Clients can reconstruct archived websites by fetching events from relays, ensuring censorship resistance and fault tolerance.

Motivation

Centralized web hosting is vulnerable to censorship, server failures, and data loss. Archiving websites on Nostr allows content to be preserved across multiple relays, making it resilient to blocking or deletion. This NIP enables users to archive static websites, snapshots of dynamic pages, or entire sites, with verifiable integrity via public-key signatures. It supports use cases like preserving historical web content, sharing immutable site versions, and hosting decentralized web applications.

Definitions

  • Website Asset: A single file (e.g., HTML, CSS, JS, image) that constitutes part of a website.
  • Archived Website: A collection of assets stored as Nostr events, linked via event IDs to reconstruct the site.
  • Relay: A Nostr server that stores and serves events containing website assets.
  • Client: A Nostr-compatible application that publishes or retrieves archived website assets.

Event Kinds

This NIP introduces the following event kinds for archiving website assets:

  • Kind 34200: Website HTML content.
  • Kind 34201: Website CSS content.
  • Kind 34202: Website JavaScript content.
  • Kind 34203: Website image content (e.g., PNG, JPEG).
  • Kind 34204: Website metadata event (describes the archived website and links assets).

Event Structure

Asset Events (Kinds 34200–34203)

These events store the content of individual website assets.

  • content: The raw content of the asset (e.g., HTML markup, CSS rules, JS code, or base64-encoded image data).
  • tags:
    • ["x", "<SHA-256 hash of content>"]: The SHA-256 hash of the content for integrity verification.
    • ["m", "<MIME type>"]: The MIME type of the asset (e.g., text/html, text/css, application/javascript, image/png). Must be lowercase.
    • ["t", "<asset type>"]: The type of asset (html, css, js, image).
    • ["r", "<website identifier>"]: A unique identifier for the website, typically the root event ID of the metadata event (kind 34204).
  • pubkey: The public key of the user archiving the asset.
  • sig: The signature verifying the event's authenticity.

Example (HTML Asset Event):

{
  "kind": 34200,
  "content": "<!DOCTYPE html><html><head><link rel=\"stylesheet\" href=\"066b7ca0b167f0adad5c6d619ab1177050423e3979e83b8dfa069992533bdcf5\"></head><body><h1>Hello, Nostr!</h1></body></html>",
  "tags": [
    ["x", "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2"],
    ["m", "text/html"],
    ["t", "html"],
    ["r", "f7d8e9a2-4b3c-4e5a-9f6b-3c8d7f1e2a3d"]
  ],
  "pubkey": "27866e9d854c78ae625b867eefdfa9580434bc3e675be08d2acb526610d96fbe",
  "created_at": 1738794235,
  "id": "e8e616e0-d894-4936-a3f5-391682ee794c",
  "sig": "..."
}
Metadata Event (Kind 34204)

This event describes the archived website and links all associated assets.

  • content: A JSON object containing:
    • title: The title of the website.
    • description: A brief description of the archived content.
    • url: The original URL of the website (if applicable).
    • archived_at: The timestamp of archiving (Unix timestamp).
  • tags:
    • ["e", "<event ID>", "<asset type>"]: References to asset events (e.g., HTML, CSS, JS, image). <asset type> is html, css, js, or image.
    • ["d", "<website identifier>"]: A unique identifier for the website (same as used in r tags of asset events).
  • pubkey: The public key of the archiver.
  • sig: The signature verifying the event's authenticity.

Example (Metadata Event):

{
  "kind": 34204,
  "content": "{\"title\":\"Example Site\",\"description\":\"A simple archived website on Nostr\",\"url\":\"https://example.com\",\"archived_at\":1738794235}",
  "tags": [
    ["e", "e8e616e0-d894-4936-a3f5-391682ee794c", "html"],
    ["e", "066b7ca0b167f0adad5c6d619ab1177050423e3979e83b8dfa069992533bdcf5", "css"],
    ["e", "b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3", "js"],
    ["e", "c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4", "image"],
    ["d", "f7d8e9a2-4b3c-4e5a-9f6b-3c8d7f1e2a3d"]
  ],
  "pubkey": "27866e9d854c78ae625b867eefdfa9580434bc3e675be08d2acb526610d96fbe",
  "created_at": 1738794235,
  "id": "f7d8e9a2-4b3c-4e5a-9f6b-3c8d7f1e2a3d",
  "sig": "..."
}

Client Behavior

Archiving a Website
  1. Collect Assets: The client gathers all assets (HTML, CSS, JS, images) from the website.
  2. Replace Internal Links: Replace href and src attributes with the event IDs of corresponding asset events.
  3. Publish Asset Events: For each asset, create an event (kinds 34200–34203) with the asset content, MIME type, SHA-256 hash, and website identifier.
  4. Publish Metadata Event: Create a kind 34204 event linking all asset events via e tags and describing the website.
  5. Send to Relays: Publish all events to one or more Nostr relays.
Retrieving an Archived Website
  1. Query Metadata Event: The client queries relays for the kind 34204 event using the website identifier (via d tag).
  2. Fetch Asset Events: Using the e tags in the metadata event, fetch the referenced asset events (kinds 34200–34203).
  3. Verify Integrity: Check the SHA-256 hash in the x tag against the content to ensure it has not been tampered with.
  4. Render Website: Reconstruct the website by rendering the HTML, applying CSS, executing JS, and displaying images.
  5. Handle Missing Assets: If an asset is unavailable on one relay, query other relays or fallback to alternative sources (e.g., IPFS, if specified in tags).

Relay Behavior

  • Store Events: Relays store kind 34200–34204 events as they would any other Nostr event.
  • Query Support: Relays must support filtering by kind, d tag (website identifier), and e tags (event references).
  • Optional Pruning: Relays may prune older events based on their policies, but archiving relays should prioritize long-term storage.
  • Content-Type Headers: When serving asset events via HTTP (e.g., /e/<event_id>), relays should set the Content-Type header based on the m tag (e.g., text/html, image/png).

Backwards Compatibility

  • Clients and relays that do not implement this NIP will ignore kinds 34200–34204, ensuring no disruption to existing Nostr functionality.
  • The use of standard tags (e, d, x, m) aligns with existing Nostr conventions, making implementation straightforward.

Security Considerations

  • Tamper Resistance: The SHA-256 hash in the x tag ensures content integrity. Clients must verify hashes before rendering.
  • Signature Verification: Clients must validate event signatures to ensure authenticity.
  • Spam Mitigation: Relays may implement rate-limiting or authentication to prevent abuse, but this is outside the scope of this NIP.
  • Privacy: Asset content is public by default. For private archives, clients should encrypt content using NIP-04 or NIP-44 before publishing.

Extensibility

  • Additional Asset Types: New kinds can be defined for other asset types (e.g., fonts, videos) in future NIPs.
  • Alternative Storage: Tags can include references to external storage (e.g., IPFS, torrent) for redundancy.
  • Dynamic Content: Future NIPs could extend this to archive dynamic content by snapshotting server responses.

Implementation Notes

  • Clients should provide tools to crawl websites, generate events, and publish them to relays.
  • Relays supporting this NIP should advertise support for kinds 34200–34204 to help clients discover compatible infrastructure.
  • Example implementation: A browser extension could archive a webpage by generating events and publishing them to a user-specified relay.

References

Cited links

Discussion

Connect a key to comment.