Relay Manager Docs
Modules

relay-connect

NIP-46 / NIP-07 SDK and connect UI. MIT, composable, browser-safe.

relay-connect

Two MIT repositories, one purpose: NIP-46 remote signing without exposing keys in the browser.

RepoPackageRole
github.com/bitmacro/relay-connect@bitmacro/relay-connect (npm)Shared logic — NIP-46 / NIP-07 helpers
github.com/bitmacro/relay-connect-webReference UI (Next.js); consumes the SDK

relay-connect-web

Stack: Next.js, React
Hosting: Vercel or self-hosted
Auth model: No user login. Server-side proxy only — RELAY_API_KEY + SIGNER_PROVIDER_USER_ID in env vars; browser never holds the key.

What it does

NIP-46 path

  1. Fetches available relays for the operator via GET /api/signer/config
  2. Initiates a NIP-46 session via POST /api/signer/connect → returns nostrconnect:// URI
  3. Renders QR code for the Signer Device (Amber or any NIP-46 compatible app) to scan
  4. Watches the bridge relay for pairing progress (client + signer over bridge_wss)
  5. Completes pairing via POST /api/signer/session/:id/complete (verifies pairing_secret server-side)

NIP-07 path

  1. Detects window.nostr and getPublicKey in the browser
  2. Reads the user’s pubkey from the extension (no RELAY_API_KEY in the page)
  3. Optionally fetches kind 0 profile data via SimplePool using NEXT_PUBLIC_NIP07_METADATA_RELAYS (and defaults) — see NIP-07

NIP-07 does not create a nip46_sessions row by itself; it is for same-machine extension signing and lightweight onboarding UI. Starting NIP-46 clears NIP-07 sessionStorage so flows stay isolated.

Docs: NIP-07 · NIP-46

Server-side proxy pattern

Browser
  │ HTTPS (no API key)

relay-connect-web /api/signer/*   ← Next.js server route
  │ X-API-Key + X-Provider-User-Id (from env)

relay-api [Web Server] /signer/*
  │ SUPABASE_SERVICE_ROLE_KEY

Supabase relay.nip46_sessions

The browser only interacts with the Next.js server. The operator's RELAY_API_KEY is never exposed to clients.


@bitmacro/relay-connect (SDK)

Shared helpers for NIP-46 and NIP-07 flows. Consumed by relay-connect-web and planned for relay-panel.

  • NIP-46 session lifecycle utilities
  • NIP-07 extension detection + metadata relay resolution
  • Bridge WebSocket subscription helpers

Extraction from relay-connect-web to the SDK is ongoing — the boundary moves as patterns stabilize.


Web Server Endpoints (relay-api /signer/*)

Also mounted at /api/signer/*.

MethodRouteDescription
GET/signer/configRelays available for provider_user_id (from relay_configs)
POST/signer/connectCreate nip46_sessions row; returns session_id + nostrconnect_uri
GET/signer/sessionsList sessions (use for polling)
POST/signer/session/:id/completeVerify pairing_secret → set status active
DELETE/signer/session/:idRevoke session

Environment Variables

VariableDescription
RELAY_API_URLWeb Server base URL
RELAY_API_KEYShared key (server-side only)
SIGNER_PROVIDER_USER_IDGitHub ID for the operator's relay_configs rows
NEXT_PUBLIC_RELAY_BRIDGE_WSSForce a specific NIP-46 bridge wss://; also used for NIP-07 metadata relays
NEXT_PUBLIC_NIP07_METADATA_RELAYSComma/space-separated wss:// for kind 0 lookup after NIP-07 connect
NEXT_PUBLIC_RELAY_CONFIG_IDPin a specific relay_configs UUID; skips relay selection step
SIGNER_PROXY_TIMEOUT_MSProxy timeout in ms (default unset = Node default)

Signer Device Compatibility

Any NIP-46 compliant remote signer works. Tested:

  • Amber (Android) — recommended; native nostrconnect:// URI handling
  • Any NIP-46 bridge-compatible signer

The nostrconnect:// URI encodes the pairing_secret and bridge_wss in the query string. Each new Connect flow generates a fresh pairing_secret — reusing an existing active session without re-scanning is a product choice not implemented by default.