📱 🚀 ⚙️
## The Mobile App Myth
Every SaaS founder wakes up asking the same question: "Should we build a mobile app?"
Then they panic and ship React Native because "that's what you do for apps." Eighteen months later, they're maintaining three codebases (iOS, Android, web), hiring native developers, and wondering why the app feels different from the web version.
Here's the truth: **80% of SaaS dashboards don't need React Native.** They need a PWA that installs to your home screen like an app, works offline, and feels native because it IS your web app in a frame.
The other 19% need Capacitor (wrap your web app in a native shell + access device hardware). The 1% that genuinely needs React Native will know it.
Aidxn pattern: **PWA by default, Capacitor when forced, React Native only if you're building something that requires native UI or heavy device interaction.**
## The Three Options Explained
### PWA — Your Web App on the Home Screen
A Progressive Web App is your React/Vue/Astro web app with three small additions:
- A `manifest.json` file (tells iOS/Android "this is installable")
- A service worker (caches assets so it works offline)
- HTTPS (required for security)
That's it. No build step. No platform-specific code. Your users hit your site, see an "Add to Home Screen" button, and the app installs exactly like any app store download.
**The numbers:**
- Build time: 5 minutes (add manifest + service worker)
- App store submission: zero (no store required)
- Codebase: one (same React code)
- Push notifications: yes (via service worker)
- Camera access: yes (via Web APIs)
- Home screen install: yes (works on 95%+ of devices)
- Offline: yes (via service worker cache)
- Size on device: 10–50MB (mostly your web bundle)
- Native UI: no (it's the web, styled to look native)
**The catch:**
PWAs don't appear in app stores (unless you manually submit to Microsoft Store or Google Play). Users have to visit your website to install. But here's the secret: your best users already visit your website. The install prompt appears automatically after they've used the app once.
On iOS, PWA support is full as of iOS 17.4. Notifications work. Offline works. Full-screen app mode works. Your PWA runs as indistinguishable from a native app on the home screen.
### Capacitor — The Native Wrapper
Capacitor is a bridge. You write React once, Capacitor wraps it in a native iOS and Android shell, giving you access to:
- Push notifications (via native services)
- Camera + photo library
- GPS and geolocation
- Filesystem access
- Native dialogs and menus
- App lifecycle events
Example: you build a Velocity X dashboard, then wrap it with Capacitor to add push notifications for deal alerts and GPS for field teams. Same codebase. Two native apps.
**The numbers:**
- Setup time: 15 minutes (Capacitor CLI + native dependencies)
- Codebase: one React app + small iOS/Android setup
- App store submission: yes (but mostly automated)
- Native features: extensive (80% of what you'd need)
- Build time: 3–5 minutes (web) + 10–15 minutes (native compile)
- App size: 40–80MB (web bundle + native runtime)
- Developer experience: high (write once, deploy to both)
- True native UI: no (still web under the hood)
**The catch:**
Capacitor is a wrapper, not a true native app. Some deep platform-specific features are unreachable (custom keyboards, widgets, background processing that needs 1000% CPU). For 19 out of 20 SaaS use cases, it's more than enough. For the 1 that needs true native UI performance or deep OS integration, you'll feel the limits.
Also, Capacitor apps still need native development environments (Xcode for iOS, Android Studio for Android) to compile. You're not writing Java or Swift, but you do need the SDKs installed.
### React Native — True Native Apps
React Native is a framework for writing iOS and Android apps in JavaScript. The code compiles down to real native iOS and Android components, not a web view.
When you import ``, it becomes a real `UIView` on iOS and `android.view.View` on Android. Gestures are native. Animations run on native threads. It feels like an actual app because it is.
**The numbers:**
- Setup time: 30–60 minutes (Xcode + Android Studio + Expo or bare workflow)
- Codebase: three separate apps (web stays separate, or you share 40% of business logic)
- App store submission: yes (full native submission process)
- Native UI: yes (you get real native components)
- Performance: near-native (95%+ of hand-written native code speed)
- Push notifications: yes (native)
- Device features: yes (100% of them)
- Offline: yes (with local DB like SQLite)
- Build time: 20–40 minutes (per platform)
- App size: 50–150MB (native runtime + compiled code)
**The catch:**
You now maintain three platforms: web, iOS, Android. Styling is different (no CSS, no Tailwind). Shared code is maybe 40% of your codebase. You need developers who know React Native patterns (different from web React). Platform differences bite you — something working on iOS breaks on Android. You absolutely need native development environments set up locally.
## Real Comparison Table
| Metric | PWA | Capacitor | React Native |
|--------|-----|-----------|--------------|
| Setup time | 5 min | 15 min | 60 min |
| Codebases | 1 (web) | 1 (web) + native shell | 3 (web separate, iOS, Android) |
| App store presence | no (web install only) | yes (Google Play, App Store) | yes (Google Play, App Store) |
| Push notifications | yes | yes | yes |
| Camera + GPS | yes | yes | yes |
| Offline support | yes | yes | yes |
| Build time | 3 min | 15 min | 40 min |
| App size | 10–50MB | 40–80MB | 50–150MB |
| Native UI | no (web) | no (web wrapper) | yes (true native) |
| Dev experience | excellent (use Tailwind, GSAP) | excellent (one build per app) | good (platform differences) |
| Maintenance burden | low | medium (two native targets) | high (three platforms) |
| Platform coverage | 95% | 99% | 100% |
| Best for | SaaS dashboards, content | SaaS + device features | performance-critical, games |
## Three Decision Trees
### Path 1: "I'm Building a SaaS Dashboard"
**Start with PWA.**
Your users are on desktop and mobile. They log in daily. You need push notifications for alerts and camera for photo uploads.
```bash
# Add manifest and service worker (5 minutes)
npm install workbox-cli
npx workbox wizard
# Add manifest.json to public/
# Deploy to HTTPS
```
Your app installs to home screen. Notifications work. Camera works. Same codebase as your desktop site.
Then? Ship it. 90% of the time, PWA is enough.
**If you hit limits** (say, you need GPS tracking for field teams AND offline maps), escalate to Capacitor:
```bash
npm install @capacitor/core @capacitor/cli
npx cap init
npx cap add ios
npx cap add android
# Now you can access GPS, camera, filesystem
```
Same React code. Two native apps appear automatically. Deploy to Google Play and App Store.
### Path 2: "I'm Building a Content App"
**Start with PWA.**
Book recommendations, article reader, podcast player. All of this works perfectly as a PWA. Install to home screen, works offline with cached content, push notifications for new episodes.
```bash
# Same setup as dashboard
npm install workbox-cli
```
Ship it. If you later need deep OS integration (background downloading, custom share sheets), add Capacitor.
### Path 3: "I'm Building a Performance-Critical Game"
**Use React Native or native code.**
Games need native frame rates, native gesture handling, native physics. PWA won't cut it. Capacitor is a wrapper and you'll hit its limits.
React Native gives you native performance without writing Kotlin and Swift. But be prepared: you're learning new patterns, platform differences will surprise you, and your timeline doubles.
## The PWA Setup (15 Minutes)
Here's the real implementation:
**Step 1: Create manifest.json**
```json
{
"name": "Velocity X Dashboard",
"short_name": "Velocity X",
"description": "SaaS platform for teams",
"start_url": "/",
"scope": "/",
"display": "standalone",
"background_color": "#ffffff",
"theme_color": "#000000",
"icons": [
{
"src": "/icon-192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/icon-512.png",
"sizes": "512x512",
"type": "image/png"
}
]
}
```
**Step 2: Link in Layout.astro**
```html
```
**Step 3: Add service worker**
```typescript
// src/service-worker.ts (Astro integration)
self.addEventListener('install', (event) => {
console.log('Service Worker installing');
});
self.addEventListener('activate', (event) => {
console.log('Service Worker activated');
});
self.addEventListener('fetch', (event) => {
// Cache first, fallback to network
event.respondWith(
caches.match(event.request)
.then(response => response || fetch(event.request))
.catch(() => caches.match('/offline.html'))
);
});
```
**Step 4: Register in browser**
```typescript
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js');
}
```
Done. Your PWA is installable.
## Escalation to Capacitor
When PWA limits hit (need GPS, background processing, native notifications), add Capacitor in 15 minutes:
```bash
npm install @capacitor/core @capacitor/cli
npx cap init my-app io.mycompany.myapp
npx cap add ios
npx cap add android
```
Your React code stays the same. Import Capacitor plugins:
```typescript
import { Geolocation } from '@capacitor/geolocation';
const coords = await Geolocation.getCurrentPosition();
console.log(coords.coords.latitude);
```
iOS app and Android app build automatically. Submit to stores as native apps.
## Six FAQs
**Q: Can PWA users access push notifications?**
A: Yes. Service workers can receive push messages from a backend service (Firebase Cloud Messaging, etc.). Notifications arrive like native notifications. Works on 95%+ of devices.
**Q: Do I have to use Capacitor if I want app store presence?**
A: No. You can manually submit PWAs to Google Play (as Trusted Web Activities) or the Microsoft Store. But most teams use Capacitor because the automated build process is easier.
**Q: Can I write Capacitor without React Native knowledge?**
A: Absolutely. Capacitor is a wrapper. You're still writing React. You just gain access to native APIs via plugins. No Kotlin or Swift required.
**Q: What about sharing code between web and React Native?**
A: ~40% (business logic, utilities). UI code diverges because React Native doesn't use CSS and Tailwind. It's a real cost. Plan for it.
**Q: Can React Native apps access web APIs like localStorage?**
A: Partially. AsyncStorage exists but it's different from browser localStorage. Some web APIs don't exist in React Native. You'll rewrite some code.
**Q: Should I worry about app store review delays?**
A: Yes, PWA avoids this (no store needed). Capacitor apps go through app store review (1–7 days typically). React Native apps go through app store review. Plan for this if you need same-day updates.
## The Verdict
Your choice isn't about technology. It's about what your users need.
If your app is a dashboard, content browser, or any "check something quickly" use case, PWA is the answer. Build it once, install it on 1000 devices for zero distribution cost.
If you need push notifications or camera + offline, add Capacitor. Still one codebase, two app stores.
If you're building a game or something that needs frame-perfect native UI, React Native. But count the cost: three platforms, longer timelines, more developers.
For Velocity X SaaS, we default to PWA. Push notifications, offline mode, camera access, home screen install — all included. If a customer later needs background GPS tracking, we add Capacitor. No rework, same React.
That's the pattern: start simple, escalate only when forced. Check out our pricing page to see how we build Velocity X stacks with PWA-first mobile strategy. For more on developer experience, read our Bun vs Node vs Deno post — the same philosophy applies to runtime choice.
One codebase. Three deployment targets. Ship faster.