Two native apps in. One Flutter plan out.
Converge reads your iOS and Android code and plans your add-to-app move to Flutter.
It tells you how long it takes, what it costs and who does it, every sprint.
| Android | iOS | Wave | Days | Developers |
|---|---|---|---|---|
| SettingsActivity.kt | SettingsViewController.swift | Wave 1 | 4 days | 1 developer |
| OnboardingFragment.kt | OnboardingView.swift | Wave 1 | 3 days | 1 developer |
| ProfileFragment.kt | ProfileView.swift | Wave 2 | 6 days | 2 developers |
| ReferralsFragment.kt | Android only | Wave 2 | 3 days | 1 developer |
| CheckoutActivity.kt | CheckoutViewController.swift | Wave 3 | 9 days | 2 developers |
Even add-to-app goes wrong when decisions are made away from the code
Nobody can say how long, or what it costs
Every team gives a different estimate, and the board can't budget around any of them.
Nobody knows what the apps contain
Hundreds of screens, no docs, and two platforms that drifted apart.
The team doesn't know Flutter yet
Your iOS and Android developers learn it on the hardest kind of project.
The app can't stop shipping
New features keep landing while screens move to Flutter.
What you receive
A plan computed from your code that you can show the board, and that keeps up with the migration sprint by sprint.
A map of both apps
Every Android screen paired with its iOS twin, and the ones only one app has.
A plan in waves
Which screens move together and in what order, the simplest first.
A date and a team per wave
An estimate, a date and the people for each wave, from your code.
Progress every sprint
What's already in Flutter, what's left and when it reaches 100%.
The plan Converge computed for Signal
Signal is open source, so its Android and iOS apps make a fair public test. Converge read both codebases and split the move into waves.
- screens to move
- 232
- of them in one app only (38 Android, 6 iOS)
- 44
- waves, each shipped on its own
- 39
- working days with 7 developers
- 226
The first 12 of 39 waves, one tile per working day. With 7 developers working in parallel, several waves run at once. The simplest screens go first, while the team learns Flutter.
Computed from the public Signal-Android and Signal-iOS repositories on GitHub.
Wave 1: Chat colours and wallpaper
- Weeks
- 1–3
- Screens
- 5
- The chat appearance entry: the live preview, the colour and wallpaper rows and the reset actions.Android + iOS
- The grid of built-in wallpapers plus the entry for picking a photo.Android + iOS
- The full-screen wallpaper preview behind a mock conversation, before it is applied.Android + iOS
Wave 2: Sticker library
- Weeks
- 1–2
- Screens
- 2
- The sticker library: the installed packs, the ones available and the ones received but not installed.Android + iOS
- One sticker pack before it is installed: its cover, its grid and the install action.Android + iOS
Wave 3: Appearance and app icon
- Weeks
- 1–4
- Screens
- 3
- Appearance: the theme, the chat colour and wallpaper entry, the app icon, and on Android also language and text size.Android + iOS
- The grid of alternative app icons.Android + iOS
- The explainer of what changing the app icon does.Android + iOS
Wave 4: Safety numbers
- Weeks
- 1–4
- Screens
- 2
- The safety number of one contact: the QR code, the digits, marking it verified and sharing it.Android + iOS
- The camera step of safety-number verification.Android + iOS
Wave 5: Contact cards
- Weeks
- 1–3
- Screens
- 2
- The details of a contact card received in a chat, with the actions that make sense for that person.Android + iOS
- Trimming a contact card before it is sent: every phone, email and address as a tickable row.Android + iOS
Wave 6: Camera, gallery and sending media
- Weeks
- 2–6
- Screens
- 8
- The container of the whole attach-and-send-media flow, from capture or gallery through editing to the destination.Android + iOS
- The in-app camera with its photo and video modes, and the text-story composer it crossfades to.Android + iOS
- The review-and-edit step before media is sent: a pager over the items with the editing tools and the send bar.Android + iOS
Wave 7: Help and the debug log
- Weeks
- 2–3
- Screens
- 3
- The help page: the support centre, contact us, the debug log, the licences and the app version.Android + iOS
- The contact-us form: the description, the category, the mood and the debug-log switch, handed to the mail client.Android + iOS
- The debug log itself, shown before it is submitted, with the submission and the save-to-file paths.Android + iOS
Wave 8: Privacy, blocking and app lock
- Weeks
- 3–7
- Screens
- 9
- Privacy: phone-number privacy, blocked people, receipts, the default timer, app security and the payment lock.Android + iOS
- Who sees the phone number and who can find the account by it.Android + iOS
- Advanced privacy: censorship circumvention, the proxy entry, call relaying and the sealed-sender switches.Android + iOS
Wave 9: Media viewer and a chat’s media library
- Weeks
- 3–8
- Screens
- 5
- The media viewer: swipe between a conversation's attachments, play them, and share, forward, save or delete.Android + iOS
- One page of the media viewer showing a zoomable attachment.Android + iOS
- The container of a conversation's media library, with its media, documents, audio and links tabs.Android + iOS
Wave 10: Data and storage
- Weeks
- 4–11
- Screens
- 2
- When media downloads automatically, the sent media quality and the network-shaped settings.Android + iOS
- The storage page: what media takes up, the optimize-storage switch and the chat-trimming controls.Android only
Wave 11: Chats and chat folders
- Weeks
- 4–7
- Screens
- 4
- Chat-wide preferences: link previews, contact photos, keeping muted chats archived and the export action.Android + iOS
- The chat-folder list, with reordering, deletion and the suggested folders.Android only
- The folder editor: its name, the chats it includes and excludes, and its filters.Android only
Wave 12: Notification profiles
- Weeks
- 4–8
- Screens
- 7
- The entry point for notification profiles: the empty state or the list with the active one described.Android only
- Naming a notification profile and picking its emoji.Android only
- Picking who may still notify while a notification profile is on.Android only
Your apps, planned the same way.
What we've learned from production migrations
LeanCode's add-to-app guidelines, from deciding whether to migrate to wiring up the native-Flutter boundary.
- What is Flutter add-to-app?How embedding Flutter in a native app lets you adopt Flutter gradually, without a full rewrite.(opens in a new tab)
- When should you consider Flutter add-to-app?When add-to-app pays off, and when a full rewrite is the better call.(opens in a new tab)
- Planning the migration to FlutterHow to pick the first screen, roll out in phases and plan the exit to a pure Flutter app.(opens in a new tab)
- Native-Flutter communicationMethod channels, Pigeon or FFI: how to move data across the native-Flutter boundary.(opens in a new tab)
- EmbeddingFlutter views inside native screens and native views inside Flutter: how each works, what it costs, and what we suggest trying before you commit to either.(opens in a new tab)
- Project structureMonorepo, polyrepo, or git submodules: where the Flutter module, the native hosts, and shared code live.(opens in a new tab)
Questions teams ask before a demo
See the migration plan for your apps

Marcin Chudy
Senior Flutter Developer at LeanCode
Leave your details and we'll email you to pick a time for the demo.