Skip to content

feat: add host-controlled external navigation - #130

Merged
robinvrd merged 7 commits into
mainfrom
robin/external-link-navigation
Nov 2, 2026
Merged

robinvrd merged 7 commits into
mainfrom
robin/external-link-navigation

Conversation

@robinvrd

@robinvrd robinvrd commented Nov 2, 2026

Copy link
Copy Markdown
Contributor

Bundle apps cannot open external links from their restricted iframe. Add ExternalLink and the navigateNewTab, navigateNewWindow, and navigateNewWindowOrTab client helpers, delivering navigation intent through an opt-in navigation:openExternal bridge route without relaxing the sandbox.

The host validates HTTPS URLs and optional allowed origins, then asks for confirmation before opening the destination. Original Shift/Ctrl/Cmd intent survives the bridge. Existing frontend navigation helpers can be registered directly with createExternalLinkHandler({ navigate: navigateNewWindowOrTab }); the SDK supplies an undispatched synthetic KeyboardEvent with the navigation modifiers during the real confirmation click. Ordinary links request a new tab.

Local preview hosts are wired up. Other viewers must register the route. Cancellation cleans up the host dialog and allows links hidden by React Activity to work when restored.

Validation: bun run check passed with Bun 1.4.4 and four test workers, including all 1,063 tests, package-consumer checks, and starter checks. The 35 focused navigation tests cover URL policy, all three intents, modifier precedence, popup isolation, helper failures, and cancellation/retry behavior.

Add ExternalLink and an opt-in navigation route with HTTPS validation,
origin policy, and host-owned confirmation. Preserve the bundle sandbox
and wire the local preview host.

Validation: build, static checks, reference check, starter check, and
1,044 tests pass. Packed consumer installation is blocked by npm
returning 404 for es-toolkit@1.53.1.

@albert20260301 albert20260301 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No blocking findings. The route is opt-in, validates absolute credential-free HTTPS destinations and exact allowed origins, and keeps confirmation in the host without widening the iframe sandbox. Modifier intent survives transport; cancellation and Activity restoration clean up pending requests.

Local build, types and lint pass, as do all 35 focused tests (21 policy/helper tests and 14 Chromium workflows), including confirmation, popup isolation and cancellation. Required source/packed CI is green.

Other viewers still need to register the route. This is not available in published packages until a containing SDK release is published.

@robinvrd
robinvrd merged commit f254243 into main Nov 2, 2026
6 checks passed
@robinvrd
robinvrd deleted the robin/external-link-navigation branch November 2, 2026 13:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants