Flutter
Flutter's own-the-rendering-engine philosophy, Dart, widgets, where it beats React Native, and the tradeoffs of not using native widgets.
Flutter
In one line: Flutter takes the opposite approach to React Native — instead of using the platform's native widgets, it ships its own high-performance rendering engine and draws every pixel itself, which buys pixel-identical UI across iOS, Android, web, and desktop at the cost of not being "native widgets" and requiring you to learn Dart.
React Native uses the phone's real UI controls; Flutter brings its own. Flutter includes a rendering engine (Skia/Impeller) that paints the entire interface directly onto a canvas, so a Flutter button isn't an iOS button or an Android button — it's Flutter's own button, drawn by Flutter, looking exactly the same everywhere. That's the core tradeoff in one sentence: you get total control and perfect consistency across every platform (and very smooth animations, because Flutter owns the whole pipeline), but you give up automatic native look-and-feel and you write in Dart, Google's language, instead of JavaScript/TypeScript. Flutter is Google's framework, it's mature and popular, and for teams without an existing React investment — or for design-heavy apps that want a precisely-controlled custom look on every platform — it's often the better cross-platform pick.
The "own the pixels" philosophy
Everything in Flutter is a widget (composed in a tree, conceptually similar to React components), but the crucial architectural difference is what those widgets become: Flutter doesn't hand off to native UI; it renders them itself via its engine. The consequences flow directly from that:
- ✅ Pixel-perfect consistency. The app looks identical on iOS, Android, web, and desktop, because Flutter — not the OS — draws it. No "it looks slightly off on Android" surprises.
- ✅ Smooth, controllable animation/UI. Owning the rendering pipeline means high, consistent frame rates and total design freedom — great for branded, custom, animation-rich interfaces.
- ✅ One codebase, many targets. iOS, Android, web, Windows, macOS, Linux from the same code (mobile is by far the most mature).
- ⚠️ Not native widgets. It mimics platform look-and-feel (Material/Cupertino widget sets) very well, but it's a re-creation; brand-new OS UI elements aren't automatically yours, and some users/purists notice the difference.
- ⚠️ Dart. A clean, capable language — but one most web developers don't already know, so there's a real learning cost and a smaller hiring pool than JavaScript.
// A Flutter counter — widgets composed in Dart. Note the declarative, React-like shape.
import 'package:flutter/material.dart';
class Counter extends StatefulWidget {
const Counter({super.key});
@override
State<Counter> createState() => _CounterState();
}
class _CounterState extends State<Counter> {
int count = 0;
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Count: $count', style: const TextStyle(fontSize: 24)),
ElevatedButton(
onPressed: () => setState(() => count++), // setState ≈ React's state update
child: const Text('Increment'),
),
],
);
}
}
The structure will feel familiar to a React developer (declarative, stateful widgets, a build method like render) — the conceptual leap is small; the language and the rendering model are the new parts.
Both are excellent, mature, production-proven cross-platform frameworks — plenty of huge apps ship on each. Benchmarks rarely decide it; for typical product apps both are fast enough. The honest deciding factors:
- Existing skills. A React/TypeScript team is already most of the way to React Native; adopting Flutter means learning Dart and a new ecosystem. This alone points most web teams to RN.
- UI philosophy. Want the app to adopt each platform's native feel with minimal effort? Lean React Native. Want a precisely controlled, identical, custom-branded look on every platform with buttery animations? Lean Flutter.
- Code/skill reuse with your web app. RN shares a language (and some code) with a React web frontend; Flutter is its own world (though Flutter Web exists).
- Targets beyond mobile. Flutter's single-codebase reach into desktop is more mature today.
So the question isn't "which is better" but "do we already know React (→ RN), and how much do we value identical custom UI everywhere (→ Flutter)?" Both are right answers for different teams.
When Flutter is the pick
Choose Flutter when: you have no existing React investment (so RN's skill-reuse advantage doesn't apply and you're choosing on merits); you want a highly custom, brand-consistent UI rendered identically across platforms; you value smooth, complex animations and full design control; or you want one codebase spanning mobile + desktop. Lean the other way (RN) when your team and product are already React/TypeScript — the leverage usually wins. And as always, if you don't truly need a native app at all, revisit the PWA option first.
Common mistakes
- Picking Flutter while sitting on a big React/TS investment. You forgo RN's skill-and-code reuse and pay to learn Dart. For React teams, that's usually the wrong trade unless UI-consistency needs are strong.
- Expecting truly native widgets. Flutter draws its own; it mimics platform UI well but it isn't the OS's controls. Usually fine, occasionally noticeable — know which your product cares about.
- Underestimating the Dart learning curve / hiring pool. Dart is pleasant but unfamiliar to most web devs, and the talent pool is smaller than JavaScript's. Factor it into team planning.
- Choosing on micro-benchmarks. Both Flutter and RN are fast enough for the vast majority of apps. Decide on team skills, UI philosophy, and reuse — not synthetic numbers.
- Forgetting the PWA question. If you don't need store presence or deep device access, a PWA may beat any cross-platform framework on cost and update speed.
Page checkpoint
Did Flutter stick?
RequiredWhat's next
→ Continue to PWAs & offline — before committing to any native framework, how far can a web app alone take you?