Domain Handling
How the SDK routes navigation between the main webview and the in-app browser
Domain Handling
When your web app runs inside the starti.app container, every link the user taps needs to go somewhere. Some links should stay inside the main webview (internal), and some should open in an in-app browser (external). This page explains how the SDK decides which is which and how you can control it.
The default behavior
By default, only your app's starting domain is considered internal. Any link to an unknown domain opens in the in-app browser — a browser view that appears on top of your app, which the user can close to return. This prevents the user from accidentally navigating away from your content.
your-app.com/page → stays in the main webview (internal)
maps.google.com → opens in the in-app browser (external)
partner-site.com → opens in the in-app browser (external)Internal domains
Internal domains are loaded inside the app's webview. The user stays in the app and sees the content inline. Use this for domains that are part of your app experience, like a partner site or a payment gateway.
await startiapp.App.addInternalDomain("partner-site.com");
// Now partner-site.com loads inside the appInternal domains are matched as exact strings against the host of the URL.
External domains
External domains use regex patterns for flexible matching. This is useful when you want to force certain link patterns to always open in the in-app browser, even if they would otherwise match an internal domain.
await startiapp.App.addExternalDomains(
/maps\.google\.com/,
/\.pdf$/
);The SDK serializes the RegExp as { pattern, flags } and sends it to the native layer, which applies the pattern against the full URL.
External domains take precedence over internal domains. If a URL matches both an internal domain and an external pattern, it opens in the in-app browser.
The "all internal" mode
Sometimes you want everything to stay in the app. For example, if your app is a browser-like experience or aggregates content from many sources:
await startiapp.App.handleAllDomainsInternally();After this call, all domains are treated as internal. You can still force specific patterns to be external:
await startiapp.App.handleAllDomainsInternally();
await startiapp.App.addExternalDomains(/play\.google\.com/, /apps\.apple\.com/);handleAllDomainsInternally() is a session-only setting. It resets when the app restarts. External domain rules persist normally.
To go back to the default behavior:
await startiapp.App.restoreDefaultDomainHandling();Decision flowchart
The navigatingPage event
Whenever the app navigates, the navigatingPage event fires with the target URL and whether it will open externally:
startiapp.App.addEventListener("navigatingPage", (event) => {
console.log("Going to:", event.detail.url);
console.log("External?", event.detail.opensExternalbrowser);
});This is useful for analytics, logging, or dynamically adjusting behavior based on where the user is going.
Opening a URL in the device's browser
If you need to open a URL in the device's actual browser (Safari, Chrome) — completely outside the app — use openExternalBrowser. This is the only way to open Safari or Chrome; external domains always open in the in-app browser, not the device's browser.
await startiapp.App.openExternalBrowser("https://maps.google.com/?q=Copenhagen");Practical patterns
Allow a payment gateway in-app
await startiapp.App.addInternalDomain("checkout.stripe.com");
// User completes payment without leaving the app
// Remove when done:
await startiapp.App.removeInternalDomain("checkout.stripe.com");Force store links to the in-app browser
await startiapp.App.addExternalDomains(
/apps\.apple\.com/,
/play\.google\.com/
);Allow everything except downloads
await startiapp.App.handleAllDomainsInternally();
await startiapp.App.addExternalDomains(/\.pdf$/, /\.zip$/, /\.xlsx$/);