Case study

Modernizing a live cross-platform app without breaking its identity

Rebuilt Adventure Cache from Xamarin.Forms into a .NET 10 MAUI single project for iOS and Android while preserving its store identity and offline-first field workflows.

Stack
  • .NET 10
  • .NET MAUI
  • SQLite
  • iOS & Android
  1. Situation

    The repository contained a Xamarin.Forms 5 application with separate Android and iOS projects. Adventure Cache already had production listings, package identity, local data, and API behavior, so the migration could not be treated as a clean rewrite.

  2. Constraints

    The package and bundle identifier, signing continuity, store update paths, offline field records, synchronization queue, and map-first product behavior all had to survive while Android and iOS retained independent release risks.

  3. Decision

    Make the MAUI single-project application the active target, retain the legacy projects as parity references, centralize local state around SQLite and queued synchronization, and validate signed and store-delivered artifacts separately on physical Android and iOS devices.

  4. Tradeoff

    The migration was not a transparent framework swap. Production rounds exposed Android startup/AOT and first-install database issues, followed by an iOS first-launch failure in App Store version 20.1.

  5. Outcome

    Android corrections were promoted through Google Play, and App Store version 20.2 corrected the iOS first-launch crash with linker and startup hardening. Adventure Cache remains live on both stores with its original production identity.

  6. Retrospective

    Debug builds and existing-database checks were not enough. The release process now treats fresh installation, first launch, signed-artifact inspection, and store-delivered physical-device validation as explicit gates.

Detail

The difficult part was preserving continuity, not simply reaching a successful local build. A production mobile identity includes package identifiers, signing, local data, upgrade behavior, store metadata, and the first-launch path that routine developer-device testing may not reproduce.

So the story includes the failures. Version 20.1 exposed a first-launch issue after delivery; version 20.2 fixed it. The lasting outcome is the release discipline that came out of that round: fresh installs and the store-delivered artifact are now test targets in their own right.

The rebuilt app, with Android and iOS released and checked separately.
Diagram as text

Parts

  • Xamarin.Forms 5 app: separate Android and iOS projects
  • MAUI single project: the active target
  • Local state: SQLite and queued sync
  • Android
    • Signed artifact: inspected
    • Google Play: store delivery
    • Physical device: fresh install, first launch
  • iOS
    • Signed artifact: inspected
    • App Store: store delivery
    • Physical device: fresh install, first launch

Connections

  • Xamarin.Forms 5 app to MAUI single project (parity reference)
  • MAUI single project to Local state
  • MAUI single project to Signed artifact
  • MAUI single project to Signed artifact
  • Signed artifact to Google Play
  • Google Play to Physical device
  • Signed artifact to App Store
  • App Store to Physical device
The Sync Queue on an iPhone: everything is synced and the queue is clear, the phone is online and ready to sync but not signed in, and a Local Storage card notes that queued drafts stay on the device until they sync.
Adventure Cache’s offline sync queue, from its current App Store listing.

Next case study: Turning one product’s knowledge into answers for product, QA, and developers