The spannora hub

The hub is a standalone PWA at spannora.dev/app/ that lets you manage multiple spannora installs from one interface. Each install runs on its own VM with its own auth; the hub is a thin client that knows how to talk to all of them.

You can use the public hub or self-host your own copy — they’re functionally identical. The hub has no backend state of its own.

When you’d use the hub

If you only have one spannora, the per-server PWA at https://<your-vm>/ works fine and you don’t need the hub.

Per-install setup (CORS opt-in)

The hub talks to your spannora across origins, so each install you want to manage needs to allow the hub’s origin. On the VM:

SPANNORA_ALLOWED_ORIGINS=https://spannora.dev systemctl restart spannora

Or edit /etc/systemd/system/spannora.service to add:

Environment="SPANNORA_ALLOWED_ORIGINS=https://spannora.dev"

Then systemctl daemon-reload && systemctl restart spannora.

Without this, the browser will refuse cross-origin requests and the hub will show a CORS error.

Adding an instance to the hub

Open spannora.dev/app/ and tap the + button on the left rail. Enter:

The hub posts to /api/auth/token on the target install, gets back a long-lived bearer token, and stores { id, base_url, label, color, token } in IndexedDB (spannora-hub DB, version 1).

What lives where

SurfaceWhere
Instance config (URL, label, token)Hub’s IndexedDB, per-origin
Conversations and messagesEach spannora’s SQLite, per-VM
Claude session stateEach VM’s ~/.claude/
Bearer-token rowsEach spannora’s sessions table, kind='token'

The hub has zero server-side state. Switching browsers = re-add instances. Sync across devices is on you (export/import is a planned feature).

Removing an instance

Right-click (or long-press) an instance chip in the rail. Remove only forgets the instance locally — the bearer token on the server is not revoked. To kill the token, log into the spannora install directly (same-origin) and revoke the matching session from the account modal.

Mixed content

The hub is served over HTTPS. If you try to add an HTTP spannora install, the hub will refuse before making any network request. There’s no workaround — browsers actively block mixed content. If you need to test against a plain-HTTP install, run the hub locally with npm run dev -w packages/hub (which serves over HTTP).

Self-hosting the hub

The hub is just static files. Clone the repo, copy packages/hub/ to any static host (with the packages/hub/shared symlink dereferenced), and you have your own private hub.

git clone https://github.com/gididaf/spannora
cd spannora
cp -rL packages/hub /var/www/spannora-hub

The manifest uses relative ./ paths so the hub works at any base path.

Mobile install

On iOS / Android, open spannora.dev/app/ in the system browser (Safari on iOS, Chrome on Android) and tap “Add to Home Screen.” The PWA installs with the identity spannora-hub and runs in standalone mode. Same UI as the desktop browser, with safe-area padding for the iOS notch and Android nav buttons.


Next: Security model →