Build a PWA, deploy it on Nostr, and it's live on your own domain. Then do it again. npanel serves every app your team ships, from one box you own.
npanel · deploy log
The dashboard
Add a site the way you'd add a DNS record: a hostname, and the nsite it points at. Your whole team logs in with Nostr keys, and each person sees only the sites they've been given.

Ditto
ditto.pub
18.6k
visitors, 24h
Armada
armada.buzz
7.2k
visitors, 24h

Shakespeare
shakespeare.diy
11.4k
visitors, 24h
Agora
agora.spot
3.9k
visitors, 24h
NostrHub
nostrhub.io
2.1k
visitors, 24h
Add site
Serve an nsite on a domain you point at this server.
npub, naddr, nprofile, or an nsite URL
Certificate issued on first visit
www redirects to the bare domain
Sitemap and robots.txt generated
Built in
Plausible-style analytics for every site, collected by npanel itself from the site's own origin. No cookie banner, no third-party script, no account somewhere else.
Built in
A few kilobytes of reporter on every page, and stack traces mapped through the source maps you already deployed. It speaks Sentry's format, so an existing Sentry SDK can report to it too.
Built in
npanel runs Arti, the Tor Project's own Rust implementation, inside its process. Turn it on and every site you serve is also an onion service, and Tor Browser offers it to visitors on its own.
Rust + Hyper
npanel looks up every path in SQLite, negotiates the encoding, and adds security and canonical headers to every response. It still serves more requests per second than nginx.
Requests per second serving the same nsite's index.html (gzip, 8.5 KB), byte for byte. oha, 64 connections, HTTP/1.1 keep-alive, median of three 10 s rounds. Each server pinned to the same 2 cores of a Ryzen 7 5850U. nginx with 4 workers, sendfile and gzip_static. Caddy 2.11.7 with precompressed.
Deploy
Publish a folder as an nsite and your npanel takes it from there: it sees the signed manifest on the relays, downloads every file, and puts the app on your domain.
❯
Install
Relays, Blossom servers and everything else are set in the dashboard, take effect without a restart, and land in the audit log.
DASHBOARD_HOST="panel.example.com" # serves the dashboard
HTTPS_PORT="443" # or leave unset, behind Caddy
PORT="80"
BIND_ADDRESS="0.0.0.0"
TLS_CHECK_PORT="3001"
DATA_DIR="./data" # SQLite + blobs
LOG_LEVEL="info"
❯ cp .env.example .env && $EDITOR .env
❯ docker compose up -d
✔ Container npanel-npanel-1 Started
✔ Container npanel-caddy-1 Started
❯ docker compose exec npanel npanel make-admin npub1…
Static x86_64 and aarch64 Linux binaries, published and signed over Nostr with ngit. Point DNS at the box, open your dashboard host, and log in with your Nostr key.
FAQ
An nsite is a static website published on Nostr (NIP-5A). The files are stored on Blossom servers by their SHA-256 hash, and a signed Nostr event maps each path to a hash. Whoever holds the key controls the site, and any gateway can serve it.