# React Native (Expo) vs Flutter for a SaaS mobile app

> React Native vs Flutter for a SaaS phone app: language, rendering, Supabase, over-the-air updates, store builds and code shared with Next.js.

Source: https://www.shipanysaas.com/blog/react-native-vs-flutter
Published: 2026-10-18 · Updated: 2026-10-18

React Native vs Flutter comes down to language and rendering. React Native, usually through Expo, runs JavaScript or TypeScript and draws the platform's own views; Flutter runs Dart and paints its own widgets. Both build iOS and Android apps from one codebase. If your web app is Next.js and TypeScript, Expo lets both apps share code and one backend.

A note before the details: this blog belongs to shipanysaas, whose All-in plan includes an Expo app, so read with that in mind. Every fact about React Native, Expo and Flutter below comes from their own docs, checked on 18 October 2026, and there is a section on where Flutter is the better pick.

## React Native vs Flutter at a glance

| | React Native with Expo | Flutter |
| --- | --- | --- |
| Language | TypeScript (the default for new projects) or JavaScript, with React | Dart |
| How the UI is drawn | Creates the platform's own iOS and Android views at runtime | Its own widgets, painted by the Impeller renderer |
| Release code | JavaScript run by Hermes, React Native's default engine | Compiled to machine code |
| Code shared with a Next.js app | Types, Zod schemas, API helpers, supabase-js and React skills | None directly: Dart can't import your TypeScript |
| Web | Expo's web target, with static rendering in Expo Router | Flutter web, which its docs steer away from text-heavy pages |
| Supabase client | supabase-js, with an official Expo quickstart | supabase_flutter, Supabase's official Flutter library |
| Over-the-air updates | EAS Update: JavaScript, styling and images | Shorebird, a third-party service: Dart code |
| Cloud store builds | EAS Build, with iOS builds on Expo's macOS machines | No first-party service; CI tools such as Codemagic, Bitrise or fastlane |
| Platforms | iOS, Android and the web | iOS, Android, the web, Windows, macOS and Linux |
| Packages | npm | pub.dev |

## What is the difference between React Native and Flutter?

React Native maps your components onto the platform's own UI controls, while Flutter draws every control itself. The language follows from that choice: React Native is React, Flutter is Dart.

React Native's docs explain that at runtime it "creates the corresponding Android and iOS views" for your components, so a `<View>` becomes a `UIView` on iPhone and a `ViewGroup` on Android. Because they are the platform's own views, the docs say React Native apps "look, feel, and perform like any other apps". New React Native projects use TypeScript by default.

Flutter takes the opposite route. Its [architectural overview](https://docs.flutter.dev/resources/architectural-overview) says Flutter "has its own implementations of each UI control, rather than deferring to those provided by the system", and that release builds are "compiled directly to machine code". Because Flutter draws the controls rather than the operating system, a screen looks the same on every device.

## Expo vs Flutter: is Expo the same as React Native?

Expo is a framework built on React Native, and it is the way React Native's own docs suggest you start. The [React Native setup guide](https://reactnative.dev/docs/environment-setup) says: "if you're building a new app with React Native, we recommend using a Framework", and names Expo.

So "Expo vs Flutter" and "React Native vs Flutter" are mostly the same question. Expo adds what a bare React Native project leaves to you: file-based routing with Expo Router, a standard library of native modules, config plugins that change native code without hand-editing Xcode or Gradle files, and hosted services for builds and updates. When you need a native feature Expo doesn't cover, its Modules API lets you write it in Swift and Kotlin.

## Can a phone app share code with a Next.js web app?

With Expo, yes: anything that isn't UI can be the same file in both apps. With Flutter, no, because Dart can't import TypeScript, so shared rules get written twice.

What a TypeScript monorepo can share between a Next.js app and an Expo app:

- **Types.** The database types Supabase generates, API response shapes, enums.
- **Validation.** One Zod schema checks a form on the phone and the same request on the server.
- **Data access.** supabase-js runs in both, and so do query helpers and cache keys.
- **Copy.** Interface strings can come from one set of message files.

Screens are the exception. A Next.js page renders HTML elements and an Expo screen renders React Native components, so you write each interface separately, but in the same language, with the same patterns and the same tooling.

Flutter can build for the web, and that matters if you hoped to skip Next.js. Flutter's [web docs](https://docs.flutter.dev/platform-integration/web) say that "text-rich, flow-based, static content such as blog articles" benefits from the web's document model rather than a UI framework like Flutter. A SaaS marketing site, blog and docs are exactly that kind of content, so most Flutter teams still run a separate website, in a separate language.

## Which works better with Supabase?

Both work well, because Supabase ships an official client for each. React Native uses supabase-js, the same library as your Next.js app, and Supabase has an [Expo quickstart](https://supabase.com/docs/guides/getting-started/quickstarts/expo-react-native). Flutter uses `supabase_flutter`, which covers the database, auth, storage, realtime and Edge Functions, with its own Flutter quickstart.

The backend doesn't care which client calls it. Row-level security decides what each signed-in user can read, whichever app sends the request. What differs is how much client code you write twice: with Expo, the session handling, error mapping and typed queries can mirror the web app's; with Flutter, you write them again in Dart. There is more on the Expo side in [one backend for web and phone](https://www.shipanysaas.com/blog/expo-supabase-one-backend), and on running costs in [Supabase pricing](https://www.shipanysaas.com/blog/supabase-pricing).

## Can you update the app without waiting for app review?

Yes, on both, within limits. Expo has EAS Update, and Flutter apps can use Shorebird. Neither can change native code, and both have to follow the store rules.

| | EAS Update (Expo) | Shorebird (Flutter) |
| --- | --- | --- |
| Who makes it | Expo | Shorebird, a separate company |
| What it can change | JavaScript, styling and images | Any Dart code, and Dart packages without native code |
| What needs a new store build | Native code, permissions, a new Expo SDK | Native code, assets such as images and fonts, a new Flutter version |
| Free tier, as of October 2026 | Updates to 1,000 monthly active users | 5,000 patch installs a month |
| First paid tier, as of October 2026 | Starter, $19 a month plus usage | Pro, $20 a month |

The [EAS Update docs](https://docs.expo.dev/eas-update/introduction/) say updates "need to follow the App Store and Play Store guidelines", and Shorebird's [code push docs](https://docs.shorebird.dev/code-push/) list what a patch can't touch. Prices come from [Expo's pricing page](https://expo.dev/pricing) and Shorebird's.

## How do you build for the App Store and Google Play?

Expo has a hosted build service, EAS Build, and Flutter doesn't have a first-party one. Both end in the same store review.

[EAS Build](https://docs.expo.dev/build/introduction/) builds Android apps on Linux machines and iOS apps on macOS machines in Expo's cloud, and can create and store your signing credentials if you want it to. Because the iOS build runs on Expo's Macs, you can start it from Windows or Linux, and EAS Submit uploads the result to the stores from any of the three. As of October 2026 the free plan includes 15 Android and 15 iOS builds.

Flutter's [iOS release guide](https://docs.flutter.dev/deployment/ios) says Xcode "is required to build and release your app" and that you need a device running macOS. Its continuous delivery page points to third-party services with Flutter support (Codemagic, Bitrise and Appcircle), to fastlane in your own CI, and to Apple's Xcode Cloud.

Either way, publishing needs Apple's and Google's developer accounts.

## Is Flutter faster than React Native?

There is no general answer, so measure your own app. Each project describes its own approach, and neither publishes a head-to-head benchmark.

Flutter compiles release builds to machine code, and Impeller, the only renderer on iOS and the default on Android API 29 and up, compiles its shaders when the engine is built rather than while your app runs. React Native runs JavaScript on Hermes, which its docs say gives "for many apps" faster start-up, less memory use and a smaller app than JavaScriptCore. The New Architecture, on by default since React Native 0.76, replaces the old asynchronous bridge with direct calls between JavaScript and native code. React Native's docs add a caveat worth repeating: switching it on "may not immediately improve the performance" of an app.

For a SaaS app made of forms, lists and settings screens, either is fast enough. Speed usually comes down to how much data a screen loads and how often it re-renders.

## Where Flutter wins

Pick Flutter when one of these matters more than sharing code with your website:

- **The same look everywhere.** Flutter paints its own widgets, so a design looks the same on every phone, whatever the OS version.
- **Heavy custom drawing.** Animated charts, custom controls and game-like interfaces are what Flutter's rendering model is built for.
- **Desktop apps too.** Flutter also deploys to Windows, macOS and Linux. Expo targets iOS, Android and the web.
- **A team that knows Dart.** If your developers already write Flutter, the shared-language argument for Expo disappears.
- **No web app to share with.** If the phone app is the product and the website is a landing page, Expo's code-sharing advantage is small.

## Why a TypeScript team with a Next.js app usually picks Expo

When the web app already exists in TypeScript, Expo adds a second front end in the same language rather than a second stack. In practice that means:

1. **One language.** The same developers, or the same coding agent, work in both apps without switching between TypeScript and Dart.
2. **Rules written once.** Validation, types and API helpers live in shared packages, so a rule fixed on the web is fixed on the phone.
3. **Familiar patterns.** Expo Router's file-based routes feel close to the App Router, and both apps use React components and hooks.
4. **One package registry.** npm packages that don't touch the DOM often work in both apps.
5. **One toolchain for your agent.** The same type checker and linter cover both apps, so an agent's checks catch mistakes on both sides. More on that in [Claude Code best practices](https://www.shipanysaas.com/blog/claude-code-best-practices).

## Web and phone on one backend, already wired

If you want this setup without wiring it yourself, it is what the kit's All-in plan adds to the Next.js web app. `apps/native` is an Expo SDK 57 app (React Native 0.86) with Expo Router, built for iPhone, iPad and Android from the same repository as the web app. Expo released SDK 58 on 15 October 2026; All-in ships Expo's own upgrade skill, with notes on where the kit's rules win.

The two apps share a lot. The phone app imports Zod schemas, types and query keys from the same packages as the web app, and the generated database types. It signs in to the same Supabase project, with the same personal and team accounts, roles, members and invitations, and it keeps sessions encrypted on the device. Customers pay on the website and the app shows their team's plan.

Some things are left out, so you know before you buy. The phone app has no push notifications. Passkeys and magic links are in the web app only. EAS Update isn't installed, though the Expo update skill ships with All-in for when you add it. App Store and Google Play releases are set up with EAS build profiles and store listing templates you fill in.

Starter is the web app; All-in adds the phone app. All-in ships 49 agent skills and 17 written fixes for setup errors, against 42 skills and 6 fixes in Starter, and the extra ones cover Expo, EAS and the stores. Both are one payment, with no subscription. Try the web and phone demos from the [pricing page](https://www.shipanysaas.com/pricing) first, where today's prices are, and read [getting started](https://www.shipanysaas.com/docs/getting-started/getting-started) to see what is in the repository.

## FAQ

### Is Flutter better than React Native in 2026?

Neither is better in general. Flutter suits apps that need the same custom look on every device or a desktop version. React Native with Expo suits teams that already work in TypeScript and React, especially with a Next.js web app to share code with.

### Can I use native code with Expo?

Yes. Expo config plugins change the native project without hand-editing Xcode or Gradle files, and the Expo Modules API lets you write your own modules in Swift and Kotlin. Changes to native code need a new store build, because EAS Update only ships JavaScript, styling and images.

### Do I need a Mac to build the iPhone app?

With Flutter, Apple's tools need macOS: Flutter's iOS guide requires Xcode on a Mac, unless a hosted CI service builds for you. With Expo, EAS Build runs iOS builds on Expo's own macOS machines, so you can start from Windows or Linux. Running the iOS simulator locally still needs a Mac.

### Can one Supabase project serve a Next.js app and a phone app?

Yes. Point both apps at the same project URL and publishable key, and they share users, data and row-level security policies. Keep the secret key on your server only, never in an app bundle.
