index ↓

publishing apps

the app catalog is federated. the official apps.bridgething.com is the default.

a source is a url

publish a catalog.v1 document anywhere that serves it over https and it is a source. users add it by url.

{
  "schema": "catalog.v1",
  "updated_at": "2026-07-24T00:00:00Z",
  "repo": {
    "name": "my apps",
    "description": "webapps I publish for bridgething.",
    "homepage": "https://example.com",
    "icon": "https://example.com/icon.svg"
  },
  "apps": [ /* AppEntry… */ ],
  "recommended_sources": []
}

app entries

id is a uuidv7 and is the app's real identity: it keys upgrade-in-place and the device key-value namespace, so it must stay stable across versions and must not collide with another app. generate one once and keep it.

{
  "id": "019e6701-13f8-71b5-ba04-85d326630e98",
  "name": "Calendar",
  "description": "Upcoming events from an iCalendar feed.",
  "author": "you",
  "icon": "https://example.com/icons/calendar.svg",
  "homepage": "https://example.com",
  "source": "https://github.com/you/calendar",
  "versions": [
    {
      "version": "0.1.0",
      "released_at": "2026-07-24T00:00:00Z",
      "download": {
        "url": "https://example.com/r/<id>/0.1.0.zip",
        "size": 402118,
        "sha256": "…"
      },
      "permissions": ["net.fetch"],
      "role": "launcher",
      "provides_overlay": true,
      "min_libbridgething_version": "0.5.0",
      "changelog": "Initial release."
    }
  ]
}

download.sha256 is mandatory and is verified before anything reaches the device.

permissions is shown at install, informationally.

role and provides_overlay are optional and mirror the bundle's manifest. set "role": "launcher" if the app declares role: launcher, and "provides_overlay": true if it ships an overlay. see launchers and overlays.

icon can be any image format.

min_libbridgething_version is the compatibility axis.

serve it with cors

your catalog url and every download.url must send Access-Control-Allow-Origin: *. the companion apps are native and do not care, but bridgething.com cannot read a cross-origin response without it.

Access-Control-Allow-Origin: *
Accept-Ranges: bytes
Access-Control-Expose-Headers: content-length, content-range, etag, accept-ranges

github raw and github pages already comply

if you are writing a client

emit versions[] newest-first by released_at, but never rely on a source having done so.

// correct: sort, then pick
const newest = entry.versions
  .filter(v => compatible(v.min_libbridgething_version, device.libbridgethingVersion))
  .sort((a, b) => Date.parse(b.released_at) - Date.parse(a.released_at))[0];

// wrong: trusts a file you did not write
const newest = entry.versions[0];

getting listed

you do not need to be listed anywhere for your source to work. someone who has your url can add it and install from it, always. the directory exists so people can find you without already knowing the url.

submit yours on the apps page. it is checked automatically for three things: that it is reachable over https, that it parses as catalog.v1, and that it sends Access-Control-Allow-Origin.

a fresh submission lands as unreviewed: named on the apps page under a collapsed section and nowhere else, with its apps left out of the grid. once someone looks at it, it becomes listed, its apps show up under community apps, and the phone app offers it as a quick-add. vouched for is an editorial nod on top of that, and it is what moves your apps up next to the official ones.

if your source goes down it is reported, not removed, and apps already installed from it keep working.

identity, and what happens when two sources collide

an installed app is pinned to the source it came from, and updates are auto-offered only from that source. another catalog listing the same uuid shows up as "also available from".