Ten Years on Cordova, Then a Rewrite: Migrating a Production Dating App to React Native
Around 2016, we shipped the mobile apps for Mignonne, our dating platform for French-speaking markets, as a hybrid built on AngularJS 1.x, Ionic v1, and Cordova. It was the pragmatic choice at the time: one codebase, two stores, and a WebView that let a small team move fast.
That stack stayed in production for roughly a decade. It aged better than its reputation suggests — but by the mid-2020s the writing was on the wall. AngularJS was long past end-of-life, the Ionic v1 ecosystem had evaporated, and every OS release meant another round of WebView quirks and plugin archaeology. Incremental migration paths existed on paper; in practice, none of them were worth the effort for a framework generation that far back.
So in 2026 we rebuilt the apps from the ground up on Expo and React Native, using React 19 and Expo Router.
What the rebuild covered
The goal was feature parity, not reinvention. The new apps re-implement the screens our members already knew — browsing and discovering profiles, real-time private messaging, account and subscription management — as native UI instead of a WebView.
Under the hood, the important continuity was the backend. The new clients authenticate with JWT against the same PHP/Swoole API that powers our web experience, and real-time messaging rides the same WebSocket infrastructure. Keeping the server contract stable meant the migration was contained to the client layer, and web, iOS, and Android stayed on one API surface.
The parts that changed the most were the ones the WebView used to abstract away:
- Push notifications moved to Expo's notification pipeline.
- In-app purchases were rebuilt on the modern store APIs — StoreKit 2 on iOS and Play Billing on Android — replacing plugin-era billing code.
- Over-the-air updates for the JavaScript layer let us ship fixes quickly without waiting on store review for every patch.
Shipping it as an upgrade, not a new app
We deliberately released the rewrite as a version upgrade of the existing store listings rather than as a new app. That preserved our reviews, our install base, and our members' muscle memory — but it imposed real constraints: signing-key continuity on Android, monotonically increasing version codes, and a staged rollout so we could watch vitals before the new binary reached everyone.
It is worth stating plainly: replacing the entire client technology inside an existing listing is very doable, but the operational details (keys, version codes, rollout percentages) deserve as much planning as the code.
What we learned
Native platform behaviors are not WebView behaviors. The subtlest issues came from things the old hybrid never exposed us to. Native autofill and password managers interact with login forms differently than a WebView ever did, and assumptions baked into a decade-old auth flow surfaced quickly once real devices started autofilling fields we didn't expect.
A forced re-login is an audit of your account edge cases. When an app generation changes, sessions don't carry over, and every dormant account, forgotten password, and stale email address shows up at once. Budget support time for the login wave, and make sure your password reset flow is bulletproof before release day.
Store policy modernization rides along. A rewrite is also the moment the stores look at you with fresh eyes. Data-safety declarations, privacy manifests, billing API deprecations — ten years of accumulated policy evolution all lands in the same review cycle. Treat compliance work as part of the migration scope, not an afterthought.
Was it worth it?
Yes. The new apps are faster, feel native because they are, and sit on a stack with an actual future. More importantly, the migration proved the value of the architecture decision we made ten years ago and kept ever since: a stable, well-defined API boundary. Clients come and go; the contract endures.