The Edition I capsule has four components per the [drop-house charter][1]: essay, object, software, audio. The essay shipped 05-15 as [The Sonos S2 Touchscreen Monoculture][2]. The audio shipped 05-15 as The Phonograph as Object Lesson. The object brief is in /objects/the-phonograph. The software component shipped today.
[1]: /codex/methods/stax-editions-drop-house-charter [2]: /journal/sonos-s2-touchscreen-monoculture
2026-05-15 — the music client, end to end
Architecture decision: PWA, not native
The Sonos S2 essay names the failure modes to avoid: cloud-account auth for local LAN control, multi-tap pause workflows, queue context that disappears under now-playing, hidden multi-room grouping, login modals and welcome wizards on every fresh device. A native iOS app would require an Apple Developer account ($99/yr), provisioning profiles, TestFlight gates, App Store review. A native Android app adds a Play Console fee and a separate codebase. A native macOS app adds a third.
A Progressive Web App eliminates the entire distribution lane: one HTML/CSS/JS surface, served by the existing AETHER Phoenix endpoint on the lab, installable on iOS Safari, Android Chrome, macOS Safari/Chrome, Linux Chromium, Windows Edge via each browser's "Add to Home Screen." No App Store. No Developer account. No SDK lock-in.
The PWA installs into the OS like a native app — its own icon, its own window chrome, lock-screen media controls via the MediaSession W3C standard, full-screen launch — but the codebase is the same web substrate the LiveView already serves.
What landed
lib/aether_web/live/music_live.ex(~340 LOC) — new LiveView at
/music, additive to the existing dashboard at /. Subscribes to the same "zones" PubSub topic; reuses the same Aether.Zone GenServers. The dashboard is the lab control plane; /music is the consumer-facing surface.
priv/static/manifest.json— PWA manifest,display: standalone,
charcoal-on-paper theme color from the stax.css palette.
priv/static/service-worker.js— cache-first for the app shell,
network-first for the LiveView mount points, offline fallback page.
priv/static/offline.html— typographic offline page (the LAN is
required; an "offline" PWA shell with no LAN is honest about it).
priv/static/icons/music-{192,512}.png— generated synthetically
via ImageMagick + Adwaita Sans Bold (no design asset roundtrip).
assets/js/app.js— addedMediaSessionLiveView hook (exposes
pushEvent to inline <script> for navigator.mediaSession action handlers), service-worker registration.
lib/aether_web/components/layouts/root.html.heex—<link rel="manifest">,
apple-touch-icon, apple-mobile-web-app-capable, theme-color.
lib/aether_web.ex—static_pathsextended to expose
manifest.json, service-worker.js, icons/, offline.html.
<internal-lab>/sonos-cli/sonos.py— addednext_track,previous_track,
group_zone, ungroup_zone, get_zone_uuid (with a corrected topology-parser regex that survives URL slashes in attribute values — a latent bug in the original parser that surfaced now that group/ungroup actually needs the topology output).
<internal-lab>/sonos-cli/sonos_bridge.py—handle_command()dispatches
the four new ops: next, previous, group, ungroup. Bridge daemon restarted cleanly.
The aesthetic — anti-skeuomorphism
Single-column on phone (rooms strip + now-playing card + queue panel). Three-column on tablet/desktop (rooms left, now-playing center, queue + group controls right). The palette is the stax.css variables — --bg: #fdfdfb, --text: #222, --accent: #880000, Charter for the now-playing title, Inter for controls, JetBrains Mono for transport state. No gradient backgrounds, no glossy buttons, no rounded corners on every element, no skeuomorphic vinyl-record animations. Restrained typographic UI — the visual inverse of the Sonos S2 redesign the essay critiques.
MediaSession — lock-screen + Bluetooth headphone controls
navigator.mediaSession.setActionHandler is the W3C standard mobile-OS hook. When the PWA is the active audio context the phone's lock screen, the iOS/Android control center, and any Bluetooth headphone's track-skip button all route through these handlers. The hook calls pushEvent on the LiveView, which casts to the matching Aether.Zone GenServer, which publishes a cmd to lab.sonos.zone.<name>.cmd, which the bridge daemon translates to UPnP SOAP. Round-trip is the same as a button tap on the page.
Distribution
localhost:4000/music— direct LAN.- Tailnet (private) — accessed from anywhere via the lab's
Tailscale node URL.
- Tailscale Funnel (later) —
music.taild0f386.ts.netwith
auto-issued TLS, for invited guests without LAN access. Deferred to next session — the install path doesn't require it for v0.1 since household devices are all on the LAN.
End-to-end verification
# AETHER restarts cleanly with the new route
curl -sI http://localhost:4000/music | head -2
# HTTP/1.1 200 OK
# Manifest, service-worker, icons all served
curl -sI http://localhost:4000/manifest.json | head -1 # 200
curl -sI http://localhost:4000/service-worker.js | head -1 # 200
curl -sI http://localhost:4000/icons/music-192.png | head -1 # 200
# New bridge ops flow through the bus
nats pub lab.sonos.zone.gym.cmd '{"op":"next","ts":...}'
# → bridge: cmd: gym next → ok
# → audit: {"zone":"gym","op":"next","status":"ok"}
nats pub lab.sonos.zone.pool.cmd '{"op":"group","coordinator":"gym","ts":...}'
# → bridge: cmd: pool group → ok
# → audit: {"zone":"pool","op":"group","coordinator_ip":"192.168.0.149","status":"ok"}
License
AGPL-3.0 throughout. Zero third-party SDKs. Zero analytics. Zero telemetry. The MediaSession API is a W3C standard, not a platform API, so even that single platform-touching surface is portable.
Cross-references
- The Sonos S2 monoculture essay is the editorial component this
software instantiates.
- The Phonograph object brief is the hardware sibling — the PWA is
the screen surface that pairs with the eventual physical artifact.
- AETHER is the substrate —
Aether.ZoneGenServers, the NATS bus,
the LiveView socket. The music client composes-with AETHER, not replaces it.