Skip to content

Mobile App Builder Architecture

mp-mobile-app-builder is a standalone repository whose sole purpose is producing signed, distributable native app packages for the iOS App Store and Google Play Store.

For the mobile app itself (development, features, OTA updates) see Mobile App Architecture. For deployment steps see iOS Build and Android Build.


Why a Separate Repo?

mp-mobile-app (the main patient app) and mp-mobile-app-builder serve different purposes and deliberately stay separated:

mp-mobile-appmp-mobile-app-builder
PurposeActive development, web deployment, OTA updatesNative app store package production only
Nuxt versionNuxt 4 (latest)Nuxt 3 (older — may lag behind)
DependenciesFull dev toolchain, mobile plugins, CapacitorMinimal — only what's needed for a static build + Fastlane
Used byDevelopers dailyCI/CD + release engineers on release day
Native reposios/ + android/ submodulesios/ + android/ submodules (separate native repos)

Why keep the Nuxt version older in the builder?

The builder only needs to produce a static bundle (nuxt generate). Upgrading it in lockstep with mp-mobile-app every time would add risk to release builds with no benefit. The builder is upgraded deliberately when needed.


How a Native Build Works

mp-mobile-app-builder

  ├─ nuxt generate              → .output/public/ (static web bundle)

  ├─ npx cap sync               → copies .output/public/ into ios/App/public/
  │                               and android/app/src/main/assets/public/

  ├─ Fastlane ios beta          → xcodebuild archive → IPA → TestFlight

  └─ Fastlane android internal  → gradle bundle Release → AAB → Play Store internal

Step 1 — Static generation

nuxt generate produces a fully static bundle in .output/public/. This is the web content that will run inside the native WebView.

Step 2 — Capacitor sync

npx cap sync copies the generated web bundle into the native projects and installs any Capacitor plugin native code changes.

Step 3 — Fastlane build + upload

Fastlane handles code signing, archiving, and store upload. See iOS Build and Android Build for full lane documentation.


Repository Structure

mp-mobile-app-builder/
  ios/                              ← git submodule → mp-mobile-app-ios-native
    App/
      fastlane/
        Fastfile                    ← beta lane: setup_ci + match + build + upload
        Appfile                     ← com.medipal.sigil + team/issuer IDs
      App.xcodeproj/
      capacitor.config.json
  android/                          ← git submodule → mp-mobile-app-android-native
    fastlane/
      Fastfile                      ← internal lane: gradle bundle + play store upload
      Appfile                       ← com.medipal.sigil
    app/
      src/
  nuxt.config.ts
  capacitor.config.ts
  package.json

Git Submodules

The native Xcode and Android Studio projects live in separate repositories to keep platform-specific build artifacts, provisioning data, and IDE files isolated from the web codebase.

Submodule pathRepository
ios/mp-mobile-app-ios-native
android/mp-mobile-app-android-native

After cloning mp-mobile-app-builder, always initialize submodules:

bash
git clone --recurse-submodules <mp-mobile-app-builder>
# or:
git submodule update --init --recursive

When the native projects are updated (Xcode project settings, Capacitor plugin native code), update the submodule pointer:

bash
cd ios && git pull origin main && cd ..
git add ios && git commit -m "chore: update ios native submodule"

Live Update Bundle

When the USE_LIVE_UPDATE environment variable is set, npm run generate additionally produces:

  • live-update.zip — compressed web bundle for OTA delivery
  • manifest.json{ hash, version, timestamp, contentUrl }

These are uploaded to the updates.{env}.medipal.dev CDN endpoint (served by mp-frontend-nginx-proxy). The running app checks this manifest on startup and downloads the zip if its local hash is stale.

bash
USE_LIVE_UPDATE=true npm run generate

See Mobile App Architecture — Live Update for the full OTA update flow.


Key Environment Variables

VariableUsed inPurpose
API_URLNuxt buildBackend API base URL baked into the bundle
API_KEYNuxt buildAPI key baked into the bundle
CRYPTO_KEYNuxt buildAES key for deep-link token decryption
LIVE_UPDATE_URLNuxt buildOTA update server URL
USE_LIVE_UPDATENuxt generateEnables live-update zip + manifest generation
APP_STORE_CONNECT_API_KEY_IDFastlane (iOS)App Store Connect API authentication
APP_STORE_CONNECT_API_ISSUER_IDFastlane (iOS)App Store Connect API authentication
APP_STORE_CONNECT_API_KEY_CONTENTFastlane (iOS).p8 key content
MATCH_PASSWORDFastlane (iOS)Passphrase for mp-fastlane-certificates decryption
ANDROID_KEYSTORE_*Fastlane (Android)APK/AAB signing

npm Scripts

ScriptWhat it does
npm run buildnuxt generate (web bundle only)
npm run build:iosnuxt generate + cap sync ios
npm run build:androidnuxt generate + cap sync android

See Also