Wire-protocol specs for nostrnests-style audio rooms, in the style of Nostr NIPs and Blossom BUDs. Each spec documents one self-contained capability that a client or relay can implement; two compliant peers implementing the same set of EGGs round-trip without further coordination. Layout: README.md cover, status table, conformance levels EGG-01.md Room event (kind:30312) required EGG-02.md Auth + WebTransport handshake required EGG-03.md Audio plane (moq-lite) required EGG-04.md Presence (kind:10312) required EGG-05.md In-room chat (kind:1311) optional EGG-06.md Reactions (kind:7) optional EGG-07.md Roles & moderation (kind:4312) optional EGG-08.md Scheduling (status=planned) optional EGG-09.md User server list (kind:10112) optional EGG-10.md Theming (c/f/bg tags) decorative EGG-11.md Recording decorative EGG-12.md Catalog track (catalog.json) optional Conformance levels (Listener / Speaker / Host) defined in the README so a deployment can declare "we implement EGG-01..EGG-04" and other peers know exactly what to expect. Each spec follows the same shape (Summary / Wire format / Behavior numbered MUST/SHOULD/MAY rules / Example / Compatibility) and fits on a single printed page. Wire formats are documented exactly as nostrnests + amethyst implement them on this branch — no hypothetical capabilities, no "future" tags without an EGG number.
3.1 KiB
EGG-06: Reactions (kind:7)
status: draft
requires: EGG-01
category: optional
Summary
Audience-side ephemeral feedback (👏 ❤️ 🎉 ...) is carried on standard
NIP-25 kind:7 reaction events, scoped to the room via an a-tag.
Clients render these as a short-lived floating overlay over the
participant grid.
A reaction is NOT durable state. Clients SHOULD NOT page through historical reactions; only the recent window matters.
Wire format
{
"kind": 7,
"pubkey": "<reactor pubkey hex>",
"tags": [
["a", "30312:<host pubkey hex>:<room d>", "<relay hint>"],
["p", "<target pubkey hex>"]?,
["emoji", "<shortcode>", "<image url>"]?
],
"content": "<emoji glyph or :shortcode:>",
...
}
content carries the reaction itself. Standard Unicode emoji glyphs are
used directly. Custom emoji follow NIP-30: content = ":shortcode:" with
a sibling ["emoji", shortcode, url] tag.
A reaction MAY include a ["p", target] tag scoping the reaction to a
specific speaker (renders over their avatar). With no p tag, the reaction
is room-wide (renders centered on the room canvas).
Behavior
- Reactors MUST emit
kind:7events with at least onea-tag matching EGG-01 and a non-emptycontentfield. - Receivers MUST apply a 30-second sliding window: a reaction is rendered
from the moment it is observed until 30 seconds after its
created_at, then dropped from the floating overlay. - Receivers SHOULD throttle their reaction-overlay updates to at most 4 Hz (250 ms minimum between repaints). At ~30 reactions per second a naive recomposition can starve the audio decoder.
- Receivers MUST tolerate unknown
contentvalues (e.g. a Unicode glyph without a font fallback) by falling back to a generic indicator rather than dropping the reaction. - Receivers MUST NOT auto-fetch the
["emoji", _, url]image at the moment of receipt — that opens an animated-emoji-driven DDoS vector. Image fetch SHOULD be batched and rate-limited. - A reactor MAY include the same
a-tagged reaction more than once (e.g. spamming claps). Receivers MUST NOT de-duplicate by content alone; events with different ids are always distinct.
Example
A clap reaction targeted at a speaker:
{
"kind": 7,
"pubkey": "ghi...audience",
"created_at": 1714003220,
"tags": [
["a", "30312:abchost:office-hours-2026-04"],
["p", "def...co"]
],
"content": "👏",
"id": "...",
"sig": "..."
}
A custom-emoji reaction (NIP-30):
{
"kind": 7,
"pubkey": "ghi...audience",
"created_at": 1714003221,
"tags": [
["a", "30312:abchost:office-hours-2026-04"],
["emoji", "amethyst", "https://example/amethyst.png"]
],
"content": ":amethyst:",
"id": "...",
"sig": "..."
}
Compatibility
EGG-06 is independent from EGG-05 (chat). A peer MAY implement either, both, or neither without affecting interop on EGG-01 through EGG-04.
Future EGGs MAY introduce paid reactions (kind:9735 zap receipts at the
same a-tag). Implementers SHOULD be prepared to source the reaction
overlay from both kind:7 and kind:9735 streams.