You have an idea for an app. Before you write a single line, you hit a fork in the road: build it native, build it for the web, or build it cross-platform. Each choice decides which language you learn, whether you need an app store, and whether you end up maintaining one project or two. This page explains all three in plain words, shows what actually sits between your code and the phone, and ends with a little chooser you can try on your own idea.
A platform is the system your app runs on. For phones there are two that matter: Apple's iOS (iPhones) and Google's Android (Samsung, Pixel and most other phones). They are separate worlds: different companies, different tools, different app stores, and an app built only for one simply won't install on the other.
A codebase is the whole collection of source code for one project. "One codebase" means you write the app once. "Two codebases" means you write it twice, usually in two different languages, and every new feature or bug fix has to be done in both. Keep that word in mind; it's at the heart of the whole choice.
A native app is written with the tools the platform's maker provides. For iPhone that means the Swift language and Apple's Xcode editor (older apps use Objective-C). For Android it means Kotlin and Google's Android Studio (older apps use Java). Because you're using the platform's own building blocks, you get every feature the phone offers on day one, the app looks and behaves exactly like the rest of the system, and performance is as good as it gets.
The catch: if you want both iPhone and Android users, you build the app twice. Two languages, two codebases, often two developers. One practical detail too: Xcode only runs on macOS, so building an iPhone app generally means owning a Mac.
A web app is a website that behaves like an app. It's built with the three languages of the web: HTML for structure, CSS for looks, and JavaScript for behaviour. It runs inside the phone's browser (Safari, Chrome and so on), so one codebase works on iPhone, Android, and laptops too. People open it with a link; no store, no install, no review. When you fix a bug, everyone gets the fix the next time the page loads.
A web app can go further and become a PWA (progressive web app): it gets an icon on the home screen, opens full-screen without the browser's address bar, and can keep working offline using a service worker, a small script the browser runs in the background that can save pages and data on the phone. The limit is that a web app can only do what the browser allows. Camera, microphone and location work (after the user says yes), but some deeper features are patchy. Bluetooth, for example, is available in Chrome on Android but not in Safari on iPhone.
A cross-platform framework lets you write the app once and produce a real, installable app for iOS and Android. A framework is a big toolkit of ready-made code you build on top of. The two best-known are:
Both produce apps you publish in the App Store and Google Play, and both reach phone features through plugins: small packages that contain the native Swift/Kotlin code for something like the camera, wrapped so you can call it from Dart or JavaScript. When no plugin exists, you (or someone on your team) write that bit natively. Other options exist too, such as Kotlin Multiplatform and .NET MAUI (which uses C#), but Flutter and React Native are where most beginners start.
The real difference between the three is how many layers your code passes through before it reaches the phone's hardware. Pick an approach, then tap any layer to see what it does.
The layer cake · tap a layer
Notice the pattern. Native has the shortest path: your code talks to the operating system directly. Web has the browser in the middle, which is what makes it run everywhere but also what limits it. Cross-platform adds its own engine (the framework's built-in code that ships inside your app) plus plugins as a bridge to native features. Each extra layer buys you convenience and costs you a little control.
To get a feel for each language, here is a single button that says "Say hi" and prints Hi! when tapped. These are fragments, the piece you'd drop into a screen, not complete apps.
One button · five languages
They look different, but the idea is identical: a button, a label, and a bit of code to run on tap. Once you've learned one, the others feel familiar. That's good news, because your first choice isn't a life sentence.
Three questions decide most real projects. Here is how each approach answers them.
| Native | Web / PWA | Cross-platform | |
|---|---|---|---|
| Languages | Swift (iOS), Kotlin (Android) | HTML, CSS, JavaScript | Dart (Flutter) or JavaScript (React Native) |
| Codebases for both phones | Two | One | One (plus a little native code sometimes) |
| App stores | Yes, required | Not needed; can be wrapped to get in | Yes, required |
| How users get it | Install from store | Open a link | Install from store |
| Updates | New version through store review | Instant, on next load | New version through store review |
| Offline | Yes, naturally | Yes, with a service worker (extra work) | Yes, naturally |
| Phone features | Everything | What the browser allows | Most, through plugins |
App stores are the official shops: Apple's App Store and Google Play. Being there helps people find and trust your app, but it isn't free or instant. Apple's developer program costs US$99 a year and Google Play charges a one-time US$25 registration fee, and every release is reviewed before it goes live. A web app skips all of that. If you later want a web app in the stores anyway, tools like Capacitor can wrap it in a thin native shell, though Apple may reject an app that's just a website with no app-like value.
Offline matters more than people think: subways, planes, bad signal. Installed apps carry their code with them, so they can open with no connection at all. A web app can do the same with a service worker, but you have to build that part on purpose, and browsers may clear saved data for sites you haven't visited in a while.
Phone features are where native shines. Home-screen widgets, Apple Watch apps, background tasks and the newest system features arrive in Swift and Kotlin first. Cross-platform frameworks usually catch up through plugins. The web gets the common ones (camera, location, notifications) and is missing or uneven on the deeper ones.
Notice that "best" never appears in that table. Big, successful apps have been built all three ways. The right choice depends on your app, your budget, and what you already know.
Switch on everything that's true for your idea. Each option starts from the same score and gains or loses points with a reason for each, so you can see why, not just who wins.
The chooser
The scoring is a rule of thumb, not a law. A team that knows Flutter inside out will happily build things the chooser says suit native. But the reasons it gives you are the real trade-offs developers weigh.
If you're just starting, here is a practical way to think about it:
Whichever you choose, the core ideas (variables, functions, screens, data, tapping a button to run code) carry straight over to the others. Plenty of developers start on the web, move to a cross-platform framework, and pick up Swift or Kotlin when a project needs it.
You want an app on both iPhone and Android and build it natively. How many codebases do you maintain?
Native means Swift for iOS and Kotlin for Android: two separate projects in two languages, and every feature is built twice.
Which language do you write a Flutter app in?
Flutter uses Dart, a language also made by Google. React Native is the one that uses JavaScript.
What lets a web app keep working when the phone has no connection?
A service worker is a background script the browser runs for your site. It can save pages and data on the phone and serve them when there's no network.
You fix a bug in your web app and deploy it. When do users get the fix?
Web apps are loaded from your server, so there's no store in the way: the new version arrives on the next load. Native and cross-platform apps ship updates as new versions through store review.