Web and app development in 2020 has converged around a simple idea: build one team, one backend, and one design system, and ship to as many surfaces as your users expect. For most projects we scope today, that means a cross-platform mobile framework — Flutter or React Native — sitting alongside a responsive web app or progressive web app, all sharing a single REST or GraphQL API. The three-team model (separate iOS, Android, and web squads) is no longer the default, and the economics explain why.
Advisory Apps has been building web and mobile products from Kuala Lumpur since 2012. Across 160+ projects, this is the pattern we reach for first.
Why Did Cross-Platform Win in 2020?
Cross-platform won because the trade-offs finally tilted. Five years ago, “hybrid” apps felt like compromise — janky scrolling, mismatched UI, painful debugging. In 2020 the frameworks are mature enough that most business apps are indistinguishable from native to the user, and the savings on the engineering side are real.
- Single codebase covers iOS and Android, with shared business logic and often 80–90% shared UI.
- One design system reduces review cycles, QA time, and long-term maintenance drift.
- Faster iteration — hot reload and over-the-air update tooling compress the feedback loop from days to seconds.
- Smaller teams — two strong cross-platform engineers can do what used to take four native ones.
The remote work shift driven by this year’s pandemic has amplified the advantage. Distributed teams are easier to run on one codebase than three.
Flutter or React Native — How Do They Compare Right Now?
Both are credible cross-platform options, but our team reaches for Flutter first on greenfield projects. Here is how they stack up side by side, then why Flutter has become our default.
| Dimension | Flutter | React Native |
|---|---|---|
| Language | Dart — single language across UI, business logic, and platform glue | JavaScript / TypeScript — but native code lives behind a JS bridge |
| UI approach | Renders its own widget tree via Skia — pixel-perfect and identical across iOS and Android | Bridges to native components — inherits native look but UI can drift between platforms |
| Stable since | Flutter 1.0 shipped end of 2018; 1.22 is the latest stable (Oct 2020) and feels genuinely production-ready | Stable since 2016, mature and widely deployed |
| Best for | Design-led apps, consistent UI, teams that want a single-language codebase | Teams with strong existing React / JS talent and shared web components |
| Ecosystem | Smaller but fast-growing pub.dev — curated, fewer surprises on upgrade | Massive npm library pool, but churn and breaking changes every few releases |
| Debugging | One language, one runtime, predictable stack traces across the whole app | JS-to-native bridge makes crashes hard to trace; Flipper (RN 0.62+) helps but the bridge adds real complexity |
| Web output | Flutter for Web (beta channel) — promising but not production-ready yet | React Native Web (maturing) |
Flutter is our default choice for new cross-platform projects today. The single-language, single-runtime model makes Flutter builds feel more predictable: one stack trace, one debugger, one set of upgrade notes to follow. Flutter 1.22’s October 2020 release brought Material Design improvements, iOS widget refinements, and real performance gains, and it tipped the balance for us on greenfield work.
React Native still has a place, and we reach for it when a client team already has deep React talent or when the app needs to reuse components with an existing React web front-end. But it comes with trade-offs that buyers should go in eyes-open about:
- Ecosystem volatility — npm packages deprecate often, and major React Native upgrades routinely break community dependencies. Upgrading a React Native app between major versions is a project in itself, and large codebases can fall behind quickly.
- The JavaScript bridge is hard to debug — when a crash happens on the native side of the bridge, stack traces cross language and runtime boundaries, and reproducing issues locally can take hours. Flipper (shipped with React Native 0.62 in March 2020) has helped, but the bridge still adds complexity that Flutter’s model avoids entirely.
- Performance edges — long lists, complex animations, and background work can hit JS bridge bottlenecks. Hermes has improved Android runtime performance since 2019, but you still need to care about it where Flutter developers simply do not.
Ionic is still in the conversation for teams already on Angular or Vue, especially where the app is essentially a wrapped web experience with a few native bridges. It is not our default, but it fits a specific niche well.
How Do Web and Mobile Share a Backend?
A shared backend is where the cross-platform story goes from “nice to have” to “essential”. The pattern we ship most often in 2020:
- API layer — REST with OpenAPI specs, or GraphQL where client queries vary a lot between surfaces.
- Auth — JWT or OAuth2 with refresh tokens, shared between web and mobile clients.
- Shared domain models defined once, consumed by TypeScript on the web and by generated clients on mobile.
- Cloud hosting — AWS, Azure, or Google Cloud, with Southeast Asia regions for Malaysian latency.
- CI/CD — separate pipelines per target, triggered off one monorepo or closely-linked repos.
GraphQL is particularly well-suited to multi-surface products because each client can ask for exactly the fields it needs. A web dashboard pulling rich data does not force a mobile client to over-fetch.
For teams mapping out their full stack strategy, our web application development service and mobile app development service describe how we plan, scope, and staff these unified builds.
Where Do Progressive Web Apps Fit In?
A progressive web app (PWA) is the right answer when you need fast reach without App Store friction. PWAs load in the browser, work offline via service workers, and can be “installed” to the home screen without going through review. They are excellent for:
- Internal business tools where you control the device policy and do not need store presence.
- Content and media products where discoverability via search matters more than app store visibility.
- Emerging market reach where users are on entry-level Android and do not want to spend 30 MB on an install.
PWAs do not replace native or cross-platform mobile apps for every use case — push notifications, deep hardware access, and store visibility still matter for consumer brands. But they are an increasingly common first step for teams who want to validate a product with web users before committing to a full mobile build.
What About Teams That Still Ship Native?
Native iOS (Swift, UIKit, and the newer SwiftUI for greenfield screens) and native Android (Kotlin with the Android Jetpack libraries) are still the right call for a specific kind of project: heavy camera and AR, complex background services, tight integration with platform-specific hardware, or apps where every millisecond of animation matters. If you are building a consumer photo app that competes on frame rate, go native.
For the other 80% of business apps — dashboards, marketplaces, booking, ordering, CRM — cross-platform gets you there faster with a smaller team and a cleaner long-term maintenance story.
Talk to Us
If you are planning a web and mobile product and want to work through the stack choice with engineers who have shipped on all of them, book a free consultation. Advisory Apps has been helping Malaysian teams pick the right technology for the right problem since 2012, and we will give you an honest recommendation even if it does not match what you walked in expecting.