Skip to content

The alt-backend (alt-backend/)

A ~220-line aiohttp app that implements just enough of /api/v1/ to run the Svelte frontend end-to-end. The POC's answer to "is the Litestar backend load-bearing?" — no, it isn't.

Why it exists

The Litestar backend is powerful, opinionated, and ~9k lines of Python. None of that is visible to the frontend, which only knows the /api/v1/ contract. To prove the contract is real rather than an accident of one implementation, there is a second backend in a different framework, with no database and no auth system, passing the same Playwright specs.

A host platform doesn't need Litestar, Dishka, or any of the reference stack — just the handful of endpoints the frontend calls.

Treat it as the contract's conformance test

It drifted once already: chat and the admin surface landed after it was written and nothing kept it in step, so make e2e-alt failed silently for four months. If a change to /api/v1/ breaks the alt-backend, the change is wrong — or the alt-backend needs updating in the same commit.

What it implements

Method Path Notes
GET /api/v1/config Static — reports auth: {local_password: false}
GET /api/v1/me Always 401 → frontend treats as guest
POST /api/v1/auth/login 404 (no login)
POST /api/v1/auth/logout 204
POST /api/v1/rooms/ephemeral Returns {event_id, slug, join_url}. No SFU call — rooms are implicit
GET /api/v1/events/by-slug/{slug} Resolves slug → event_id (from in-memory dict)
POST /api/v1/events/{event_id}/join Signs the Galene JWT itself — no SFU call
POST /api/v1/events/{event_id}/chat Posts a chat message
WS /api/v1/events/{event_id}/chat-ws Chat fanout to everyone in the room

What it deliberately doesn't do

  • Persistence — events live in a {event_id: slug} dict and chat is in-process. Restart loses everything.
  • Presence — no operator connection, so it never learns who is in a room. It doesn't need to.
  • Authentication/me is hard-coded to 401, /auth/login to 404. No sessions, no cookies.
  • Users, OIDC, admin — none of it.
  • Plugins, metrics, OpenAPI — the schema lives in the Litestar backend.
  • Scheduled events — ephemeral only.

If you need any of those, either stay on the Litestar backend or add them to alt-backend yourself. The point of alt-backend isn't to be production-capable; it's to be undeniably the contract.

Running

make run-alt               # SFU + alt-backend + front (interactive)
make e2e-alt               # Same stack + Playwright (one-shot)

e2e-alt runs only the guest specs: with no auth and no admin surface, the admin spec doesn't apply.

The SFU needs no changes and no knowledge of which backend is running. alt-backend signs tokens with GALENE_AUTH_KEY, whose dev default matches ops/galene/groups/meetings.json.

Point the browser at the proxy

SFU_WS_URL defaults to ws://localhost:5173/ws, the Vite proxy, so the WebSocket upgrade is same-origin. Aiming the browser straight at :8443 earns a 403 from Galene's CheckOrigin.

Stack

Web aiohttp
Tokens PyJWT
Package manager uv
Lines of code ~220

Trivia

Honcho assigns each process a $PORT environment variable by default, which confused the first run of alt-backend — the app read PORT and bound to 5100 instead of 8000. The fix was to rename the knob to BIND_PORT so honcho's $PORT doesn't steer it. Left as a breadcrumb for anyone writing a third backend.

Further reading