clone

a deno framework for local-first web apps that open instantly, work offline and sync when users choose

feat/prf-provision-custody
lofi / docs / recipes / protocol-handler.md
protocol-handler.md 2.5K rendered
1# Custom-protocol collaborative-list links23Use this recipe when a companion tool needs to open one collaborative-list item in an installed PWA.4The manifest surface is5[experimental and not Baseline](https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps/Manifest/Reference/protocol_handlers),6so every shared item must also have an ordinary HTTPS deep link.78## 1. Declare one custom scheme910The starter registers no protocols. Add one lowercase `web+` scheme and a same-scope, prerendered11handler route:1213```json14{15 "protocol_handlers": [16 {17 "protocol": "web+lofi",18 "url": "./open-item/?url=%s"19 }20 ]21}22```2324The validator requires exactly one `%s`, as the entire value of one query parameter. It rejects25privileged schemes, duplicate protocols, extra members, fragments, escaped scope, and a handler26route that is missing from the offline production output.2728Protocol registration and conflicts are browser- and OS-dependent. A browser may ask the user for29confirmation, another application may remain the default, and manifest changes may require an app30refresh or reinstall. To remove the capability, delete `protocol_handlers`, rebuild, refresh or31reinstall the PWA, and verify the OS association separately.3233## 2. Parse identifiers, not a redirect3435Use links shaped like:3637```text38web+lofi:collaborative-list/list_123/item/item_45639```4041On the action route:4243```ts44import { parseCollaborativeListProtocolTarget } from "@nzip/lofi/recipes/protocol-handler";4546const result = parseCollaborativeListProtocolTarget(location.search, {47 protocol: "web+lofi",48 parameter: "url",49 maxLength: 512,50});5152if (result.ok) {53 showItemPreview(result.target.listId, result.target.itemId);54} else {55 showGenericInvalidLink();56}57```5859`URLSearchParams` performs the one query decode. The parser rejects remaining percent escapes rather60than decoding a second time. It bounds the decoded URL, requires the exact configured scheme and the61exact `collaborative-list/LIST/item/ITEM` shape, and allow-lists both IDs. It returns identifiers62only; the received URL can never become `location.href`, a router destination, or proof of caller63identity.6465Build the fallback HTTPS link from your own origin and the validated identifiers. Unsupported66browsers and devices then open the same item through ordinary navigation.6768Test direct HTTPS navigation, a valid protocol launch, wrong schemes, malformed and double-encoded69values, duplicate parameters, oversized input, offline action-route startup, fallback links, handler70conflicts, and removal/reinstallation behavior.