Internal · SpaceMusic Engineering · Plan 042

The Host Becomes the Front Door

Today SpaceMusic launches as one program, with nothing in front of it. Plan 042 puts a launcher first — it signs you in, lets you pick an interface, then starts the core and that interface together.

Why a launcher, and why now

Starting SpaceMusic today is one move: you run an executable and it brings up the engine and the user interface together. Simple — but that single launch happens with no front door in front of it.

Nothing greets you, asks who you are, checks what your license allows, or lets you choose which interface you want before the whole thing boots. The first moment a user meets the product is also the moment nobody owns — there is no place to log in, set up streaming, or say what you're here to do. At a developer's own desk that's invisible. For a customer, a touring operator, or an unattended venue, it's the difference between a product and a tech demo.

Plan 041 already gave us a host window that supervises streaming and reaches the outside world. Plan 042 asks the obvious next question. If something is going to greet you and hold everything together, why not put it first — before the engine starts — so it can log you in and let you choose your interface? That reorders the whole startup. And most of what it needs already exists.

How startup works today

Today, starting SpaceMusic is a single move. You run one program, and it brings up the core — the engine that actually runs the show — and the user interface together, in one shot. One launch, and a moment later everything is on screen.

That's simple, and at a developer's desk it's fine. What it can't do is anything before that boot. There's no point where the product asks who you are, checks what your license allows, or sets up streaming. It just starts everything at once. We built a login and licensing system on the server, but the desktop never calls it — nothing in that one-shot launch is set up to.

One thing about that single program matters for what comes next. The interface and the core talk over one shared connection. We've shown that same connection works two ways: when the interface is on the same machine, and when it reaches the core across the internet. So the interface doesn't have to live inside the core. It can be a separate program that something else picks and starts. That's the opening the next section walks through.

The inversion

Plan 041's eventual end-state was phrased as "SM launches the host." Plan 042 turns that around: the host launches first, and the host launches the core. The launcher stops being a window that shows a viewer and becomes the shell that owns the whole product.

The reason is simple: you should check who someone is before the heavy part starts, not after. The launcher is the right place to ask the three questions nothing else can — who are you, what may you run, and what do you want to see — and to ask them before the engine boots. This would be a lot of work if we had to build a supervisor from scratch. We don't. The host already starts a child process, watches it, restarts it if it crashes, and kills it cleanly when the host exits. We're adding two more children to a pattern that already runs one.

The payoff is as much about experience as architecture. The host starts the engine and the chosen interface together, and only after you pick one. So you never watch an engine sitting on a blank scene, or an interface with nothing behind it. The first time, you see a sign-in. After that you're usually already signed in, so you get a welcome screen instead: pick up your last session, or choose another interface you're allowed to run. Pick one, and the core and that interface come up together, in the window you're already looking at.

What's already standing

This isn't a fresh start. Plan 041 already built — and we tested — most of the launcher's machinery. That's why 042 is mostly wiring, not a new product.

  1. One window, one launch — done. The host opens a window with the viewer and a status bar, and runs the texture streamer as a child. If the streamer crashes, the host restarts it. If the host is killed, the streamer is killed too — we tested it, and nothing is left holding the GPU.SpaceMusic.Host · StreamerProcess · ChildJob
  2. Local and LAN — done. Parameters and a live texture show up in the host window, and on a phone or iPad on the same wifi (scan a QR to connect). No cloud in the path.
  3. Cloud — done. One "Go WAN" button creates a cloud stream, gets the access tokens, and sends the texture out — no OBS. We watched it arrive on an iPad over the internet, end to end.Go WAN · WHIP → LiveKit
  4. The server lets a desktop in — done. The API used to bounce any non-browser request to a login page before it could even show a key. We fixed that, so the host can call the API directly. The login flow will use the same door.

So the parts 042 depends on are already running: process supervision, the status checks, the served viewer, encrypted storage for keys, and a working API client. The new work is the sign-in, the UI picker, and one rebuilt interface. The rest is connecting things that already work.

One launcher, three children, one wire

The load-bearing idea is small enough to say in a sentence: the host becomes a front door with three jobs — gate, pick, supervise — and everything downstream is a supervised child that binds to one shared wire.

Figure 1 · Host-first architecture Open full size · print A3 landscape ↗

api.spacemusic.tv Authentik SSO · license JWT · WAN tokens SpaceMusic Host the front door · one launch 1 · Sign in / license gate 2 · Pick a UI 3 · Spawn · supervise · status device-code / PKCE · license · tokens Core — exported .exe engine · params :8788 · Spout texture Texture streamer perf-037 · :8037 · WHIP→WAN spawned + supervised (Job Object — never orphaned) Selected UI a web app on the wire launched + supervised by host params · batch frames texture · H.264 transport-follows-origin — direct (:8788 / :8037) on localhost & LAN · relay (Centrifugo + LiveKit) off a *.spacemusic.tv domain

Read it top to bottom. The host reaches up to the cloud once, to ask who you are and what you may run. Then it reaches down to start the engine and the streamer — the two programs that produce the data — and it launches the UI that reads it. All three are supervised the same way the streamer already is: started, watched, restarted if they crash, and tied to the host so a hard kill never leaves something behind. The bottom line is the quiet part that does the heavy lifting: the UI is a web page that picks its connection from where it was served. So the same UI talks to the engine directly on a laptop, and through the cloud from a phone in another country — with no build flag and no second version.

How it actually runs

The architecture says what the parts are; the sequence says what happens when you double-click. It is deliberately boring, which is the point — a launcher earns trust by being predictable.

Figure 2 · The launch flow Open full size · print A3 landscape ↗

Start SpaceMusic Host opens sign in · or welcome back Pick a UI continue last · or choose Launch core + UI together · in this window Running status · Go WAN if licensed soft gate — signing in never blocks the show; a license only unlocks cloud (WAN · library · sync)

The gate is worth a close look. It follows a rule we've kept since plan 039: the internet is a bonus, never a requirement. The gate is soft. Sign in with a license and you unlock the cloud features — WAN streaming, the cloud library, settings sync. Skip it, or run with no internet, and you still get a full local core and a local UI. The license adds to the show; it never blocks it. That keeps an unattended venue running through an internet outage — exactly when a login screen would be a disaster.

Three things keep the rest cheap. First, the core is a normal .exe, so launching it is the same supervised start the host already does for the streamer — no engine to find, no patch arguments. Second, the sign-in is a thin client over a backend we already built: type a one-time code from the portal, or sign in through the browser, and get back a license token the host stores and can read offline. Third, the host waits until the engine is ready before it shows the interface, so the window never opens onto an empty scene. The two arrive together.

There's one real gap, and the plan tackles it early. Today the connection is one-way: the engine talks, the web viewer listens. That's fine for a viewer. But a control UI — the rebuilt Pro interface, a scene browser — needs to send changes back, and there's no return path on the web side yet. So before we build any Svelte control UI, we build that return path once, in one place. Everything interesting stands on it.

The edges we're choosing to walk into

A plan that only lists its wins is selling something. Here are the corners we know about.

The Svelte Pro UI is the long pole. We chose to rebuild the Pro interface from scratch in Svelte, rather than ship the Avalonia version that already runs in a browser and already reads and writes over the relay. That's a real head start we're giving up, for a lighter, web-native result. It's a deliberate choice. The way we cover it is order: the earlier phases all deliver something usable without waiting on this one, and the return channel it needs gets built early anyway.

The engine has no clean "ready" signal in development. Run from source, it compiles on load, which can take tens of seconds. We can tell when its connection opens, but that only means "it started," not "it finished loading." A generous timeout and an honest "starting…" message cover it. The shipped .exe is much faster, so this is a development-only wrinkle.

The cached license can be edited. The host trusts the offline token without checking its signature, so a determined user could extend their own license until the next online check catches it. We accept this. It's the normal trade for working offline, and it's not the kind of user a soft gate is trying to stop.

One server bug to fix first. A few license endpoints look up "the user's license" without saying which app, and there's now a second app in the same database. We fix that on the server before the host relies on it.

The full rollout is below, phase by phase. The short version: phase 1 stands on its own and gives us parameters and texture over the internet right away.

Why this matters

"A product an operator can run is not the same as a pile of processes an engineer can start."

Today, starting SpaceMusic is easy but bare — it just runs. No sign-in, no choice of interface, no setup before it boots. Plan 042 turns that into one thing you launch that knows who you are, lets you choose what you want to see, and brings up the rest in the right order, restarting anything that falls over. That's the difference between software we can demo and software we can hand to a venue technician, a touring operator, or a customer.

The reason to do it now is that the expensive parts are already paid for. The host is already a supervisor. The core is already an .exe we can launch. The login and license system is built and waiting for the desktop to call it. The connection every UI uses already works the same on a laptop and over the internet. So 042 is mostly connecting things that exist, plus one new interface — and the soft gate keeps it true to our rule that the show runs with or without the internet. Skip it, and every install stays a hand-wired routine, the Go-WAN button stays the only part of the product that knows the cloud exists, and the launcher we keep almost-building stays a viewer that wants to be more.

The plan, phase by phase

Seven phases. Each one is something you can run on its own, so we don't have to finish everything before any of it is useful. Sizes are relative, smallest to largest — no calendars.

  1. Deploy the viewer we already have. Put the existing web viewer on a public address, so the WAN share link shows parameters and texture. No new code — just hosting.size: small · depends on nothing else
  2. Launch the core as a child. Teach the host to start and watch the core .exe, the same way it already runs the streamer. Wait for the engine to be ready before showing a UI.size: small · reuses the streamer pattern
  3. Add the return channel. Give the one-way connection a way back, so a web UI can send changes to the engine. Every control UI needs this, so it comes early.size: medium · the foundation for control UIs
  4. Sign-in and license (the soft gate). The desktop side of logging in: a one-time code or a browser sign-in, a cached license, and a way to manage your devices. Unlocks cloud features; never blocks local launch.size: medium · new code, backend already built
  5. The UI picker. A small list of available interfaces the host reads, and the logic to launch the one you pick alongside the core. Ship the existing viewer as the first option.size: medium
  6. Rebuild the Pro UI in Svelte. The full control interface as a web app on the wire, using the return channel from phase 3. This is the big one.size: large · the long pole
  7. Later. Let UIs discover which textures exist instead of being handed the name; more interfaces, like a scene browser; a sign-in that finds live sessions on the LAN and over the internet.size: large · ongoing

Phase 1 is the quick win and waits on nothing. We can do it first and have parameters and texture over the internet — in the viewer we already trust — right away.

Glossary

Terms and proper nouns used above, in plain language.

Core
The SpaceMusic engine — the exported .exe of the vvvv patch that produces the parameters and the texture. "Launch the core" means start that process.
Host
The launcher window (a Windows WinForms + WebView2 app, plan 041). In 042 it becomes the front door that gates, picks a UI, and supervises the children.
The wire
The shared data contract every UI binds to: a stream of parameter batch frames plus a named texture channel.
Batch frame
The parameter message format — a snapshot on connect, then per-frame deltas — broadcast by the engine and forwarded to the cloud unchanged.
transport-follows-origin
A UI served from localhost/LAN talks direct (sockets); served from a *.spacemusic.tv domain it auto-switches to relay (cloud). Same UI, no build flag. (Plan 039.)
Relay
The cloud message bus (Centrifugo) that carries parameters to remote viewers over WAN.
LiveKit / WHIP
The cloud video path: WHIP is how the streamer publishes a texture to LiveKit, which fans it out to remote browsers.
Spout
The Windows GPU-texture-sharing mechanism the engine uses to hand a texture to the streamer with no copy.
Soft gate
Sign-in / license is offered but never blocks launch; it only unlocks cloud features. The core always runs locally.
Device code
A short SM-XXXX code generated on the my.spacemusic.tv portal and typed into the desktop to link it to your account — no browser round-trip on the desktop.
PKCE
The browser sign-in flow for desktop apps; the host catches the redirect on a loopback port and exchanges it for a token.
License JWT
The signed token the server returns describing your plan, features, and device — cached on disk so the host can authorize you offline.
IChannelProvider
The C# abstraction the Avalonia UI binds through; it already swaps between an in-process connection and the cloud relay with no UI change — the proof the wire is consumer-agnostic.
perf-036 / perf-037
The web viewer (036, the parameter+texture monitor) and the texture streamer (037, Spout→encode→serve/WHIP).
Pro UI
The full control interface (CSV-driven parameter pages), today an Avalonia app, to be rebuilt as a Svelte web app on the wire.

Settled

The shape is decided

Host-first launch, core as a supervised .exe, a soft license gate, and out-of-process web UIs on one wire. The host is already the supervisor we need.

Next

Deploy, then connect

Phase 1 hosts the existing viewer at viewer.spacemusic.tv (no code). Then CoreProcess and the param write-back channel that every control UI needs.

Later

The picker and the rebuild

A UI manifest the launcher reads, the Svelte Pro rebuild, texture discovery, and a sign-in that finds live LAN + WAN sessions.

Figure 1 · The Host Becomes the Front Door · designed for A3 landscape print ← back to the document

Figure 1 · Host-first architecture

api.spacemusic.tv Authentik SSO · license JWT · WAN tokens SpaceMusic Host the front door · one launch 1 · Sign in / license gate 2 · Pick a UI 3 · Spawn · supervise · status device-code / PKCE · license · tokens Core — exported .exe engine · params :8788 · Spout texture Texture streamer perf-037 · :8037 · WHIP→WAN spawned + supervised (Job Object — never orphaned) Selected UI a web app on the wire launched + supervised by host params · batch frames texture · H.264 transport-follows-origin — direct (:8788 / :8037) on localhost & LAN · relay (Centrifugo + LiveKit) off a *.spacemusic.tv domain
Figure 2 · The Host Becomes the Front Door · designed for A3 landscape print ← back to the document

Figure 2 · The launch flow

Start SpaceMusic Host opens sign in · or welcome back Pick a UI continue last · or choose Launch core + UI together · in this window Running status · Go WAN if licensed soft gate — signing in never blocks the show; a license only unlocks cloud (WAN · library · sync)