index ↓
settings pages
typing a url or picking from many entities on the car screen is painful. a settings page moves that to the phone. it is one self-contained html file in your bundle. the companion app renders it in a webview.
s1 - declare it
point manifest.json at the built file. it must be a single self-contained html file, all js and css inlined.
the cap is 1 MiB at install. keep it lean.
{
"id": "…",
"name": "My App",
"version": "0.1.0",
"settings": "settings.html"
} bun create bridgething scaffolds all of this: a preact page under settings/, a
single-file vite build with size warnings at 200 KiB, and the manifest entry.
// package.json: the scaffold ships this wiring
"build": "vite build && vite build -c vite.settings.config.ts" s2 - talk to the companion
inside the page, import @bridgething/client/settings. it is a tiny bridge sdk. it reads and writes
your app's declared config and writes the doc namespace: shared per-app
key/value state.
import { settings } from '@bridgething/client/settings';
const { webappId, name } = await settings.context();
// the user's saved config values (and the manifest schema, for rendering a form)
const fields = await settings.config.fields();
const values = await settings.config.list();
await settings.config.set('base_url', url);
// the shared doc namespace: what your phone-side page authors, your
// on-device webapp reads
await settings.doc.set('selected_entities', ids.join(','));
const off = settings.onDocChanged((key, value) => sync(key, value));
settings.done(); // closes the sheet on the device side, your webapp reads the same doc namespace over the normal client:
// on-device webapp: adopt what the settings page authored, live
const saved = await client.doc.get({ key: 'selected_entities' });
client.doc.onChanged(c => applySelection(c.value)); s3 - network: use websocket apis or permissive origins
the page runs on the phone, so it has real internet. but it loads from a file:// origin, and the webview
enforces cors on fetch/xhr from that origin. in practice:
- websocket apis work. the ws handshake is not cors-gated.
- plain http apis work only if the server sends permissive cors headers
(your requests arrive with
Origin: nullor*). most public apis are fine.
rule of thumb: if the service has a websocket api, use it from the settings page. if it's http-only and
cors-strict, do the fetching in your on-device webapp via client.net, which tunnels through the phone
and is not origin-restricted.
s4 - a worked example
the home assistant example app ships a settings page. it dials your ha server over its websocket api. it lists every entity, grouped and searchable. it saves your selection as a doc the device app applies live. the entity picker never renders on the car screen.