> ## Documentation Index
> Fetch the complete documentation index at: https://www.minitap.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Providing app builds

> Get your iOS or Android build onto a virtual device for a run — Mini builds it from your repo, or you upload one.

Every run uses a real build of your app, running on a virtual device. There are two ways to get a build to Mini, and you can mix them per app.

<Tabs>
  <Tab title="Mini builds it (recommended)">
    Connect your repo and Mini does the build for you. When a run needs a fresh artifact, it pulls the right commit, compiles for iOS and Android, and hands the binary to the test device.

    Requires:

    * The **MiniTest GitHub App** installed on the org. See [GitHub integration](/docs/minitest/integrations/github).
    * The build env vars your app needs to compile (see below).

    Monorepos are supported — point Mini at the subfolder that holds your mobile app in **App Settings → Builds**.

    This is the path that powers [PR checks](/docs/minitest/runs/triggering-a-run): when a PR opens, Mini builds the head commit, runs the suite, and posts the verdict back on the PR.

    <Note>
      For Expo apps, Mini supports **repack builds** — incremental rebuilds that reuse the native shell when only the JS bundle has changed. First build of the day is full; the rest are fast.
    </Note>

    ### Build env vars

    Most mobile builds need at least one env var to compile cleanly: an API base URL, a Sentry DSN, a feature flag override. Mini stores them per app and injects them at build time.

    Set them in **App Settings → Builds → Environment Variables**. Add, edit, or remove individual values. Changes take effect on the next build.

    ```env theme={null}
    API_URL=https://staging.example.com
    SENTRY_DSN=https://abc@sentry.io/123
    FEATURE_FLAG_CHECKOUT_V2=true
    ```

    <Note>
      Values are encrypted at rest and only decrypted inside the build environment. They don't appear in dashboard logs, run reports, or copies of the fix prompt.
    </Note>

    ### Build options

    Two more switches live in **App Settings → Builds → Advanced build settings**. Like build env vars, they only apply when Mini builds your app from your repo. An uploaded build is already compiled, so these options can't touch it.

    #### Testing RevenueCat purchases

    <Note>
      **Experimental.** These patches modify your native project inside the build environment, and every app's build setup is different. The first build after enabling may fail, or purchases may not complete. When that happens we get the failed build on our side and investigate to make the patches work with your app. You can switch the toggle off at any time to go back to normal builds.
    </Note>

    If your app monetizes through RevenueCat, runs can exercise your real purchase flows, paywalls included, against RevenueCat's [Test Store](https://www.revenuecat.com/docs/test-and-launch/sandbox/test-store). No mocking on your side.

    This works for React Native and Expo apps using `react-native-purchases`, on both iOS and Android. Other frameworks aren't supported yet.

    To set it up:

    1. Create a Test Store in your RevenueCat project and copy its `test_` API keys. RevenueCat's [sandbox testing guide](https://www.revenuecat.com/docs/test-and-launch/sandbox) covers two options; the one used here is the **Test Store**, not the platform sandboxes (Apple sandbox and Google Play testing tracks).
    2. Put those keys in your build env vars (above), under the same variable names your app reads its RevenueCat keys from. Your app must read the key from configuration rather than hardcode it, so test builds hit the sandbox while your production builds keep using the production key.
    3. Turn on **RevenueCat sandbox patches** in **App Settings → Builds → Advanced build settings**.

    On the next build, Mini patches the native build files so the binary on the virtual device can complete sandbox purchases. Your source code is never modified; the changes only exist inside the build environment.

    #### Loop animations are frozen by default

    To the agent, an infinite spinner looks exactly like a screen that's stuck loading. To avoid runs failing on animations that were never going to end, Mini ships every Expo and React Native build with **Disable loop animations** turned on.

    At build time, looping animations are patched to settle immediately: `Animated.loop` completes on its first frame, and Reanimated's `withRepeat` runs one cycle instead of repeating. Everything else keeps working as shipped, including transitions, gestures, and any animation that ends on its own.

    Turn the toggle off in **App Settings → Builds → Advanced build settings** if your app has looping animations that need to keep running during a run.
  </Tab>

  <Tab title="You upload it">
    Build the app yourself — on your laptop, on Bitrise, on Codemagic, wherever — and push the artifact with the [CLI](/docs/minitest/integrations/cursor-and-claude):

    ```bash theme={null}
    minitest build upload ./path/to/build.ipa
    # or
    minitest build upload ./path/to/app-debug.apk
    ```

    The CLI prints a build ID you can target from a run. Best for one-off checks and for apps whose build pipeline lives outside GitHub.

    <Note>
      Build env vars don't apply here, and neither do the build options above: your artifact already baked everything in.
    </Note>
  </Tab>
</Tabs>

## Picking a build for a run

When you trigger a run from the dashboard, the build picker lets you:

* Use the **latest** build for the configured branch (default).
* Pick a **specific commit** or build ID.

CI-triggered runs always use the build produced by the triggering commit. There's no manual picking when Mini is gating a PR.

## Web preview URLs

When you run a web build, Mini deploys it to a generated preview host you can open and share. The host looks like this:

```text theme={null}
<preview_key>--<tenant_slug>.preview.minitap.ai
```

`<tenant_slug>` is your Workspace slug, which you'll find in **Settings → General**. `<preview_key>` is derived per build, so each build you run gets its own host on `preview.minitap.ai`.

### The injected env var

The build automatically receives `MINITAP_PREVIEW_URL`, set to that preview URL. You don't add this variable yourself. When you need the host inside your build config, reference the placeholder `{{MINITAP_PREVIEW_URL}}` and Mini fills it in at build time.

```env theme={null}
MINITAP_PREVIEW_URL=https://<preview_key>--<tenant_slug>.preview.minitap.ai
```

### OAuth and allowed redirects

If your web app uses OAuth or any origin allow-list, preview builds need their host accepted. Add the wildcard domain below to your provider so every preview build authenticates without a per-build change:

```text theme={null}
*--<tenant_slug>.preview.minitap.ai
```
