Mobile App Development
I build cross-platform mobile apps that run on both iOS and Android from a single codebase. Instead of hiring two separate teams and maintaining two completely different projects, you get one streamlined build that covers both platforms. I work with React Native, Capacitor, and Expo depending on what fits your project best, and I handle everything from initial architecture through app store submission.
React Native: The Industry Standard for Cross-Platform
React Native is my primary tool for building production mobile apps. Created by Meta and used by companies like Shopify, Discord, and Microsoft, it lets me write your app in JavaScript and React while producing truly native UI components on both platforms. This is not a web view wrapped in an app shell. When a user taps a button or scrolls through a list, they are interacting with the same native elements that a Swift or Kotlin app would render.
I use React Native when the project demands a polished, app-store-ready experience with smooth animations, complex navigation patterns, and tight integration with device hardware. Push notifications, camera access, biometric authentication, offline storage, and background tasks all work reliably. The ecosystem is mature, the community is enormous, and the library support is deep enough that I rarely encounter a device feature I cannot tap into.
From a practical standpoint, React Native also means faster iteration. Hot reloading lets me make changes and see them reflected on a device in seconds rather than waiting through full recompile cycles. That translates directly to shorter development timelines and lower costs for you. I can prototype an idea, put it on your phone for testing, and iterate on feedback the same week.
Capacitor: Turning Web Apps into Mobile Apps
If you already have a web application built with a modern frontend framework like React, Vue, or Angular, Capacitor is often the fastest and most cost-effective path to the app store. Capacitor wraps your existing web app in a native container and provides a plugin system for accessing device APIs like the camera, geolocation, file system, and push notifications.
I recommend Capacitor when clients have an existing web app they want to distribute through the App Store or Google Play without rebuilding from scratch. The web codebase stays intact, and I add a native layer on top. This is especially useful for internal business tools, dashboards, and SaaS products where the core functionality already works well in a browser but needs the distribution and notification capabilities of a native app.
The trade-off is transparent: Capacitor apps run your web code in a WebView, which means complex animations and gesture-heavy interfaces may not feel as snappy as a React Native build. But for data-driven apps, forms, content displays, and workflow tools, the difference is negligible and the development savings are significant. I will always tell you upfront which approach makes more sense for your use case.
Expo: Rapid Development and Managed Infrastructure
Expo is a platform built on top of React Native that removes much of the configuration overhead. It provides a managed build service, over-the-air update capabilities, and a curated set of libraries that are guaranteed to work together. I use Expo when speed is the priority and the project does not require deeply custom native modules.
The biggest advantage of Expo is the development workflow. I can share a preview build with you through a simple link or QR code, no TestFlight invitation or APK sideloading required. You scan the code, the app loads on your phone, and you can start testing immediately. When I push an update, you see it within minutes rather than waiting for a new app store review cycle.
Expo has matured considerably. With the introduction of Expo Modules and continuous native generation, many of the old limitations are gone. Custom native code, background tasks, and advanced configurations that previously required ejecting from Expo are now supported within the managed workflow. For the majority of mobile app projects I take on, Expo provides the right balance of speed, reliability, and flexibility.
Cross-Platform vs. Native: Making the Right Call
I get asked about this regularly, so here is my honest take. For most small-to-mid-sized businesses, cross-platform development is the practical choice. You save on development time, maintenance overhead, and ongoing feature costs because there is one codebase to update instead of two. The performance gap between cross-platform and fully native has narrowed to the point where most users cannot tell the difference.
That said, there are cases where native code makes more sense, and I write it myself rather than treating it as somebody else's problem. If your app depends on real-time audio or video processing, Bluetooth hardware, background location, home screen widgets, or a deep integration specific to one platform, I build that layer in Swift or Kotlin and expose it to the shared codebase as a native module. A fully native build is also on the table when the requirements justify it. The only work I would hand off is genuinely specialized territory like a 3D game engine or heavy computer vision research, and I will tell you that up front instead of taking the project and learning on your budget.
What I have found over years of building apps is that the technology choice matters far less than the architecture decisions, the attention to UX details, and the quality of the underlying code. A well-built React Native app will outperform a poorly built native app every time. I focus on getting the fundamentals right regardless of the framework.
App Store Deployment and Ongoing Maintenance
Getting an app built is only half the job. I handle the full submission process for both the Apple App Store and Google Play Store. That includes provisioning profiles, signing certificates, screenshots, metadata, privacy policy compliance, and navigating the review process. Apple in particular has a detailed and sometimes unpredictable review workflow, and I have the experience to anticipate common rejection reasons and address them before submission.
After launch, I can set up over-the-air updates through Expo or CodePush so that JavaScript-level changes reach your users without requiring a new app store review. For larger updates that involve native code changes, I manage the versioning and staged rollout process. I also configure crash reporting, analytics, and performance monitoring so you have visibility into how your app performs in the real world.
I offer ongoing maintenance arrangements for clients who need regular updates, bug fixes, and feature additions. Mobile platforms evolve quickly. iOS and Android release major updates annually, and keeping your app compatible requires attention. I stay on top of deprecations, permission changes, and new platform requirements so your app does not break when users update their phones.
Flutter
Flutter is Google's cross-platform framework and the other serious answer to building one app for iOS and Android. It uses Dart and takes a fundamentally different approach from React Native: instead of translating your code into the operating system's native widgets, Flutter ships its own rendering engine and draws every pixel itself.
That single architectural decision drives every tradeoff worth knowing about. Because Flutter paints its own interface, your app looks exactly the same on an iPhone, a budget Android device, and a tablet — no chasing platform inconsistencies, no "why does this button look wrong on Samsung." For a company with a strong brand and a designer who wants the layout honored precisely, that is a genuine advantage. Flutter also compiles to the web, Windows, and macOS from the same codebase, so a mobile app and a desktop companion can share nearly all of their logic.
The flip side is that Flutter apps do not automatically inherit platform behavior. When Apple restyles its controls in a new iOS release, a React Native app largely follows along because it is using the real system components; a Flutter app looks the way you built it until you update it. Bundle sizes also start larger because the engine ships with the app.
My default remains React Native, mostly because it shares a language and mental model with the React front ends I build, which means one stack across web and mobile and no context switching. But when a project is design-driven, needs pixel-identical rendering across devices, has heavy custom animation, or is targeting mobile and desktop together, Flutter is the better tool and I will say so.
When Flutter Wins
- Brand-driven apps where the design must render identically on every device
- Heavy custom animation and bespoke UI that does not map to stock components
- Projects targeting mobile, web, and desktop from one codebase
- Teams that already write Dart or have an existing Flutter codebase
- Apps where consistent rendering on low-end Android devices is a requirement
SwiftUI & Jetpack Compose: The Native Layer
Cross-platform gets you most of the way. The native layer is what closes the gap, and on nearly every app I build there is some amount of it.
SwiftUI on iOS and Jetpack Compose on Android are the modern, declarative ways to build native interfaces. They replaced the old UIKit and XML-layout approach, and both work the way React does: describe the interface for a given state, let the framework reconcile the changes. If you have seen a React component, you can read a SwiftUI view.
On a cross-platform project, I use them for the parts that have to be native. A Core Bluetooth service that talks to a medical device or a piece of shop equipment. A HealthKit or Google Fit sync. A camera pipeline processing frames live instead of just capturing a photo. Background location that keeps running after the OS suspends the app. A home screen widget, a Live Activity on the lock screen, or a watch app. Each of those gets written natively and bridged into the shared codebase, so you get platform-grade behavior without giving up a single codebase for the other ninety percent of the app.
Sometimes fully native is simply the right answer — an app that is a thin interface over deep hardware integration, or one where the client's roadmap is iOS-only for the foreseeable future. In that case I build it natively rather than forcing a cross-platform framework to do something it was not designed for.
Native Work I Take On
- Bluetooth Low Energy integrations with hardware and medical devices
- HealthKit, Google Fit, and other permission-gated platform data sources
- Real-time camera, audio, and sensor processing
- Background location, geofencing, and long-running background tasks
- Widgets, Live Activities, watch apps, and share extensions
Progressive Web Apps
Not every "we need an app" conversation should end with an app store. A Progressive Web App is a website engineered to behave like an installed app: the user taps "Add to Home Screen," gets an icon on their device, and launches into a full-screen experience with no browser chrome. Under the hood a service worker caches the interface and data so it keeps working with a bad connection or none at all.
The business case is often overwhelming. There is no app store review, no developer program fee, no 15 to 30 percent platform commission, and no waiting three days for an approval to ship a one-line fix. A deploy is live instantly for every user on every platform. For an internal tool, a customer portal, a booking system, a field-service checklist, or a menu and ordering flow, a PWA frequently delivers everything the business actually wanted at a fraction of the cost and timeline of a native build.
I build them with the same discipline as any app: an installable web manifest with proper icons, a service worker with a deliberate caching strategy rather than a copy-pasted one, offline-first data handling that queues writes and flushes them when connectivity returns, and web push notifications where the platform supports them.
I will also tell you when a PWA is the wrong call. iOS still restricts access to Bluetooth and HealthKit from the browser, background execution is more limited than a native app, and you give up App Store discovery — which matters if the store is a real acquisition channel for you rather than just a distribution mechanism. If your app depends on hardware or background behavior, build the real thing.
Firebase & Push Notifications
Most mobile apps need the same backend services, and rebuilding them from scratch for every project wastes your money. Firebase covers that ground well: authentication with email, phone, Apple, and Google sign-in; Firestore for realtime synced data; Cloud Storage for user uploads; Cloud Functions for server-side logic; Crashlytics for crash reporting; and Analytics for understanding what people actually do in the app.
The realtime piece is what makes it worth reaching for. Firestore pushes changes to every connected client automatically and keeps working offline, resolving writes when the device reconnects. For chat, live order status, collaborative features, or anything where two people need to see the same thing at the same moment, that behavior would take real effort to build and maintain on your own backend.
Push notifications are where mobile projects quietly fail, so I treat them as real engineering rather than a checkbox. Delivery runs through Firebase Cloud Messaging to Android and through APNs to iOS, each with its own certificate and token lifecycle. Permission gets requested at a moment that makes sense in context, not on first launch when the user has no reason to say yes — that one decision moves opt-in rates dramatically. Device tokens are stored, refreshed, and pruned when they go stale, because sending to dead tokens degrades your delivery reputation. Deep links route a tap to the right screen instead of dumping the user on a home feed.
I am also honest about the tradeoff: Firebase is a Google-hosted platform, so you are accepting a dependency and a usage-based bill that grows with scale. When a project needs full data ownership, has strict compliance requirements, or is already running on PostgreSQL, I build the equivalent on your own infrastructure with Supabase or a custom API instead.
What I Wire Up on a Typical App
- Authentication with email, phone, Apple, and Google sign-in
- Realtime data sync with offline persistence and conflict handling
- Push notifications via FCM and APNs, with deep links to the right screen
- Contextual permission prompts that protect your opt-in rate
- Crash reporting and analytics so problems surface before reviews do
Comparing React Native, Flutter, Capacitor, and Expo
| Feature | React Native | Flutter | Capacitor | Expo |
|---|---|---|---|---|
| Rendering | Native UI components | Own engine draws every pixel | WebView-based | Native UI components |
| Best For | Complex, performance-critical apps | Brand-consistent, animation-heavy apps | Converting existing web apps | Rapid development, MVPs, standard apps |
| Performance | Near-native | Near-native, compiled to machine code | Good for data-driven apps | Near-native |
| Code Sharing | Shared logic, platform-specific UI possible | Shared across mobile, web, and desktop | Full web codebase reuse | Shared logic, platform-specific UI possible |
| OTA Updates | Via CodePush | Via Shorebird or a full store release | Manual or plugin-based | Built-in with EAS Update |
| Native Module Access | Full access, custom modules supported | Full access via platform channels | Via Capacitor plugins | Full access via Expo Modules |
| Setup Complexity | Moderate, requires Xcode and Android Studio | Moderate, Flutter SDK plus platform tooling | Low, builds on existing web project | Low, managed cloud builds available |
| Ideal Client | Businesses needing a polished, feature-rich app | Design-led brands wanting identical UI everywhere | Teams with an existing web app | Startups and businesses wanting fast delivery |
Ready to Build Your App?
Book a free discovery call to talk through your mobile app idea.
Book a Call