Flitzdocs
Loader plugins

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.flitz

What the server and the network must provide:

  • An HTTP 200 with 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 publish emits it. See Reserved hosts.
  • A download URL 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 download URL 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 the CFBundleURLTypes entry named FlitzLoader — its first CFBundleURLSchemes value — from flitz to your scheme. Keep the entry's name FlitzLoader: 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, or schema: acme in flitz.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.

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.

On this page