---
type: reference
title: "CAMDOM -- Stack Migrations & Build Evolution"
description: "Complete evolution of the technology stack: React Native versions, Expo SDK, JSI migration, TurboModules, build system, patches, CI/CD."
tags: [camdom, react-native, expo, build-system, migration, jsi, turbomodules]
timestamp: "2026-07-20"
---

# CAMDOM -- Stack Migrations & Build Evolution

> **Repository:** `p4bventures/condom-app`
> **Total commits:** 429 (2024-06-06 to 2025-11-16)
> **Package name:** `condom-app` (npm) / `com.billyboy.condomapp` (Android) / `innocean-camdom` (Expo slug)
> **Current version:** `4.44.44` (app.json) / `7.7.7` (package.json)

---

## 1. Timeline Overview

```
2024-06-06  Initial commit ........... Expo 51, RN 0.74.2, React 18.2.0, Reanimated 3.x
2024-06-16  Pipeline added .......... EAS Build, GitHub Actions v1
2024-07-01  Skia + Reanimated V3 .... @shopify/react-native-skia ^1.3.7
2024-07-01  Native Modules defined .. Expo Modules API (JSI) for BLE
2024-07-07  iOS/Android native modules BLE Manager (Swift + Kotlin)
2024-07-10  BLE cross-platform ...... Android + iOS BLE working
2024-07-29  V1.0.0 Android .......... Firebase, Google Auth, Apple Auth added
2024-08-02  V2.0.0 .................. Peripheral manager feature branch merged
2024-08-04  V2.x rapid iteration .... Expo Updates configured, CI/CD stabilized
2024-08-18  Unistyles introduced .... react-native-unistyles ^2.9.1
2024-09-01  Android SDK 34 .......... compileSdk/targetSdk bumped
2024-09-05  V3.x series ............. Alarm/disconnection rework, session replay
2024-09-20  V3.33.0 ................. Last Expo 51 release before naming reset
2024-10-11  CamdomApp 1.0.0 ......... Version naming reset (CamdomApp era)
2024-10-15  Google login removed ..... Firebase auth stripped
2024-11-07  1.0.2 ................... itusexexempt encryption added
2025-01-31  1.2.0 ................... Package encryption
2025-06-09  Android versions update .. compileSdk 36, Gradle update, expo-modules-core patch
2025-10-06  Workbranch merge ......... Version bumps to 3.34.0 (Expo 51 still)
2025-11-12  **MAJOR MIGRATION** ...... Expo 54, RN 0.82, React 19, Reanimated 4
2025-11-16  Migration stabilized ..... "it builds fuck", final fixes
```

---

## 2. React Native Version History

| Date | Commit | RN Version | React Version | Expo SDK | Notes |
|------|--------|------------|---------------|----------|-------|
| 2024-06-06 | `27d64d6` | 0.74.2 | 18.2.0 | ~51.0.11 | Initial scaffold (Expo create-template) |
| 2024-07-01 | `b1f54f3` | 0.74.2 | 18.2.0 | ~51.0.11 | + Skia, ReanimatedV3, GestureHandler |
| 2024-08-02 | `6078d0f` | 0.74.3 | 18.2.0 | ~51.0.11 | V2.0.0 - Peripheral manager merged |
| 2024-08-18 | `73b7478` | 0.74.3 | 18.2.0 | ~51.0.24 | + Unistyles ^2.9.1 |
| 2024-11-07 | `bfc816c` | 0.74.3 | 18.2.0 | ~51.0.24 | Stable Expo 51 build |
| 2025-06-09 | `010d6d7` | 0.74.3 | 18.2.0 | ~51.0.24 | Android SDK 36, still Expo 51 |
| 2025-10-06 | `c82e02d` | 0.74.3 | 18.2.0 | ~51.0.24 | Last pre-migration release |
| **2025-11-12** | `231cbb5` | **0.82.1** | **19.1.1** | **^54.0.23** | **Big bang migration** |
| 2025-11-16 | `23ef990` | 0.82.1 | 19.1.1 | ^54.0.23 | Migration stabilized |

### Key Observations

- The project stayed on **RN 0.74 + Expo 51** for 17 months (Jun 2024 -- Nov 2025).
- The migration to **RN 0.82 + Expo 54** happened in a single burst over 4 days (Nov 12--16, 2025).
- React jumped from **18.2.0 to 19.1.1** (major version bump).
- The commit messages during migration tell the story: `wip: almost alive babe` -> `working shit` -> `yaaay fita!` -> `it builds fuck` -> `final bitch - wip` -> `yaaay olddd`.

---

## 3. Expo SDK Evolution

### Phase 1: Expo 51 (Jun 2024 -- Nov 2025)

Initial SDK 51.0.11 with minimal plugins. Grew to include:

```json
{
  "plugins": [
    "expo-router",
    "expo-font",
    "expo-localization",
    "react-native-ble-plx",
    "expo-splash-screen",
    "expo-build-properties",
    "expo-haptics",
    "expo-updates"
  ]
}
```

Removed during cleanup: `expo-status-bar`, `expo-system-ui`, `expo-web-browser`, `expo-dev-client`, `expo-updates`.

### Phase 2: Expo 54 (Nov 2025 -- present)

Full SDK jump. Module versions jumped to Expo 54-compatible:

| Module | Expo 51 | Expo 54 |
|--------|---------|---------|
| expo | ~51.0.24 | ^54.0.23 |
| expo-router | ~3.5.20 | ~6.0.14 |
| expo-av | ~14.0.6 | ~16.0.7 |
| expo-font | ~12.0.9 | ~14.0.9 |
| expo-haptics | ~13.0.1 | ~15.0.7 |
| expo-constants | ~16.0.2 | ~18.0.10 |
| expo-splash-screen | ~0.27.5 | ~31.0.10 |
| expo-localization | ~15.0.3 | ~17.0.7 |
| expo-linking | ~6.3.1 | ~8.0.8 |
| expo-build-properties | ~0.12.4 | ~1.0.9 |

---

## 4. JSI Migration: Bridge to JavaScript Interface

### Why JSI Was Needed

CAMDOM is a BLE (Bluetooth Low Energy) consent protection app. The core loop requires:
- Real-time BLE peripheral advertising and central scanning
- Sub-second bidirectional packet exchange between paired devices
- Native AppleScript/Alarm integration on iOS
- Background BLE operation with WakeLock on Android

The React Native Bridge architecture adds ~5-10ms per native call due to JSON serialization. For BLE state machines handling 60-second polling intervals with alarm triggers, this latency compounds and causes disconnection race conditions.

### The Custom BLE Manager Module (Expo Modules API / JSI)

Located at `modules/ble-manager/`, this is a **custom Expo Module** (not a TurboModule, not a Bridge module) that uses the Expo Modules API with JSI bindings.

**Structure:**
```
modules/ble-manager/
  expo-module.config.json     # Platform registration
  index.ts                    # requireNativeModule('BleManager')
  src/
    BleManager.ts             # JS API surface
    BleManagerModule.ts       # requireNativeModule bridge
    BlePeripheralManager.ts   # Peripheral API
    Events.types.ts           # Type definitions
    Utils.ts                  # Helpers
  android/
    build.gradle              # Android build (compileSdk 36)
    src/main/java/p4b/modules/blemanager/
      BleManagerModule.kt     # Kotlin Expo Module
      BleManager.kt           # Central manager logic
      BlePeripheralManager.kt # Peripheral logic
  ios/
    BleManagerModule.swift    # Swift Expo Module
    BlePeripheralManager.swift
    BleManager.podspec
```

**Key JS interface** (`modules/ble-manager/src/BleManagerModule.ts`):
```typescript
import {requireNativeModule} from 'expo-modules-core';
// It loads the native module object from the JSI or falls back to
// the bridge module (from NativeModulesProxy) if the remote debugger is on.
export default requireNativeModule('BleManager');
```

This explicitly uses `requireNativeModule` which loads via JSI, bypassing the Bridge entirely. The fallback to `NativeModulesProxy` only activates during remote debugging.

**Module registration** (`expo-module.config.json`):
```json
{
  "platforms": ["ios", "android"],
  "ios": { "modules": ["BleManagerModule"] },
  "android": { "modules": ["p4b.modules.blemanager.BleManagerModule"] }
}
```

### Evolution of Native Module Architecture

| Phase | Date | Architecture | Commit |
|-------|------|-------------|--------|
| Definition | 2024-07-01 | `91c4be0` - Native Modules definition | Initial Expo Modules API types |
| Android config | 2024-07-08 | `c986dda` - Android native module config | Kotlin module registration |
| iOS config | 2024-07-08 | `5b98522` / `7a4664f` - iOS native module config | Swift module registration |
| BLE working | 2024-07-10 | `681eb80` - 0.1.6 ANDROID & iPhone BLE | Cross-platform BLE verified |
| Android scan | 2024-07-22 | `43d273a` - Android Scanning and connect | BLE scan + connect flow |
| Android 100% | 2024-07-22 | `68c2810` - Android Finally 100% | Full BLE peripheral + central |
| Peripheral merged | 2024-08-02 | `6078d0f` - V2.0.0 | Peripheral manager feature branch |
| New Arch enabled | 2025-11-12 | `231cbb5` | TurboModules + Fabric enabled |
| Nitro Modules added | 2025-11-16 | `23ef990` | react-native-nitro-modules ^0.31.4 |

---

## 5. TurboModules / New Architecture

### Activation

New Architecture was enabled during the Expo 54 migration (Nov 2025):

**`android/gradle.properties`:**
```properties
newArchEnabled=true
hermesEnabled=true
edgeToEdgeEnabled=true
```

**`MainActivity.kt`** references:
```kotlin
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled
import com.facebook.react.defaults.DefaultReactActivityDelegate
```

The activity delegates Fabric rendering via `fabricEnabled` flag from `DefaultNewArchitectureEntryPoint`.

**`MainApplication.kt`** uses the new React Native 0.82 initialization pattern:
```kotlin
import com.facebook.react.ReactNativeApplicationEntryPoint.loadReactNative
import com.facebook.react.common.ReleaseLevel

class MainApplication : Application(), ReactApplication {
  override fun onCreate() {
    super.onCreate()
    DefaultNewArchitectureEntryPoint.releaseLevel = ReleaseLevel.STABLE
    loadReactNative(this)
    ApplicationLifecycleDispatcher.onApplicationCreate(this)
  }
}
```

This is the RN 0.82+ `ReactNativeApplicationEntryPoint` pattern, replacing the older `SoLoader.init()` approach. The `ReleaseLevel.STABLE` flag indicates full New Architecture adoption.

### ReactHost (New Architecture)

```kotlin
override val reactHost: ReactHost by lazy {
    getDefaultReactHost(
      context = applicationContext,
      packageList = PackageList(this).packages,
      jsMainModulePath = ".expo/.virtual-metro-entry",
      useDevSupport = BuildConfig.DEBUG
    )
}
```

The `jsMainModulePath = ".expo/.virtual-metro-entry"` is the Expo 54 virtual entry point pattern.

### Nitro Modules

Added in the final migration commit (`23ef990`): `react-native-nitro-modules: ^0.31.4`. This provides高性能 native bindings as an alternative to TurboModules for specific use cases.

### ProGuard Rules (TurboModules)

```proguard
-keep class com.swmansion.reanimated.** { *; }
-keep class com.facebook.react.turbomodule.** { *; }
```

Both Reanimated and TurboModule classes are preserved from R8 minification.

---

## 6. Build System

### Gradle Configuration

**Root `android/build.gradle`:**
```groovy
ext {
    buildToolsVersion = "36.0.0"
    minSdkVersion = 24
    compileSdkVersion = 36
    targetSdkVersion = 36
    ndkVersion = "27.1.12297006"
}
```

**App `android/app/build.gradle`:**
```groovy
android {
    buildToolsVersion "36.0.0"
    compileSdk 36
    
    defaultConfig {
        multiDexEnabled true
        applicationId 'com.billyboy.condomapp'
        minSdkVersion 24
        targetSdkVersion 36
        versionCode 7777777
        versionName "7.7.7"
    }
}
```

The `versionCode`/`versionName` in build.gradle are **placeholder values** -- actual versions are injected by `scripts/version_bumper.js` at build time.

**Gradle Wrapper:** `gradle-8.14.3-bin.zip`

**Kotlin Gradle Plugin:** Applied via `classpath('org.jetbrains.kotlin:kotlin-gradle-plugin')`

### Expo CLI Integration in Gradle

```groovy
react {
    entryFile = file(["node", "-e", "require('expo/scripts/resolveAppEntry')", ...].execute().text.trim())
    cliFile = new File(["node", "--print", "require.resolve('@expo/cli', ...)"].execute().text.trim())
    bundleCommand = "export:embed"
    autolinkLibrariesWithApp()
}
```

The build uses Expo CLI (`@expo/cli`) for bundling instead of the standard React Native CLI. The `bundleCommand = "export:embed"` ensures Metro configuration from Expo is respected.

### Hermes Engine

Enabled by default:
```groovy
if (hermesEnabled.toBoolean()) {
    implementation("com.facebook.react:hermes-android")
} else {
    implementation jscFlavor
}
```

JSC fallback configured as `io.github.react-native-community:jsc-android:2026004.+`.

### Metro Bundler

Minimal configuration -- delegates entirely to Expo defaults:
```javascript
const {getDefaultConfig} = require('expo/metro-config');
const config = getDefaultConfig(__dirname);
module.exports = config;
```

### Babel

```javascript
presets: ['babel-preset-expo'],
plugins: [
    ['react-native-unistyles/plugin', { root: 'app' }],
    'react-native-reanimated/plugin',
]
```

Reanimated plugin is last (required by Reanimated docs). Unistyles Babel plugin processes files under `app/`.

### Expo Autolinking

```groovy
// settings.gradle
plugins {
    id("com.facebook.react.settings")
    id("expo-autolinking-settings")
}
expoAutolinking.useExpoModules()
expoAutolinking.useExpoVersionCatalog()
```

Uses Expo's own autolinking system, not the community `@react-native-community/cli` autolinking.

---

## 7. Patches Directory

### `expo-modules-core@1.12.24.patch`

**File:** `patches/expo-modules-core@1.12.24.patch`

**Problem:** Expo Modules Core's `PermissionsService.kt` had a null-safety issue on Android when targeting SDK 34+. The `requestedPermissions` field from `PackageInfo` became nullable in newer Android API levels.

**The fix (commit `672821d`, 2025-06-09):**
```diff
- return requestedPermissions.contains(permission)
+ return requestedPermissions?.contains(permission) ?: false
```

**Why it was needed:** When `compileSdkVersion` was bumped to 36, the Android SDK's `PackageInfo.requestedPermissions` field changed from `String[]` (non-null in Java) to `String[]?` (nullable in Kotlin). The Expo Modules Core library had not yet updated for this change, causing a Kotlin compilation error: `Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver`.

**Impact:** Without this patch, the entire Android build would fail. The patch was applied via `pnpm patch expo-modules-core` (standard pnpm patching mechanism).

**Commit:** `672821d` "add patch to expo-modules-core-permissions due to kotlin check"

---

## 8. Android SDK Evolution

| Date | Commit | compileSdk | targetSdk | minSdk | buildTools | Kotlin/Gradle | Notes |
|------|--------|------------|-----------|--------|------------|---------------|-------|
| 2024-06-06 | `27d64d6` | 34 | 34 | 24 | 34.0.0 | Kotlin plugin | Initial Expo prebuild |
| 2024-09-01 | `3bc4163` | 34 | 34 | 24 | 34.0.0 | Same | Explicit SDK 34 bump commit |
| 2025-06-09 | `010d6d7` | **36** | **36** | 24 | **36.0.0** | Updated | "update app to newer android versions" |
| 2025-11-12 | `231cbb5` | 36 | 36 | 24 | 36.0.0 | Same | Expo 54 migration |

### Key Changes

- **minSdkVersion 24** (Android 7.0 Nougat) -- maintained throughout the entire project lifecycle. This is the minimum for BLE peripheral mode on Android.
- **NDK version:** `27.1.12297006`
- **multiDexEnabled:** `true` -- required for Firebase + all native modules
- **Edge-to-edge:** Enabled in the final migration (`edgeToEdgeEnabled=true` in gradle.properties, `edgeToEdgeEnabled: true` in app.json)

---

## 9. iOS Configuration

### Podfile

The iOS configuration uses Expo's managed Podfile approach. No custom Podfile modifications were found in the repository -- the Podfile is generated by `expo prebuild`.

### Entitlements

No `.entitlements` files were found in the repository. iOS entitlements are managed through Expo's prebuild system and the `app.json` configuration.

### Background Modes

BLE background operation is configured via the `react-native-ble-plx` plugin in `app.json`:
```json
["react-native-ble-plx", {
    "isBackgroundEnabled": true,
    "modes": ["peripheral", "central"],
    "bluetoothAlwaysPermission": "Allow $(PRODUCT_NAME) to connect to other devices..."
}]
```

The `isBackgroundEnabled: true` setting triggers Expo prebuild to add `bluetooth-central` and `bluetooth-peripheral` background modes to the iOS `Info.plist`.

---

## 10. CI/CD

### GitHub Actions

The CI/CD pipeline evolved through multiple iterations:

**Phase 1 (Jul 2024):** `android_build_googleplay.yml` -- initial EAS Build workflow
**Phase 2 (Aug 2024):** EAS Update configured (`583bcb0`), Expo Updates auto-publish
**Phase 3 (Sep 2024):** AppCenter deploy added (`b5eab2e`)
**Phase 4 (Jun 2025):** New `main.yml` created (`4e07cd9`), modernized CI
**Phase 5 (Oct 2025):** Workbranch updates (`b75f182`)

### Version Bumping Strategy

Two-mode version bumper at `scripts/version_bumper.js`:

**Dev mode** (`pnpm version:android:dev`):
- Auto-increments `minor` version (e.g., `4.44.44` -> `4.45.44`)
- Increments `versionCode` by 1
- Non-interactive

**Final mode** (`pnpm version:android:final`):
- Interactive wizard -- prompts for `versionName` and `versionCode`
- Validates `versionCode > current versionCode` (Play Store requirement)
- Blocks build if validation fails

### Build Scripts

```json
{
    "android:fast": "pnpm expo run:android -- --active-arch-only -PreactNativeArchitectures=arm64-v8a",
    "build:android": "cd android && ./gradlew bundleRelease && cd ..",
    "release:android": "pnpm build:android && pnpm check:sdk-details && pnpm open-aab-folder",
    "release:android:dev": "pnpm version:android:dev && pnpm build:android && pnpm check:sdk-details && pnpm open-aab-folder",
    "release:android:final": "pnpm version:android:final && pnpm build:android && pnpm check:sdk-details && pnpm open-aab-folder"
}
```

The `android:fast` script builds only for `arm64-v8a` (development device), skipping x86/x86_64/armeabi-v7a architectures. The `check:sdk-details` script validates the output AAB file.

---

## 11. Dependency Highlights

### BLE & Connectivity

| Package | Version | Role | Evolution |
|---------|---------|------|-----------|
| `react-native-ble-plx` | ^3.5.0 | BLE central scanning + connection | ^3.2.1 -> ^3.5.0 (Expo 54 compat) |
| Custom `ble-manager` module | 0.6.0 | BLE peripheral advertising (JSI) | Expo Modules API, never changed architecture |
| `react-native-permissions` | ^4.1.5 | Runtime permission handling | Same version throughout |

### State & Storage

| Package | Version | Role | Evolution |
|---------|---------|------|-----------|
| `react-native-mmkv` | 4.0.0 | Key-value storage (fast) | ^2.12.2 -> 4.0.0 (Expo 54 compat) |
| `react-native-volume-manager` | ^2.0.8 | System volume control | Added in v2.18 era |

### UI & Animation

| Package | Version | Role | Evolution |
|---------|---------|------|-----------|
| `react-native-reanimated` | ~4.1.5 | Smooth animations, layout animations | ~3.10.1 -> ~4.1.5 (major version bump) |
| `react-native-gesture-handler` | ~2.28.0 | Touch gesture system | ~2.16.1 -> ~2.28.0 |
| `@shopify/react-native-skia` | 2.3.10 | Canvas rendering (background balls) | ^1.3.7 -> ^1.2.3 -> 2.3.10 (major bump) |
| `react-native-unistyles` | 3.0.17 | Runtime theming/styles | ^2.9.1 -> 3.0.17 (major version bump) |
| `react-native-screens` | ~4.18.0 | Native screen containers | 3.31.1 -> ~4.18.0 (major bump) |

### Navigation

| Package | Version | Role | Evolution |
|---------|---------|------|-----------|
| `expo-router` | ~6.0.14 | File-based routing | ~3.5.20 -> ~6.0.14 (major bump) |
| `@react-navigation/native` | ^7.1.19 | Navigation primitives | ^6.0.2 -> ^7.1.19 (major bump) |

### Audio & Haptics

| Package | Version | Role | Evolution |
|---------|---------|------|-----------|
| `expo-av` | ~16.0.7 | Audio playback (alarm sounds) | ~14.0.6 -> ~16.0.7 |
| `expo-haptics` | ~15.0.7 | Haptic feedback | ~13.0.1 -> ~15.0.7 |
| `react-native-snackbar` | ^2.6.2 | Toast notifications | Same version throughout |

### Device Info & Utilities

| Package | Version | Role | Evolution |
|---------|---------|------|-----------|
| `react-native-device-info` | ^11.1.0 | Device metadata | Same version throughout |
| `react-native-nitro-modules` | ^0.31.4 | High-perf native bindings | **Added in Expo 54 migration** |
| `i18next` / `react-i18next` | ^23.12.2 / ^15.0.0 | Internationalization | Same versions throughout |

### Removed During Migration

| Package | Last Seen | Reason |
|---------|-----------|--------|
| `react-native-firebase/*` | Expo 51 era | Firebase auth removed (Oct 2024) |
| `@react-native-google-signin/google-signin` | Expo 51 era | Google login removed (Oct 2024) |
| `@invertase/react-native-apple-authentication` | Expo 51 era | Apple auth removed |
| `expo-dev-client` | Expo 51 era | No longer needed in Expo 54 |
| `expo-status-bar` | Expo 51 era | Deprecated/merged |
| `expo-system-ui` | Expo 51 era | Deprecated/merged |
| `expo-web-browser` | Expo 51 era | Not used |
| `react-native-awesome-slider` | Expo 51 era | Replaced or removed |
| `react-native-keyboard-controller` | Expo 51 era | Replaced or removed |
| `react-native-quick-base64` | Expo 51 era | Replaced or removed |
| `react-native-get-random-values` | Expo 51 era | Polyfill no longer needed |
| `expo-updates` | Expo 51 era | Removed from dependencies |

---

## 12. Migration Challenges

### Expo 51 -> 54 Migration (Nov 12--16, 2025)

This was the largest migration in the project's history. Evidence from commit messages and diffs:

**Day 1 (Nov 12) -- "the painful day":**
- `4aa6cfe` "version bumps" -- Initial dependency updates
- `aeaf642` "bump one version yaay" -- Version bump after first successful change
- `231cbb5` "working shit" -- First build that compiled
- `d822683` "yaaay fita!" -- Breakthrough moment
- `5efba89` "update splash" -- expo-splash-screen config changed (0.27 -> 31.x)
- `b19cdc4` "final bitch - wip" -- Still fixing issues
- `d94d64c` "it builds fuck" -- Finally building

**Day 2 (Nov 14):**
- `1ac485c` "latex" -- Unknown but likely asset-related

**Day 3 (Nov 16) -- "cleanup day":**
- `259fb54` "idk" -- Confusion during cleanup
- `bef7ef5` "update versions" -- Version reconciliation
- `57487ad` "betterscripts" -- Script improvements
- `c379064` "android 6" -- Android build number 6
- `8db976f` "wip" -> `3c21891` "yup" -> `988ca99` "idk bro" -> `23ef990` "yaaay olddd" -- Final stabilization

**What broke:**
1. **Reanimated 3 -> 4**: Major API changes. The project was using Reanimated 3.10.1; Reanimated 4 has breaking changes in layout animations and shared element transitions.
2. **Unistyles 2 -> 3**: Major version bump with new plugin API (`react-native-unistyles/plugin` with `root` option).
3. **Skia 1.x -> 2.x**: Complete API overhaul for `@shopify/react-native-skia`.
4. **expo-splash-screen 0.27 -> 31.x**: The splash screen API changed dramatically (now `SplashScreenManager.registerOnActivity(this)` pattern in Kotlin).
5. **React 18 -> 19**: New rendering behavior, potential breaking changes in hooks.
6. **expo-router 3 -> 6**: File-based routing API changes.
7. **MMKV 2.x -> 4.0**: Storage API changes.
8. **MainApplication.kt rewrite**: New `ReactNativeApplicationEntryPoint.loadReactNative()` pattern replaced `SoLoader.init()`.
9. **Firebase/Google auth removal**: The entire auth stack was stripped, simplifying the dependency tree but requiring code removal.
10. **expo-modules-core patch**: The null-safety fix for Android SDK 36 compatibility was carried forward.

### Earlier Migration Challenges

**V1 -> V2 (Jul-Aug 2024):** The Peripheral Manager feature branch (`feature/peripheral-manager`) required three Android build fix commits (`0c38e44`, `45dc77c`, `63af0dd`) before merging. BLE peripheral mode on Android required careful handling of `BluetoothGattServer` lifecycle.

**Android SDK 34 bump (Sep 2024):** Required version matching across all CI steps (`51c5d7c` "Ensure Android Versions matching in all steps + SetupGradle Action before using gradle").

**Expo Updates crashes (Sep 2024):** Multiple crash-fix iterations: ExoPlayer crash (`a8c0c8c`), Android crash (`aa21d5a`), Expo Updates on Android (`ff44afa`). The rapid 2.x -> 3.x version progression (v2.47.3 -> v3.33.0 in one day) indicates aggressive hotfixing.

---

## 13. Current State Summary

| Aspect | Value |
|--------|-------|
| React Native | 0.82.1 |
| React | 19.1.1 |
| Expo SDK | 54 |
| TypeScript | ~5.9.3 |
| Package Manager | pnpm 9.6.0 |
| Android compileSdk | 36 |
| Android targetSdk | 36 |
| Android minSdk | 24 |
| Gradle | 8.14.3 |
| NDK | 27.1.12297006 |
| New Architecture | Enabled (Fabric + TurboModules) |
| Hermes | Enabled |
| Edge-to-edge | Enabled |
| JSI | Custom BLE Manager (Expo Modules API) |
| Nitro Modules | ^0.31.4 (added Nov 2025) |
| App version | 4.44.44 (app.json) / 7.7.7 (build.gradle placeholder) |
| Package ID | com.billyboy.condomapp |
| Patches | expo-modules-core@1.12.24.patch (null-safety fix) |
| CI/CD | GitHub Actions (main.yml) |
| Version management | Custom version_bumper.js (dev + final modes) |

---

## References

- **Commit `27d64d6`**: Initial commit (2024-06-06)
- **Commit `91c4be0`**: Native Modules definition (2024-07-01)
- **Commit `6078d0f`**: V2.0.0 - Peripheral manager merged (2024-08-02)
- **Commit `3bc4163`**: Android SDK 34 bump (2024-09-01)
- **Commit `7c1ec63`**: CamdomApp 1.0.0 version reset (2024-10-11)
- **Commit `672821d`**: expo-modules-core patch (2025-06-09)
- **Commit `010d6d7`**: Android SDK 36 update (2025-06-09)
- **Commit `231cbb5`**: Expo 54 migration begins (2025-11-12)
- **Commit `d94d64c`**: "it builds fuck" - first successful build (2025-11-12)
- **Commit `23ef990`**: Migration stabilized (2025-11-16)

---

*This document is a living reference. As new migrations occur, update the timeline and tables accordingly.*
