# Build and validate the iPhone and iPad app

A persistent iOS shell presents the same workspace, with adaptive navigation and system integrations.

The installed iOS shell loads the authenticated Ralti app origin in a persistent system WebView. It uses the same responsive components, feature paths, permissions, and APIs as the website. Flutter initializes the shell and existing platform plugins; it does not provide a second iOS workspace interface. Android currently retains the earlier Flutter interface.

```bash
cd mobile
flutter pub get
flutter devices
flutter run -d IOS_DEVICE_ID --dart-define=ATLAS_API_URL=https://app.your-domain.example
flutter analyze
flutter test
```

## Validate the shared navigation

Phone and narrow tablet layouts use Home, Workbooks, Create, Search, and Explore. Wider iPad layouts use the sidebar. Home includes search, a recent or featured workbook, and quick actions. Verify that resizing and rotation keep navigation usable, while workbook sections and record back trails preserve context.

Exercise all ten sheet views, including Calendar’s Month, Week, and Agenda. Confirm table and timeline scrolling stays inside the working surface, visible group controls work by touch, record Details/Related work/Activity shortcuts reach their sections, and document Edit/Preview controls retain the same draft. Review and revision checks must remain identical across devices.

## Match the server and identity

ATLAS_API_URL must be the actual app origin and reachable from the device. A physical phone’s localhost is the phone, not your development computer. Hosted deployments use HTTPS. Configure the server’s exact app origin, secure cookies, Clerk domain, and email callback addresses. The public marketing site cannot serve authenticated workspace APIs.

Email sign-in, verification, and recovery render inside the installed iOS app. Only explicit social-provider actions open the system authentication browser, then establish the persistent website session through a short-lived, single-use handoff. Canceling returns to the inline form. Existing authorization and account-linking rules remain authoritative. Keep app and browser accounts aligned for mailbox consent. Apply all current database migrations before distributing a build; server/provider secrets never enter the bundle.

## Create an installable build

```bash
npm run device:build-ios -- --api-url https://app.your-domain.example
```

Run that command from the repository root with Flutter, Xcode, CocoaPods, a valid Apple development team, and provisioning available. It creates a release-mode development-signed app and output/ios/Ralti.ipa; it does not install, upload, or submit the app. TestFlight/App Store distribution requires its own archive and account workflow. A simulator bundle or unsigned archive is not installable by sharing it to an iPhone. Android release delivery requires a private release keystore.

> **Validate on real hardware** Offline write queues, background sync, push notifications, and system share extensions are not included. Check physical-device sign-in, social-provider return, file picking and sharing, printing, speech permissions, keyboard layout, and saved-state continuity before distribution. Automated tests and successful builds do not prove account- or hardware-dependent flows.

For Android, use the existing Flutter setup with ATLAS_API_URL and the matching public CLERK_PUBLISHABLE_KEY. The shared iOS shell does not establish Android feature parity. Keep platform-specific acceptance results separate, including hardware permissions, provider consent, and distribution readiness.

