Skip to main content

Custom-protocol collaborative-list links

Use this recipe when a companion tool needs to open one collaborative-list item in an installed PWA. The manifest surface is experimental and not Baseline, so every shared item must also have an ordinary HTTPS deep link.

1. Declare one custom scheme

The starter registers no protocols. Add one lowercase web+ scheme and a same-scope, prerendered handler route:

{
"protocol_handlers": [
{
"protocol": "web+lofi",
"url": "./open-item/?url=%s"
}
]
}

The validator requires exactly one %s, as the entire value of one query parameter. It rejects privileged schemes, duplicate protocols, extra members, fragments, escaped scope, and a handler route that is missing from the offline production output.

Protocol registration and conflicts are browser- and OS-dependent. A browser may ask the user for confirmation, another application may remain the default, and manifest changes may require an app refresh or reinstall. To remove the capability, delete protocol_handlers, rebuild, refresh or reinstall the PWA, and verify the OS association separately.

2. Parse identifiers, not a redirect

Use links shaped like:

web+lofi:collaborative-list/list_123/item/item_456

On the action route:

import { parseCollaborativeListProtocolTarget } from "@nzip/lofi/recipes/protocol-handler";

const result = parseCollaborativeListProtocolTarget(location.search, {
protocol: "web+lofi",
parameter: "url",
maxLength: 512,
});

if (result.ok) {
showItemPreview(result.target.listId, result.target.itemId);
} else {
showGenericInvalidLink();
}

URLSearchParams performs the one query decode. The parser rejects remaining percent escapes rather than decoding a second time. It bounds the decoded URL, requires the exact configured scheme and the exact collaborative-list/LIST/item/ITEM shape, and allow-lists both IDs. It returns identifiers only; the received URL can never become location.href, a router destination, or proof of caller identity.

Build the fallback HTTPS link from your own origin and the validated identifiers. Unsupported browsers and devices then open the same item through ordinary navigation.

Test direct HTTPS navigation, a valid protocol launch, wrong schemes, malformed and double-encoded values, duplicate parameters, oversized input, offline action-route startup, fallback links, handler conflicts, and removal/reinstallation behavior.