# Xyvenra Mobile build and release workflows

Xyvenra Mobile generates an Expo React Native project and ready-to-use EAS profiles. Expo runs the builds, submissions, and updates under the developer's Expo account. Xyvenra does not run build workers or charge for these actions.

## Run a starter online with Expo Snack

From the Mobile builder, choose **Run starter in Expo Snack**. The link opens Expo's editor in a new tab and starts the React Native starter in the Web preview. Add, toggle, or remove a sample task or habit, or edit a sample note. Expo also offers a **My Device** option for compatible Expo Go installations.

In a downloaded task, habit, or notes starter, use the pencil beside an item to load its title into the entry field. Save with the check button or cancel with ×. Notes also let you edit the note body directly. Item changes save locally on the device or browser.

Generated projects include **Items**, **Overview**, and **Backup** screens. Overview summarizes item counts, task or habit completion, or the character count of note text, and shows recent items. Backup holds the local export and restore controls and explains the storage boundary. Switching screens does not copy data to Xyvenra or Expo.

Use the up and down arrows beside an item to reorder the list. The first item's up control and the last item's down control are disabled. Reordering keeps each item's completion state or note body and saves with the app's local data.

Search the generated app's list by item title; the notes starter also searches note bodies. Search is case-insensitive and does not change the stored list. Use **Clear search** to show all items again. A no-results message appears when nothing matches.

Task and habit starters also provide **All**, **Active**, and **Completed** filters. They combine with search and only affect the displayed rows; toggling items, reordering, and local persistence continue to use the full list. The notes starter has no completion filter.

The link sends the generated `App.js`, including the selected starter, app name, accent color, and a built-in example. Your tasks, habits, note text, bundle identifier, and Xyvenra account saves stay in Xyvenra. Snack selects its supported SDK independently of the ZIP download. Snack edits are separate from your Xyvenra draft. Use the Xyvenra ZIP for the full project, your seed data, and the EAS profiles.

## Back up installed-app data

Generated task, habit, and notes apps can export or restore their local item data with **Export backup** and **Import backup**. Native apps offer the JSON through the device's share sheet. Web builds try the browser clipboard and leave the JSON available for manual copy if clipboard access is unavailable.

Backups use a versioned Xyvenra Mobile JSON format and contain only the current starter app's items. They are limited to 100 items and 250 KB; titles are limited to 160 characters and note text to 1,000 characters. Import accepts only the matching starter type, validates the fields and limits, previews how many items will replace the current list, and requires an explicit **Restore on this device** action.

The Items screen reports whether the latest local save succeeded. If storage is unavailable, export a backup before leaving. This is a manual local backup, not account sync. Xyvenra does not receive the exported JSON. It excludes builder settings, account saves, provider credentials, and data from other apps. The app still stores its active list in unencrypted AsyncStorage, scoped to that installation or browser origin; clearing app/browser data can erase it. Store backups somewhere private. Mobile/EAS workflow support and provider limits are described below.
## App icon and launch screen

The downloaded ZIP generates a 1024-pixel PNG app icon and a transparent launch-screen mark from the selected accent. The native config uses Expo's splash-screen plugin. The icon and launch screen are generated in your browser and included in the ZIP; Xyvenra does not upload them. Expo Go shows its own launch screen, so install a fresh preview or production build to check the configured launch screen. Rebuild after changing native image assets or app config. See Expo's [app icon and splash screen guide](https://docs.expo.dev/develop/user-interface/splash-screen-and-app-icon/).

## Export a standalone web app

Download and unzip the Expo project. With Node.js 24.3 or later in the 24.x release line, run `npm install` and `npm run export:web`. Metro writes a single-page web build to `dist/`. Run `npm run serve:web` to try the production output locally. You can deploy the contents of `dist/` to the root of a static site without an Expo account. Expo Hosting is another option after signing in and linking the project. Run `npx eas-cli@latest deploy` to create a preview deployment. See the [Expo web publishing guide](https://docs.expo.dev/guides/publishing-websites/).

The export contains the builder's initial item text in its JavaScript bundle. Remove any private seed data before publishing. Visitor edits use browser storage for that origin and stay separate from the Xyvenra builder and native app installations.

## Profiles in `eas.json`

- **development** creates an internal development-client build for iterating with `expo start --dev-client`.
- **preview** creates an internal Android APK or iOS installable build for tester distribution.
- **ios-simulator** creates a standalone build that runs in the iOS Simulator; it does not create a device-installable IPA.
- **production** creates a store-ready build with remote app-version incrementing.
- **submit:production** selects the production submission profile.

The development profile needs the version of `expo-dev-client` compatible with the selected Expo SDK. Run the generated `npm run setup:development` script before the first development-client build. EAS profile fields and development-client requirements are described in the [Expo EAS Build configuration guide](https://docs.expo.dev/build/eas-json/).

## Link the project and build

1. Install Node.js, unzip the project, and run `npm install`.
2. Sign in to the Expo account that should own the build, then run `npx eas-cli@latest init`.
3. Run `npx eas-cli@latest build:configure`. If it edits the generated `eas.json`, keep the development, preview, and production channel settings.
4. For development, run `npm run setup:development`, then `npm run build:development -- --platform android` or `--platform ios`.
5. For internal preview, run `npm run build:preview -- --platform android` or `--platform ios`.
6. For a store build, run `npm run build:production -- --platform all`.
7. After a build is complete and store credentials are configured, submit it with `npm run submit:production -- --platform all`.

Apple Developer and Google Play developer accounts, signing credentials, store listings, and review are managed by the app owner. Put build credentials in Expo's credential management or environment secrets; never commit them to the generated project.

## Build and run an iOS Simulator preview

The project ZIP includes an `ios-simulator` EAS profile and a manual `.eas/workflows/ios-simulator-preview.yml`. After installing dependencies, signing in to your Expo account, and linking the project, run `npm run build:ios-simulator` to build directly or `npm run workflow:ios-simulator-preview` to run its Expo Workflow. The profile sets `ios.simulator: true`, so EAS can build it without Apple Developer enrollment or Apple signing credentials. Expo's build allowance and any account limits still apply.

To install the finished build, use a Mac with Xcode and an iOS Simulator, then run `npm run run:ios-simulator` and select the build. The simulator app is for desktop simulator testing; it cannot be installed on an iPhone or submitted to the App Store. See Expo's [iOS Simulator build guide](https://docs.expo.dev/build-reference/simulators/).

## Run the Android preview workflow

The downloaded ZIP includes `.eas/workflows/android-preview.yml`. From the extracted project, sign in with `npx eas-cli@latest login`, link the project and keep the existing profiles as described above. Set up its Android signing keystore using `npx eas-cli@latest credentials --platform android` and select the preview profile. Then run `npm run workflow:android-preview` and follow the run URL to the APK. A manual CLI run uploads the local project to Expo and works without linking GitHub. Review your source and seed data before uploading.

The workflow runs one Android job with the internal APK profile. It starts on explicit invocation and uses your Expo account's limits. Expo serves the build logs and APK. Check the project's internal-build access settings before sharing the install link. See the [Expo Workflows guide](https://docs.expo.dev/eas/workflows/introduction/).

## Check workflow status in your Expo project

The Mobile workspace also lets any signed-in Xyvenra user check one workflow run in an Expo project they can access. Enter the project slug as `account/project`, the workflow run ID, and an Expo access token. Create a token with access limited to the selected account and the Viewer role where Expo supports it. Read the run ID from its workflow URL in Expo. Xyvenra forwards the token to Expo for this read-only request, checks that the returned run belongs to the project slug you entered, and discards the request after the response. The token is held in page memory only and is cleared on reload or when you leave the page. Use a temporary, narrowly scoped token and revoke it in Expo when finished. The checker reports workflow and job states and links to Expo-hosted build details. It does not queue a workflow, retrieve build files, retain credentials, or save the project link. See Expo's [Workflows REST API](https://docs.expo.dev/eas/workflows/rest-api/) and [programmatic access guide](https://docs.expo.dev/accounts/programmatic-access/).

## Track a workflow in Xyvenra

The optional **Expo workflow status** panel is a pilot for one Xyvenra operator and one Expo project. Paste a run ID from the end of its Expo workflow URL to see current run and job status. The panel shows a validated source commit hash when Expo includes one, remembers the last valid run ID in the current tab's session storage, and restores it after a reload in that tab; choose **Check run** to refresh the restored run, then **Check again** for later refreshes. The run ID stays in that browser session, is not synced to your account, and is not an Expo credential. Open the linked Expo run for logs or the build page for the APK. Status checks use the Expo API. Build execution and artifact access are managed by Expo.

Xyvenra keeps the Expo build-details link for logs and exposes a separate **Download Android APK** link only when a signed EAS build webhook matches the pinned Expo app, project, Android platform, source commit, reserved workflow run, successful job, and build ID. It accepts only an HTTPS APK URL from Expo's `expo.dev/artifacts/eas/` path; Xyvenra does not proxy or retain the artifact. Expo controls access and retention. Its webhook signature is HMAC-SHA1 over the raw request body, carried in `expo-signature`; Xyvenra verifies it before parsing or storing the bounded allowlist fields. Expo retries deliveries that receive non-2xx responses. See the [Workflows REST API](https://docs.expo.dev/eas/workflows/rest-api/), [EAS webhooks](https://docs.expo.dev/eas/webhooks/), and [Expo data retention](https://expo.dev/security).

To enable the panel, add these server-side deployment settings and redeploy:

- `XYVENRA_MOBILE_EXPO_OPERATOR_ID` is the authorized Xyvenra account's Supabase user UUID.
- `XYVENRA_MOBILE_EXPO_PROJECT` is the Expo account and project slug in `account/project` form, as shown in the Expo dashboard URL.
- `XYVENRA_MOBILE_EXPO_TOKEN` is a read-only Expo access token for the project's runs. Create a robot user with the **Viewer** role on the owning account, create its token, and enter it directly as a server-side deployment secret. A Viewer can inspect runs but cannot dispatch builds.

The panel is hidden until all three settings are valid and the operator signs in. To verify setup, paste the ID of an existing run from that Expo project. The panel checks one run at a time and does not retain a run history. See [Expo Workflows REST API](https://docs.expo.dev/eas/workflows/rest-api/) and [Expo token permissions](https://docs.expo.dev/accounts/programmatic-access/).

### Queue a configured Android preview

Operators can optionally enable **Queue configured Android preview** for one reviewed source revision. Connect the Expo project to a repository containing the extracted Mobile project at its root and the generated `.eas/workflows/android-preview.yml`. Set up Android signing in Expo. The idempotent dispatch-reservation migration creates a table keyed by the configured Expo project UUID and pinned commit SHA; RLS is enabled, client roles have no table privileges, and only `service_role` can use it.

Alongside the read-only monitor settings, configure `XYVENRA_MOBILE_EXPO_PROJECT_ID` with the linked Expo project UUID and `XYVENRA_MOBILE_EXPO_PREVIEW_COMMIT` with the reviewed 40-character commit SHA. For dispatch, create a **separate** robot user and token with the **Developer** role, the lowest Expo account role that can start builds, and store its token as the server-side `XYVENRA_MOBILE_EXPO_DISPATCH_TOKEN` secret. The dispatch token is not the Viewer token. Redeploy to pick up these settings. The button sends only the pinned commit and fixed Android preview workflow to Expo, using the owning account's build allowance. Expo's REST endpoint still authorizes that token at the account/project level; Xyvenra constrains the request in its own server code.

Xyvenra reserves one dispatch per project and commit. A repeat returns the recorded run when available. If Expo accepted a build but the reservation could not be updated, the panel warns the operator not to queue that revision again. If a network error leaves Expo's answer uncertain, check the Expo dashboard before a database administrator clears an unresolved reservation. The operator should confirm there is no run for the commit before clearing it.

The production operator pilot is configured for one Expo project and a pinned GitHub revision. On November 8, 2026, the live Xyvenra button dispatched that revision, Expo built the Android preview APK successfully, and the signed-in status panel reported the successful workflow and linked Expo build details. Direct artifact links require the webhook setup below and are only shown for the pinned run and matching completed build. This does not enable customer-selected projects or builds.

### Dispatch and track an iOS Simulator build in Xyvenra

The operator panel can queue the pinned iOS Simulator workflow alongside Android by setting the server-only `XYVENRA_MOBILE_EXPO_IOS_SIMULATOR_ENABLED=true`. It reuses the existing operator allowlist, Expo project, pinned commit, and separate Developer-role dispatch token. Simulator runs use their own idempotency reservation so they do not block or reuse the Android run for the same commit. Apply migration `20261108130354_xyvenra_mobile_ios_simulator_dispatches.sql` before deploying this panel change. The iOS workflow file must be present in the Expo-linked repository at the pinned commit; update the pinned reviewed commit only after both workflow files are in that repository. The panel sends a workflow dispatch only after the operator confirms, then uses the same run-ID status check and Expo build-details link as other workflows. The simulator artifact migration and signed webhook handling are deployed. The production iOS dispatch panel remains disabled while `XYVENRA_MOBILE_EXPO_IOS_SIMULATOR_ENABLED` is false; no simulator build was triggered by this deployment. If the panel is enabled, a completed iOS build can expose a direct Expo-hosted archive link only when the signed build event, configured project, pinned commit, iOS Simulator profile, reserved workflow run, and successful matching build job all agree.

The project-wide Expo BUILD webhook used for artifacts also receives other profiles and revisions. Xyvenra acknowledges correctly signed, out-of-scope events without changing either artifact record. For simulator artifacts, the event must identify the pinned project and commit, use the `ios-simulator` build profile from the pinned Mobile workflow, and provide an Expo-hosted `.tar.gz` artifact. Xyvenra does not queue or run a build automatically.

To roll back this dispatch capability, set `XYVENRA_MOBILE_EXPO_IOS_SIMULATOR_ENABLED` to false or remove it and redeploy. After old app code is no longer reading/writing the table, run `drop table if exists public.xyvenra_mobile_expo_simulator_dispatches;`. Android reservations and run records are unaffected.

### Enable direct build artifact links

The production BUILD webhook is registered at `https://xyvenra.com/api/mobile/expo-build-webhook`. Its signing secret is stored in Vercel as `XYVENRA_MOBILE_EXPO_WEBHOOK_SECRET` and in Expo's webhook configuration; keep its value out of source files and logs. Vercel requires a deployment for environment changes to take effect.

Migration `20261108093002_xyvenra_mobile_expo_webhook_artifacts.sql` enables Android APK links and was applied to production on November 8, 2026. Migration `20261108135315_xyvenra_mobile_ios_simulator_artifacts.sql` adds a separate constrained simulator archive record. It was applied to production on November 8, 2026, before deploying this iOS artifact handling change. The webhook verifies Expo's raw-body HMAC-SHA1 signature before saving records. The status panel returns an artifact link only when the configured Expo project, pinned commit, dispatched workflow run, signed build ID, matching successful job, build profile, and strict Expo artifact URL allowlist all match. Android remains limited to `.apk` files at `https://expo.dev/artifacts/eas/`; simulator links are limited to `.tar.gz` files at that exact host and path. Xyvenra never proxies or stores the artifact bytes. Simulator archives require macOS and Xcode and cannot be installed on an iPhone.

To roll back iOS artifact links, deploy code without simulator artifact reads/writes, then drop the three added simulator artifact columns and constraints. Keep the project-wide webhook if Android artifact links are still needed.

The migration `20261108093002_xyvenra_mobile_expo_webhook_artifacts.sql` adds nullable build ID, terminal build status, and constrained APK URL fields to the service-role-only dispatch reservation table. It was applied to the production database on November 8, 2026. To roll back: disable/delete the Expo webhook, deploy code without webhook reads/writes, then run `alter table public.xyvenra_mobile_expo_dispatches drop constraint if exists xyvenra_mobile_expo_dispatches_artifact_status_check, drop constraint if exists xyvenra_mobile_expo_dispatches_artifact_url_check, drop constraint if exists xyvenra_mobile_expo_dispatches_build_status_check, drop column if exists expo_artifact_url, drop column if exists expo_build_status, drop column if exists expo_build_id;`. Existing dispatch/run reservations are preserved.

## Over-the-air updates

EAS Update publishes JavaScript and compatible asset changes. It cannot replace native code or add a native dependency to an installed binary. After the project is linked, configure updates once:

```sh
npx eas-cli@latest update:configure
```

That command sets the project update URL and runtime version policy. Build and install binaries for the configured update channels, then publish a production JavaScript update with:

```sh
npx eas-cli@latest update --channel production --message release-notes
```

Expo's [EAS Update setup guide](https://docs.expo.dev/eas-update/getting-started/) explains how runtime versions and channels keep updates compatible with installed binaries.

## Costs and limits

Expo applies its current build and update quotas, plan limits, and charges to the developer's Expo account. Use the Expo CLI steps above to link the downloaded project, start builds, publish updates, or submit to the stores.
