← Mosaic

App manifest contract

An external mosaic app is a normal web app on its own origin. To be installable as a launcher tile, serve a manifest at /.well-known/mosaic.json — with CORS enabled so the launcher can fetch it — matching this JSON schema (v0.1):

{
  "slug": "etch",
  "name": "Etch",
  "url": "https://etch.example.com",
  "emoji": "🛰️",
  "description": "Ambient GPS journal (bring your own server)"
}
FieldReqMeaning
sluglowercase kebab-case id, unique per user registry
nametile display name
urlabsolute URL the tile opens
iconsquare icon URL
emojifallback glyph when no icon
descriptionone-liner shown while installing
widget.endpointreserved: glance-widget JSON endpoint (spec coming)

How installation works

  1. The user opens the launcher's Apps page (swipe left, or /#apps) and pastes your app's URL.
  2. Mosaic fetches the manifest, validates it, and adds a tile.
  3. The registry lives only in that user's localStorage — there is no server-side app directory and no review process.

The hard rule

Linked, never embedded. Mosaic will not iframe your app or import your code — the launcher origin holds users' OAuth tokens, so no third-party code runs there, ever. Your app gets its own origin, its own storage, its own permissions. Storage is entirely your concern (etch, for instance, talks to a server the user runs on their own tailnet — see Storage for the pattern and requirements).

Feeling native

  • Adopt the design contract.
  • Ship a PWA manifest so standalone installs look right.
  • If users reach you from an HTTPS mosaic deploy, your app must be HTTPS too (mixed-content rules) — on a tailnet, tailscale serve gives you certificates.