bd12d5ef72
Edits across all 13 EGGs to remove implementer guesswork. After this an
implementer can build a listener and speaker without reading our source.
README:
- Conventions section: hex casing rule (lowercase, 64 chars, no 0x),
NIP-01 foundations, `a`-tag form, created_at tie-break, JSON / time.
- Joining sequence: numbered end-to-end walkthrough from `kind:30312`
to first audio frame, referencing each EGG.
EGG-01 (room event):
- `relays` tag is one tag with multiple values (not multi-tag).
- `service` URL trailing-slash normalization.
- `private` status: gate is implementation-defined, not "render as open".
- `d`-tag charset locked to [A-Za-z0-9._-] so it interpolates safely
into the moq-auth namespace.
- Relay-discovery rule: publish to `relays` tag ∪ NIP-65 outbox.
- Tie-break on identical created_at via smallest event id.
EGG-02 (auth):
- JWT signing pinned: ES256 over P-256, JWKS at /.well-known/jwks.json,
5-minute relay cache.
- NIP-98 tags pinned: u / method / payload, base64 RFC 4648 standard
(not base64url).
- Error taxonomy: full HTTP status + `error` slug table for /auth, plus
WebTransport CONNECT 200/401/403/404 table.
EGG-03 (audio):
- Pin moq-lite Lite-03 to kixelated/moq-rs `rs/moq-lite/src/lite/`.
- One Opus packet per moq Frame (no container, no timestamp).
- Pubkey hex casing reaffirmed at the suffix / broadcast slots.
- AnnouncePlease prefix="" for speaker discovery.
- Mute = stop publishing (not silence frames, not Announce Ended).
- Mid-stream join: discard pre-skip per RFC 7845.
EGG-04 (presence):
- Heartbeat jitter ±5 s required (anti-thundering-herd).
- "0"/"1" are strings, not booleans.
- Single-room rule via replaceable-event semantics.
EGG-05 (chat): 8 KB suggested, 64 KB hard cap, 3 msg/s render rate.
EGG-06 (reactions): 30s window measured against created_at, drop-on-arrival
if already stale.
EGG-07 (moderation): replay protection — dedupe kicks by id within 120 s.
EGG-08 (scheduling): planned rooms MUST 403 at the auth sidecar.
EGG-10 (theming): bg image caps (1 MB / 4096 px soft, 8 MB / 8192 px hard).
Deferred (per review): EGG-00 (Conventions as a standalone spec), EGG-13
(capability advertisement), EGG-14 (discovery), test vectors corpus.
The "Conventions" section in README covers EGG-00's most urgent content
inline.
https://claude.ai/code/session_01RDpuki4t8StSg1CZcXnV5b
115 lines
4.2 KiB
Markdown
115 lines
4.2 KiB
Markdown
# EGG-10: Theming
|
|
|
|
`status: draft`
|
|
`requires: EGG-01`
|
|
`category: decorative`
|
|
|
|
## Summary
|
|
|
|
A host MAY skin their room with custom colors, font, and a background
|
|
image. Theme tags are added to the existing `kind:30312` event; clients
|
|
without theme support ignore them and render with their default theme.
|
|
|
|
This EGG is decorative: theming MUST NOT affect protocol semantics
|
|
(joining, audio, presence, chat). A non-themed renderer MUST NOT show
|
|
fewer features than a themed one.
|
|
|
|
## Wire format
|
|
|
|
Three optional tags on `kind:30312`:
|
|
|
|
```json
|
|
["c", "<hex color>", "background" | "text" | "primary"]
|
|
["f", "<font family>", "<optional font URL>"]
|
|
["bg", "<background image URL>", "cover" | "tile"]
|
|
```
|
|
|
|
### Color (`c`)
|
|
|
|
- The hex value is six hex digits (`#RRGGBB`); a leading `#` is OPTIONAL.
|
|
Three-digit shorthand (`#abc`) is NOT supported.
|
|
- The third element selects the role: `background`, `text`, or `primary`.
|
|
- A room MAY include up to one `c` tag per role. Extras MUST be ignored
|
|
by receivers (palette fallbacks are reserved for a future EGG).
|
|
|
|
### Font (`f`)
|
|
|
|
- The family name is a free-form string. Receivers SHOULD match the
|
|
four CSS-style generic names case-insensitively: `sans-serif`,
|
|
`serif`, `monospace`, `cursive`. Other names fall through to the
|
|
platform default unless the renderer also supports the URL.
|
|
- The URL element is OPTIONAL. When present, it MUST be a fully-qualified
|
|
HTTPS URL pointing at a single-style font file (TTF/OTF/WOFF2). HTTP
|
|
URLs MUST be rejected (mixed-content + integrity concerns).
|
|
|
|
### Background (`bg`)
|
|
|
|
- The URL is a fully-qualified HTTPS URL pointing at an image (PNG/JPEG/
|
|
WEBP).
|
|
- The mode is `cover` (scale to fill, crop overflow) or `tile` (repeat
|
|
on both axes). Unknown modes MUST fall back to `cover`.
|
|
- Hosts SHOULD keep the asset under 1 MB and 4096 px on its longest
|
|
edge. Receivers MUST cap any asset they fetch at 8 MB and 8192 px on
|
|
its longest edge; over-cap assets MUST be discarded with a fall-through
|
|
to the `background` color so a malicious host cannot OOM clients.
|
|
|
|
## Behavior
|
|
|
|
1. Theme tags are PARSED ONLY by clients with rendering support. Clients
|
|
without that support MUST ignore them silently.
|
|
2. Color values MUST be parsed strictly: `^#?[0-9a-fA-F]{6}$`. Anything
|
|
else MUST result in the role falling back to the platform default,
|
|
not in a render error.
|
|
3. The `text` color is the foreground for room name, summary, and chat
|
|
bodies. The `background` color paints behind everything except the
|
|
`bg` image (image overlays the color). The `primary` color drives
|
|
accent surfaces (active-speaker ring, send button).
|
|
4. Font URL fetching MUST be opt-in to the renderer's image / asset
|
|
pipeline (Tor or proxy if so configured). Renderers MUST cache the
|
|
fetched font on disk keyed by URL hash; the same URL MUST NOT be
|
|
re-fetched in the same session.
|
|
5. Background image fetching MUST go through the same channel as
|
|
inline images (typically the renderer's image cache).
|
|
6. Themed renderers MUST tolerate a TIME-OF-FETCH gap: the room screen
|
|
opens with platform defaults, font / background swap in once
|
|
loaded. There MUST be no flash-of-blank-screen.
|
|
7. A room theme MUST NOT alter element positions, sizes, or behavior.
|
|
This EGG controls colors, font family, and a background image — no
|
|
layout primitives.
|
|
|
|
## Example
|
|
|
|
```json
|
|
{
|
|
"kind": 30312,
|
|
"pubkey": "abc...host",
|
|
"tags": [
|
|
["d", "purple-room"],
|
|
["room", "Purple"],
|
|
["status", "open"],
|
|
["service", "..."],
|
|
["endpoint", "..."],
|
|
["p", "abc...host", "wss://relay", "host"],
|
|
["c", "#1a0033", "background"],
|
|
["c", "#FFFFFF", "text"],
|
|
["c", "#a020f0", "primary"],
|
|
["f", "Inter", "https://fonts.example/inter.woff2"],
|
|
["bg", "https://example.com/stars.png", "tile"]
|
|
],
|
|
"content": "",
|
|
"...": "..."
|
|
}
|
|
```
|
|
|
|
## Compatibility
|
|
|
|
A non-themed receiver renders the room without any of the cosmetic
|
|
overrides. A themed receiver that fails to fetch one of the assets
|
|
(font / background) MUST render the rest of the theme and the room is
|
|
still fully functional.
|
|
|
|
Future EGGs MAY introduce per-user profile themes (e.g. `kind:16767`)
|
|
and shared theme references (e.g. `kind:36767` Ditto themes). Those
|
|
specs MUST be additive: a theme defined on the room itself overrides
|
|
any per-user or shared theme.
|