Skip to content

Add NIP-5A nsite discovery, installation, and serving#171

Merged
greenart7c3 merged 8 commits into
masterfrom
claude/stoic-ramanujan-0fi2uv
Jun 29, 2026
Merged

Add NIP-5A nsite discovery, installation, and serving#171
greenart7c3 merged 8 commits into
masterfrom
claude/stoic-ramanujan-0fi2uv

Conversation

@greenart7c3

Copy link
Copy Markdown
Owner

Summary

Implements full support for discovering, installing, and serving nsites (NIP-5A static websites) on the relay. Users can browse available nsites from Nostr relays, install them locally, and access them via the relay's web server. Auto-update checks run daily and can be toggled per-site.

Key Changes

  • NsiteManager (service/NsiteManager.kt) — New singleton managing the complete nsite lifecycle:

    • Discovers nsites (kind 15128 root / 35128 named) from configured relays with deduplication by address
    • Fetches author display names (kind 0) for UI presentation
    • Downloads manifest blobs from Blossom servers with sha256 verification
    • Stores sites to filesDir/nsites/<folderName> with path-traversal guards
    • Checks for updates daily (gated like backup checks) and applies auto-updates or posts notifications
    • Extracts icon URLs from manifest path tags, prioritizing common raster formats
  • Web server integration (server/CustomWebSocketServer.kt):

    • Added serveFromDir() to serve files from plain File trees (vs. SAF DocumentFile)
    • Added startNsiteServer() / stopNsiteServer() to hot-add/remove nsite servers without relay restart
    • Nsites are served at /<folderName>.localhost:<port> alongside existing web clients
  • Settings & persistence (server/Settings.kt, service/LocalPreferences.kt):

    • Added nsites: MutableList<NsiteInfo> to store installed sites
    • Added lastNsiteCheck: Long to gate daily update checks
    • Serialization/deserialization via Jackson mapper
  • UI screens:

    • BrowseNsitesScreen — Discover and install nsites with search, progress tracking, and error handling
    • NsiteRow — Display installed nsites with auto-update toggle, update button, and delete action
    • NsiteIcon — Coil-based icon loader with globe placeholder fallback
    • Integrated into WebClientsSettingsScreen to show installed nsites alongside web clients
  • Service integration (service/WebSocketServerService.kt):

    • Daily nsite update check in the 100s timer (gated by lastNsiteCheck)
    • Auto-applies updates for sites with autoUpdate=true; posts notification otherwise
    • Notification ID 4 reserved for nsite update prompts
  • Dependencies:

    • Added Coil 3.1.0 for image loading (icons from Blossom URLs or local files)

Implementation Details

  • Manifest parsing: Extracts path (file mappings), server (Blossom hints), x (aggregate hash for change detection), title, and icon filenames from event tags
  • Blob download: Tries each Blossom server in order, verifies sha256, and falls back to author's kind-10063 server list or defaults
  • Path safety: Canonicalizes all file paths and rejects traversal attempts (e.g., ../../../etc/passwd)
  • SPA support: Falls back to index.html for extension-less routes; serves 404.html with 404 status per NIP-5A
  • Discovery relays: Uses configured aggregator relays or fallback set (damus.io, nos.lol, primal.net); filters private/onion URLs based on proxy settings
  • Deduplication: Keeps newest manifest per address across relay results
  • Folder naming: Deterministic nsite<16-hex-chars> slug from sha256(address) for hostname safety

https://claude.ai/code/session_01NgPUkQoCoYH2Fz9bPxK1j7

claude added 8 commits June 22, 2026 15:16
Extend the Web Clients settings section with nsites — static websites
published on Nostr per NIP-5A. Users can browse nsites discovered by
querying relays globally for manifest events (kinds 15128/35128), install
one (download its blobs from Blossom servers, verify each against its
path sha256, and store under filesDir/nsites), and serve it through the
existing localhost web-client mechanism.

A daily update check (gated on the existing service timer, mirroring the
weekly auto-backup) compares each installed manifest's aggregate hash and
either auto-applies the update (per-nsite toggle) or posts a notification
letting the user choose to update.

- Settings: NsiteInfo model, nsites list, lastNsiteCheck + JSON helpers
- LocalPreferences: persist nsites and last-check timestamp
- NsiteManager: discovery, blob download/verify, install, update check
- CustomWebSocketServer: File-based serveFromDir + nsite server start/stop
- WebSocketServerService: daily check + update notification
- ClipboardReceiver: notification action to apply an update
- UI: BrowseNsitesScreen, NsiteRow, Web Clients section + nav wiring

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NgPUkQoCoYH2Fz9bPxK1j7
The browser list showed the author's kind-0 profile name. NIP-5A manifests
carry an optional `title` tag (the site's own name); prefer it as the
primary label, falling back to the d tag, author name, then short pubkey.
The author name is now shown as the secondary line.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NgPUkQoCoYH2Fz9bPxK1j7
Add Coil 3 to load each nsite's icon. NIP-5A has no icon tag, so the icon
is one of the manifest's path-mapped blobs (favicon.png, etc.); the browse
list loads it from a Blossom URL and the installed list loads it from the
already-downloaded file on disk. Coil's network fetcher is wired to the
app's OkHttp client so icon requests honor the Tor/proxy fail-closed policy.
Undecodable/missing icons fall back to a globe placeholder.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NgPUkQoCoYH2Fz9bPxK1j7
Order discovered nsites by their manifest's most recent update (newest
first) instead of alphabetically, and add a search field that filters the
list by name, author, or address.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NgPUkQoCoYH2Fz9bPxK1j7
Thread a progress callback through NsiteManager.install/downloadAndStore
reporting downloaded/total blobs. While installing, the browse row shows a
determinate spinner in place of the icon and a "Installing… x/y files"
subtitle, and other rows are disabled until it finishes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NgPUkQoCoYH2Fz9bPxK1j7
Add a configurable nsite relay list (Settings.nsiteRelays, persisted) that
NsiteManager.discoveryRelays() uses when non-empty, falling back to the
aggregator relays otherwise. New NsiteRelaysSettingsScreen (reusing the
relay-list editor components) is reachable from the Web Clients nsites
section, with add/delete and a reset-to-default action.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NgPUkQoCoYH2Fz9bPxK1j7
nsite discovery now uses only the nsite relay set (defaulting to
DEFAULT_NSITE_RELAYS) and no longer falls back to the relay aggregator
relays. nsiteRelays defaults to the built-in set on fresh installs and on
reset.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NgPUkQoCoYH2Fz9bPxK1j7
@greenart7c3
greenart7c3 merged commit 664958d into master Jun 29, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants