Tappable Links

A tiny Cloudflare Worker that makes custom app URL schemes tappable from a chat message.

synodic-studio/patchbay-url-scheme-wrapperยท MIT

I built this for the Patchbay Relay workflow. When I run my studio from a phone, the agents on the Mac Mini constantly want to hand me a link: a note in my Obsidian vault, a reminder, a specific day in Calendar, a Things task. The natural way to do that is a custom URL scheme like obsidian://open?vault=.... The problem is that Telegram, and most chat apps, refuse to render a custom scheme as a link. It arrives as dead text. Tapping does nothing.

This Worker is the fix. It wraps the custom scheme in an ordinary https:// URL, which every chat app renders as a single tap. The Worker serves a one-line page that immediately bounces the browser to the real native-scheme URI, and the app opens on the phone.

How it works

https://go.example.com/obs/MyVault/notes/today.md
  -> serves a tiny redirect page
  -> obsidian://open?vault=MyVault&file=notes/today.md
  -> Obsidian opens on the phone

The redirect page is about as small as a web page gets: a meta refresh to the native URI with a JavaScript fallback for browsers that ignore it. There is no auth, no logging, and no server state. The whole thing is roughly 450 lines of Worker code with no runtime dependencies, and it costs nothing to run on Cloudflare’s free tier.

The reason it has to be a hosted https:// URL rather than something clever on the device is that the chat app is the gatekeeper. It decides what is a link, and its rule is “starts with http(s).” So you give it exactly that, and do the scheme swap one hop later in the browser, where custom schemes are allowed.

Routes

A handful of named routes cover the apps I link to most, with a base64url escape hatch for anything else:

Route Opens
/obs/<vault>/<path> a note in an Obsidian vault
/remind/<title> Apple Reminders
/cal/<yyyy-mm-dd> a date in Calendar.app
/cal/<yyyy-mm-dd>/<hh:mm> a date and time in Calendar.app
/raw/<base64url> any custom scheme, full URI base64url-encoded
/key/<uuid> an optional token-secured paste form

The named routes exist so an agent can construct a link by hand without encoding anything: https://go.example.com/obs/Cobalt/daily/today.md is something a language model writes correctly on the first try. The /raw/ route base64url-encodes a complete URI for the long tail of schemes that do not have a named shortcut.

The /key paste form

The one route that does more than redirect is /key/<uuid>, a one-shot paste form for getting a secret from the phone into the host without typing it into a chat. The host drops a short-lived token in Cloudflare KV and sends a /key/<uuid> link; tapping it shows a small labeled form, and the value the user pastes gets handed back to the host and the token deleted. A quiet way to move an API key from a phone to a server without it ever sitting in a chat log.

It is a standard Cloudflare Worker that runs on the free tier, and once it is deployed the agents start emitting tappable links on their own. The README has the deploy and custom-domain steps.