Decentralized audio rooms on Nostr, powered by MoQ (Media over QUIC) for real-time audio transport.
Nests has two parts:
- Frontend — A React SPA that handles rooms, chat, reactions, theming, and all Nostr interactions directly from the browser
- Audio Server — A MoQ relay + auth sidecar that handles real-time audio transport via WebTransport/QUIC
The frontend is fully static. All Nostr data (rooms, chat, presence, reactions) flows through public Nostr relays. The only backend you run is the MoQ audio server.
# 1. Generate self-signed TLS certs (required for WebTransport)
./dev-config/generate-certs.sh
# 2. Start MoQ relay + auth
docker compose -f docker-compose-moq.yml up -d
# 3. Start the frontend dev server
cd NestsUI-v2
npm install
VITE_MOQ_CERT_FINGERPRINT=$(cat ../dev-config/certs/fingerprint.b64) npm run devOpen http://localhost:8080 in your browser.
Use docker-compose.yml to run everything:
# 1. Clone the MoQ relay (built from source)
git clone https://github.com/moq-dev/moq.git
# 2. Configure your domains
cp .env.example .env
# Edit .env:
# MOQ_RELAY_DOMAIN=moq.yourdomain.com
# MOQ_AUTH_DOMAIN=moq-auth.yourdomain.com
# 3. Get TLS certs for the MoQ relay (WebTransport requires valid TLS)
certbot certonly --webroot -w /var/www/certbot -d moq.yourdomain.com
ln -s /etc/letsencrypt/live/moq.yourdomain.com ./certs
# 4. Start all services
docker compose up -dThis starts:
| Service | Port | Description |
|---|---|---|
nests-web |
8080 | Frontend (nginx serving the Vite build) |
moq-relay |
4443 (TCP+UDP) | MoQ audio relay (WebTransport/QUIC) |
moq-auth |
8090 | NIP-98 auth sidecar (issues JWTs) |
Put a reverse proxy (Caddy/nginx) in front for the frontend and auth. The MoQ relay handles its own TLS on port 443 — do not proxy it.
# Caddy example
nests.yourdomain.com {
reverse_proxy nests-web:80
}
moq-auth.yourdomain.com {
reverse_proxy moq-auth:8080
}
# moq.yourdomain.com:4443 — no proxy, relay handles its own TLS
Firewall: Open TCP + UDP on port 4443 for the MoQ relay subdomain.
DNS: Point all three subdomains to your server.
Anyone can run their own MoQ audio server. No frontend required — Nests clients can connect to any relay.
# 1. Clone the MoQ relay
git clone https://github.com/moq-dev/moq.git
# 2. Get TLS certs
certbot certonly --webroot -w /var/www/certbot -d moq.yourdomain.com
ln -s /etc/letsencrypt/live/moq.yourdomain.com ./certs
# 3. Start the relay
docker compose -f docker-compose-moq.yml up moq-relay moq-auth -dThen add https://moq.yourdomain.com:4443 as an audio server in any Nests client under Settings > Audio.
Users can also publish their preferred audio servers to Nostr as a kind:10112 server list, so their rooms automatically use their own relay.
| Variable | Default | Description |
|---|---|---|
VITE_MOQ_RELAY_URL |
https://moq.nostrnests.com |
MoQ relay URL (build-time) |
VITE_MOQ_AUTH_URL |
https://moq-auth.nostrnests.com |
Auth service URL (build-time) |
VITE_MOQ_CERT_FINGERPRINT |
— | Dev only: self-signed cert fingerprint |
MOQ_RELAY_PORT |
4443 |
MoQ relay port |
MOQ_AUTH_PORT |
8090 |
Auth service port |
Based on NIP-53 for live activities.
{
"kind": 30312,
"tags": [
["d", "<unique identifier>"],
["title", "<room name>"],
["summary", "<description>"],
["image", "<preview image url>"],
["status", "<live, planned, ended>"],
["starts", "<unix timestamp>"],
["streaming", "<moq relay url>"],
["auth", "<moq auth url>"],
["color", "<banner gradient class>"],
["relays", "wss://relay1.com", "wss://relay2.com"],
["p", "<pubkey>", "<relay>", "<role>"],
["c", "#hexcolor", "background"],
["c", "#hexcolor", "text"],
["c", "#hexcolor", "primary"]
],
"content": ""
}Participant roles in p tags: host, admin, speaker.
Room theming uses inline c tags (Ditto theme colors) or an a tag referencing a kind:36767 theme.
Same as NIP-53. Messages reference the room via a tag.
{
"kind": 1311,
"tags": [
["a", "30312:<pubkey>:<d-tag>"]
],
"content": "Hello from Nests!"
}Replaceable event signaling a user's presence in a room.
{
"kind": 10312,
"tags": [
["a", "<room-a-tag>"],
["hand", "1"],
["publishing", "1"],
["muted", "0"],
["onstage", "1"]
]
}Clients publish presence every 2 minutes as a heartbeat. Presence can only be indicated in one room at a time (replaceable event).
Users publish their preferred MoQ relay servers.
{
"kind": 10112,
"tags": [
["server", "https://moq.example.com:4443"],
["server", "https://moq2.example.com:4443"]
]
}Nests supports Ditto profile themes and room themes:
- kind:16767 — User's active profile theme (colors, font, background)
- kind:36767 — Shareable theme definitions
Avatar shapes use the shape field in kind:0 metadata (an emoji rendered as a CSS mask).
MIT