Week of 2026-05-15 — Edition I software component: multi-room music client (PWA)

Started 2026-05-15 · active · SMC17/aether

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

/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.

charcoal-on-paper theme color from the stax.css palette.

network-first for the LiveView mount points, offline fallback page.

required; an "offline" PWA shell with no LAN is honest about it).

via ImageMagick + Adwaita Sans Bold (no design asset roundtrip).

pushEvent to inline <script> for navigator.mediaSession action handlers), service-worker registration.

apple-touch-icon, apple-mobile-web-app-capable, theme-color.

manifest.json, service-worker.js, icons/, offline.html.

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).

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

Tailscale node URL.

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

software instantiates.

the screen surface that pairs with the eventual physical artifact.

the LiveView socket. The music client composes-with AETHER, not replaces it.