- Svelte 55.6%
- TypeScript 42.5%
- Dockerfile 0.8%
- Nix 0.4%
- HTML 0.4%
- Other 0.2%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
The proxy forwarded NIP-86 and NIP-11 requests to any ws(s):// URL a caller supplied, which made it an open server-side request forwarder. It now accepts only hosts from PUBLIC_DEFAULT_RELAYS; without that setting it allows only wss:// relays on public hostnames. Redirects are no longer followed and credentials in relay URLs are rejected. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> |
||
| .forgejo/workflows | ||
| e2e | ||
| src | ||
| static | ||
| .dockerignore | ||
| .envrc | ||
| .gitignore | ||
| .npmrc | ||
| CLAUDE.md | ||
| Dockerfile | ||
| flake.lock | ||
| flake.nix | ||
| LICENSE | ||
| package.json | ||
| playwright.config.ts | ||
| pnpm-lock.yaml | ||
| README.md | ||
| svelte.config.js | ||
| tsconfig.json | ||
| vite.config.ts | ||
| vitest.config.ts | ||
Relay Manager
Web-based admin panel for managing Nostr relays that support NIP-86 (Relay Management API).
Features
- Dashboard — Relay info, stats, and status overview
- Event browser — Browse and inspect stored events
- Pubkey management — View and manage known pubkeys
- Moderation — Ban/unban pubkeys and events
- Access control — Configure relay allow/deny lists
- Admin management — Add or remove relay administrators
- Relay-to-relay sync — Sync events between relays
- Settings — Relay configuration and schema management
Tech Stack
- SvelteKit + Svelte 5 with TypeScript
- DaisyUI 5 + Tailwind CSS 4
- applesauce libraries (accounts, core, loaders, relay, signers)
- nostr-tools
Getting Started
Prerequisites
- Node.js 22+ and pnpm (or use
nix developwith the included flake)
Install & Run
pnpm install
pnpm dev
Build
pnpm build
pnpm preview # preview the production build
Authentication
On the login screen, enter a relay URL and choose a signing method:
- Extension (NIP-07) — Browser extension like nos2x or Alby
- Bunker (NIP-46) — Remote signing via a bunker URL
- nsec — Direct private key entry (stored in memory only, never persisted)
API calls to the relay are authenticated with NIP-98 HTTP auth events.
Deployment
The app uses @sveltejs/adapter-node and ships a Dockerfile (Node 22, pnpm via corepack,
listens on :3000, non-root, healthcheck on /). NIP-86 calls are proxied through the
SvelteKit server route /api/relay-proxy to avoid CORS; they stay NIP-98 signed by the
browser signer, so the server holds no secret.
docker build -t relay-manager .
docker run -p 3000:3000 \
-e ORIGIN=https://relay-manager.example.org \
-e PUBLIC_DEFAULT_RELAYS=wss://relay-a.example.org,wss://relay-b.example.org \
relay-manager
| Variable | Purpose |
|---|---|
PORT / HOST |
adapter-node listen address (defaults 3000 / 0.0.0.0 in the image) |
ORIGIN |
Public origin the app is served from (adapter-node origin checks) |
PUBLIC_DEFAULT_RELAYS |
Optional comma-separated wss:// URLs offered on the login screen and seeded into the saved-relay list |
Pushes to main and v* tags build and publish git.edufeed.org/edufeed/relay-manager
via .forgejo/workflows/build.yml.
Development
pnpm dev # start dev server
pnpm build # production build
pnpm test # run unit tests (vitest)
pnpm test:e2e # run e2e tests (playwright)
pnpm check # svelte-check + type checking
pnpm format # format with prettier
pnpm lint # check formatting
Nix
A flake.nix is included for reproducible development environments with Node.js 22, pnpm, and Playwright:
nix develop
Related Projects
- amb-relay — Nostr relay for AMB educational metadata (kind 30142)
- calendar-relay — Nostr relay for NIP-52 calendar events
- standard-86-relay — Reference NIP-86 relay implementation