URL scheme
How flitz:// links open bundles and the panel, the hosts the loader reserves, sharing the scheme, and how to use a custom scheme.
The loader opens bundles through flitz://download?url=<https-url> links: it
downloads the bundle at <https-url> over HTTPS and runs it. The value must be
https:// and is URL-encoded inside the url query parameter.
flitz publish emits these links: it prints the link, shows it as a QR code (in
the terminal, or as a --qr-output PNG), and puts it behind the button on the
bundle's landing page. The panel opens builds
through the same links. A track's link opens whichever build is newest on that
track when the download starts.
flitz://download
The url query parameter must be present, non-empty, and parse as an
https:// URL with a host. Plain http:// is rejected. The download follows
up to five redirects, each of which must also be https://.
flitz://download?url=https%3A%2F%2Fexample.com%2Fbuilds%2Fmy_app.flitzWhat the server and the network must provide:
- An HTTP
200with the archive. A host without sign-in sends no credentials, so the URL must be downloadable as is. A host with sign-in sends the signed-in user's token only to Flitz's own download host, and drops it at the first redirect to any other host; links to your own servers never receive it. Nothing is cached or resumed; every open downloads the bundle again. - A download that finishes in time. On iOS the whole transfer must complete within 30 seconds, so a large bundle on a slow network can fail. On Android the connection must open within 15 seconds, and each read must arrive within 30 seconds.
The download screen shows progress. A failed download shows Download failed
with the reason — for example HTTP 404 …, Too many redirects (>5) for <url>,
or a redirect to a non-https URL — and a Retry button.
When the build's app is set to Members only, Flitz refuses the download to a host without sign-in and to an account outside the app's organization. The loader then shows Members only or Can't open builds with this account, with no Retry — see Members only.
Recognition rules
The loader identifies its URLs by authority — the download in
flitz://download — never by scheme. The operating system only delivers URLs
for a scheme your app has registered, so the scheme is already validated by the
time the loader sees it — which is what makes custom schemes work with no code
change.
- The authority is matched case-insensitively. A URL with any other authority
is not the loader's: on iOS it falls through to your own open-URL handling,
and on Android it never reaches the loader. Android routes links from other
apps only when the authority is lowercase, as
flitz publishemits it. See Reserved hosts. - A
downloadURL whose parameters are malformed is "ours, but invalid" and shows the loader's native error screen ("Invalid bundle URL" on Android, "Invalid URL" on iOS) with the parser's reason. - A new
downloadURL arriving while a bundle runs replaces the current bundle: its engine is torn down, its extracted files are removed, and the new one opens. On iOS the new flow takes over the window the same way the first one did. One bundle runs at a time. Opening the panel ends a running bundle the same way.
flitz://flitz-panel
flitz://flitz-panel opens the panel in a
host with sign-in. Any path or query is ignored. In a host without sign-in the
loader takes the link and does nothing. Opening the panel ends a running
bundle; a panel that is already open stays as it is.
Reserved hosts
On its scheme the loader owns three hosts, whether or not sign-in is on:
download— opens a bundle;flitz-panel— opens the panel;flitz-auth— where the sign-in page returns to the app. Never link to it.
Your own deeplinks on the same scheme must use other hosts.
Sharing the flitz scheme
The landing page's button opens the flitz:// link in whichever installed app
handles the scheme. On a device where another app also handles flitz://
links, Android may ask which app should open the link, and on iOS it is
undefined which app opens it.
To make links open your host, give it its own scheme and publish with a
matching --schema — see Custom schemes.
With sign-in on Android, the same applies when the sign-in page returns to the app: Android may ask which app should open the result. Pick your host. Your own scheme avoids the question.
Custom schemes
flitz is the default scheme, not a requirement. The scheme is set through the
native registration you already write; the loader has no runtime setting for it.
-
Android: set it in the Gradle plugin's block. The value must be a lowercase URL scheme of at most 32 characters (letter-led; lowercase letters, digits,
+,-,.); the build fails otherwise.android/app/build.gradle.kts flitz { enabledFlavors = listOf("withLoader") urlScheme = "acme" } -
iOS: in
Info.plist, change the scheme in theCFBundleURLTypesentry namedFlitzLoader— its firstCFBundleURLSchemesvalue — fromflitzto your scheme. Keep the entry's nameFlitzLoader: with sign-in on, the loader reads its scheme from that entry and reports Loader build is broken without it. No Swift change is needed. -
Publishing:
flitz publish --schema acme, orschema: acmeinflitz.yaml, makes the printed link, the QR codes, and the landing page's button use your scheme. The value must be a lowercase scheme of at most 32 characters. It is not checked against any app: if it does not match what the host registered, the link opens nothing. With sign-in, it must also be the scheme you gave Flitz. See flitz publish.
Your own deeplinks
The loader owns only the reserved hosts, so your app can use
the same scheme for its own deeplinks (for example acme://profile/42):
- iOS: those links go to whichever Flutter engine is running — your app's until a bundle loads, then the bundle's.
- Android: those links go to your own activities, never to the loader. Bundles do not receive deeplinks on Android.
Give the loader a distinct scheme if any of your own links use a reserved host, or if on iOS you do not want a running bundle to receive your app's links.