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 —
/meis hard-coded to 401,/auth/loginto 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¶
alt-backend/app.py— the whole thing- API contracts — full
/api/v1/reference - Reference backend (Litestar) — for comparison