Skip to content

odio application

The odio application is a web app that lets you manage all your odio nodes from one place. Install it from your browser on your phone or desktop.

The application loads each node’s embedded web UI in an iframe. You get the full interface of each node, playback, audio routing, Bluetooth, services, power, all accessible from a single app.

  1. Open pwa.odio.love in your browser.
  2. Tap “Install” or “Add to Home Screen” when prompted.
  3. Add your nodes by hostname or IP.

Browser support. On mobile, installation works on Chrome, Edge, Safari, and Firefox. On some browsers like DuckDuckGo, the option is in the three-dot menu. On desktop, Chrome and Edge can install the app; Firefox and Safari desktop hit browser-level restrictions on LAN access.

A web app cannot perform mDNS/Zeroconf discovery — browsers don’t have access to UDP multicast. That’s why you need to add your nodes manually by hostname or IP.

On first launch, click + Add Instance and enter the host/IP, port (default 8018), and an optional label for your node. Add as many as you have, each card shows the node name, architecture, odio-api version, and connection status. Click Connect to open the node’s interface.

A CIDR-based subnet scanner is tracked in odio-pwa#12 as a workaround for the missing mDNS. Contributions welcome, a nice entry point for frontend devs who want to try Svelte.

Since v0.5.0, the active instance lives in the URL, so any node can be opened directly:

https://pwa.odio.love/#/i/<host>[/<port>][?label=<name>]

Port and label are optional. First-time visits stay transient and the app prompts to save on exit. Hash routing also means refresh and the back/forward buttons behave like any other web app.

odio also print the matching link in the SSH MOTD, so SSH’ing to a node gives you a one-click path to its UI in the PWA.

The application surfaces the situations described below directly in the UI so you don’t have to dig through devtools to know what’s wrong.

When the PWA detects Firefox or Safari desktop on an HTTPS context (the combinations that cannot reach LAN nodes at all), it shows a persistent banner pointing back at this guide and disables the + Add Instance button. There is nothing useful those browsers can do without switching browser or self-hosting over HTTP.

When a probe fails for an existing node, the card re-probes with mode: 'no-cors' to tell three failure modes apart:

Card messageColorWhat it means
Server unreachableredThe server is down, or the request was blocked at the network layer.
Server reachable: missing CORS headersamberThe request round-tripped but the response lacks Access-Control-Allow-Origin. Add the PWA’s origin to api.cors.origins.
Browser blocked (mixed content)amberBoth probes failed on an HTTPS PWA, so a browser-level mixed-content block is the most likely cause. Use Chrome 142+ with LNA granted, or self-host over HTTP.

The amber messages embed a link to the relevant docs section so you can jump straight from the card.

Since v0.5.0, clicking Connect on a node that doesn’t respond shows a dedicated Connecting, Server unreachable, or Browser blocked view instead of the native broken-iframe error. Deep links to a host you’ve never reached land on the same screen rather than the Server is shutting down overlay.

pwa.odio.love is the easiest path, but it’s not the only one. If your browser blocks mixed content, doesn’t support PWA install, or you only have one node, these alternatives may fit better.

If you only have one odio node, the PWA isn’t really needed. Bookmark the node’s embedded web UI directly, it’s the simplest option, especially on a browser that doesn’t allow PWA install.

Multiple nodes, no install: self-host over HTTP

Section titled “Multiple nodes, no install: self-host over HTTP”

If you have several nodes and don’t need the installable-app experience, self-host the PWA on your LAN over plain HTTP. No mixed-content restriction, no CORS setup, just bookmark the address and access it from any device on your network. See Self-hosting below.

Multiple nodes with install: self-host over HTTPS

Section titled “Multiple nodes with install: self-host over HTTPS”

To keep PWA install, self-host the PWA over HTTPS on a local address, for example with Traefik and Let’s Encrypt. The mixed-content situation is unchanged since the HTTPS PWA still calls HTTP nodes, so this setup still requires a Chromium-based browser (Chrome 142+ with LNA granted, or Edge). Add your self-hosted origin to api.cors.origins in each node’s config so the API accepts requests from your PWA, see CORS on each node below.

Self-hosting has always been possible by cloning and building the repo yourself. v0.3.4 makes it easier with an official Docker image and a ready-to-deploy static zip.

  • Docker (multi-arch, amd64 + arm64):

    Terminal window
    docker run -d -p 8080:80 --restart unless-stopped \
    --name odio-pwa ghcr.io/b0bbywan/odio-pwa:latest

    The image is based on nginx:alpine with SPA fallback and PWA-aware cache headers already configured.

  • Static zip — download odio-pwa-<version>.zip from the releases page and serve the extracted files from any web server. Make sure unrecognized paths fall back to /index.html, and set Cache-Control: no-cache on /index.html, /sw.js, and /registerSW.js.

If you serve the PWA over HTTPS, the API on each node must accept your origin. Add it to api.cors.origins in every node’s config. The list replaces the defaults, so include the hosted addresses too if you want to keep them reachable:

api:
cors:
origins:
- https://pwa.odio.love
- https://odio-pwa.vercel.app
- https://odio.yourdomain.com # your self-hosted origin

HTTP self-hosting on the LAN doesn’t require this, see Browser limits and alternatives above.

An arrow indicator appears next to the app version when a newer GitHub release is available, click it to open the release notes. To include prereleases (for testing RCs), run in the browser devtools console:

localStorage.setItem('odio-include-prereleases', 'true')