What problem are you trying to solve?
HTML Apps run in a sandboxed iframe (sandbox="allow-scripts allow-forms", no allow-popups, no allow-top-navigation). That's the right default, but it means an app has no way at all to send the user to an external website: plain <a href="https://..."> clicks navigate nowhere useful inside the frame, target="_blank" and window.open() are blocked by the sandbox, and the window.hubble runtime only exposes files.* methods.
Concrete example: a "reading list" HTML App that lists bookmarks from Markdown front matter can render the URLs but can't open any of them in the browser.
The Markdown editor already solves this for note links: clicks go through desktopApi.openExternalUrl(href) → desktop:open-external-url IPC → shell.openExternal(url), with the main process rejecting anything that isn't http(s).
Proposed solution
Extend the runtime broker (per ADR-0007, "future APIs should extend the runtime broker") with a links.open method:
window.hubble.links.open(url) / window.hubble.links.safeOpen(url) on the injected runtime global, matching the files.* style.
- The renderer-side
hubble:request handler validates the URL (http/https only, same rule as the existing main-process guard) and forwards to the existing desktopApi.openExternalUrl. No new IPC surface.
I have a small draft PR ready to pair with this issue — happy to adjust the naming or approach based on discussion here.
What problem are you trying to solve?
HTML Apps run in a sandboxed iframe (
sandbox="allow-scripts allow-forms", noallow-popups, noallow-top-navigation). That's the right default, but it means an app has no way at all to send the user to an external website: plain<a href="https://...">clicks navigate nowhere useful inside the frame,target="_blank"andwindow.open()are blocked by the sandbox, and thewindow.hubbleruntime only exposesfiles.*methods.Concrete example: a "reading list" HTML App that lists bookmarks from Markdown front matter can render the URLs but can't open any of them in the browser.
The Markdown editor already solves this for note links: clicks go through
desktopApi.openExternalUrl(href)→desktop:open-external-urlIPC →shell.openExternal(url), with the main process rejecting anything that isn'thttp(s).Proposed solution
Extend the runtime broker (per ADR-0007, "future APIs should extend the runtime broker") with a
links.openmethod:window.hubble.links.open(url)/window.hubble.links.safeOpen(url)on the injected runtime global, matching thefiles.*style.hubble:requesthandler validates the URL (http/https only, same rule as the existing main-process guard) and forwards to the existingdesktopApi.openExternalUrl. No new IPC surface.I have a small draft PR ready to pair with this issue — happy to adjust the naming or approach based on discussion here.