Capacitor.js Experience Report Building Native Mobile Apps with React

Capacitor.js Experience Report Building Native Mobile Apps with React

Ryan Wong June 12, 2026 capacitor.js, react, mobile-development, cross-platform, ios, android, webview, native-apps

Introduction

Your React application executes within a browser. In order to deploy your application on the App Store or Google Play, you typically have no other choice but to hire mobile developers or learn Swift or Kotlin alongside React. With Capacitor.js, however, you can deploy real native apps to stores without having to learn any new technologies or hiring mobile developers.

Capacitor was tested for an existing React client application which was already working. The changes made to React were minimal. All other changes were made surrounding it, including Xcode, Android Studio, permissions, synchronization, signing, etc. This document presents our findings.

The Purpose: Web Proficiency, Native Application Generation

Capacitor was designed to solve the problem of bringing the gap between web programming and the production of mobile apps. Using what you already know React, Vite, and npm Capacitor creates native applications for both iOS and Android with a webview.

What it tries to accomplish:

Enable web development teams to deploy native applications without turning into mobile developers overnight.

Provide access to the camera, GPS, push notifications, and other device functionalities via JavaScript plugins.

Maintain the existing hot reload capabilities and the familiar frontend development process without having to switch everything.

Make builds that can be shipped right out of the box without any risk of being summarily rejected by Apple or Google.

Hybrid build systems from the past used to abstract away the native project from you. Capacitor flips the script. Instead of having your builds wrapped in an abstraction, you can access actual Xcode and Android Studio projects.

Important Features

Plugin system Official plugins include those for Camera, Geolocation, Push Notifications, etc. There are community plugins that can fill other gaps. Should none be applicable, you may create one yourself using Swift or Kotlin.

Live reload Connect Capacitor with your Vite or CRA development server and then use the command npx cap run ios --livereload. The changes will instantly appear in the iOS simulator or on your smartphone.

Same code, different platforms: one codebase targeting iOS, Android, and web (PWA). It's framework agnostic too; React was our choice but any other would do, such as Vue or Svelte.

You have full control over your native app: use npx cap open ios to open your project in Xcode. Or run npx cap open android for Android Studio.

Oddities and Troubles

Capacitor does work. Just not by magic. Here’s what wastes our time.

Platform Detection

Sometimes App.getInfo() will return information about the platform that you do not expect. If you want to make absolutely sure whether your code is running in a mobile app or a website, you still need to check the user agent:

const isMobile = /Mobi/i.test(window.navigator.userAgent);

Permissions Must Be Done Manually

Info.plist modifications for the camera plugin on iOS? That's on you. Capacitor won't automate this process.

<key>NSCameraUsageDescription</key>
<string>This app needs access to the camera to take photos.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>This app needs access to the photo library to select pictures.</string>

Skip this step, and you'll have an application crash or fail camera functionality.

Simulators Cheat

Camera, cellular connection, certain sensors, security storage these either don't exist or simulate in simulators. For anything that requires access to the actual device, you better test your application on a physical one. We found this out after weeks debugging a camera feature working in Chrome.

Version Matching

@capacitor/cli, @capacitor/core, @capacitor/ios, and @capacitor/android need to be matched to the same version number. If mismatched, the JS bridge gets out of sync with the native code and you get build errors or runtime failures.

Sync Command

The npx cap sync command builds your web project assets and places them in the native project directory. It’s one of those commands that you use frequently. It fails from time to time because of permissions issues or bad configuration in your native app. Also, remember that you must build before syncing.

Two Sources for Finding Bugs

Bugs that occur in the JavaScript console include both front-end errors as well as plugin API bugs. Native crashes are visible in either Xcode or adb logcat. When you have a broken plugin, you will not get much in the browser at all.

Live reloads behave differently than the build after npm run build && npx cap sync.

React Developers How Easy is It?

We would give it an 8 out of 10.

Your React application isn’t transformed into anything. The entire codebase runs within a WebView. Components, Hooks, Redux, Context, Zustand, React Router, Tailwind, ShadCN everything just worked for us right away.

Initial setup takes somewhere around 20 minutes for the first time. Native features can be added one by one rather than doing conversion all at once. Documentation is decent and can be copied from there. Whenever we faced an issue, someone on Stack Overflow or GitHub had done that already.

Learning curve is definitely not about React. It is all about mobile development permissions, certificates, background processes, and app store policies. None of this has anything to do with Capacitor perse.

Development Workflow

Install and init:

npm install @capacitor/core @capacitor/cli
npx cap init
npx cap add ios
npx cap add android

Day-to-day UI work: npm run dev in the browser like always.

Test on device: npx cap run ios --livereload for simulator or phone with hot reload.

Add a native feature:

import { Camera } from '@capacitor/camera';

Use it like any other npm package import.

Native config: npx cap open ios or npx cap open android when you need to set permissions or signing.

Ship it:

npm run build && npx cap sync

Then build and submit from Xcode or Android Studio.

Capacitor vs. The Other Options

Factor Capacitor + React Separate Native Apps Web-Only PWA
Code reuse One React codebase Swift + Kotlin, two teams Web only
Device APIs Via plugins Full native Very limited
App store Yes Yes Weak / no install
Setup for web devs ~30 minutes Months Already done
Live reload on phone Yes Varies N/A
Main headache Permissions, sync, versions Two codebases No native features

Implementation Recommendations

Ensure matching versions of Capacitor packages before each new release. cli, core, ios, android should all be the same version.

Ensure proper permissions are set in Info.plist and Android manifest before using Camera, Geolocation, or any hardware functionality.

Use the hardware early. Simulation is a waste of time because it focuses only on the camera and sensors.

Build and synchronize. npm run build && npx cap sync. It's mandatory.

If there's an error with a plugin, examine both Xcode or logcat and the JS console.

Produce builds and live reload builds are two different binaries. Verify them separately.

Conclusion

The use of Capacitor.js can help those web developers who use React achieve access to mobile environments without changing much of their existing code. In other words, they will have to address issues relating to the mobile environment, not React.

It made sense in this scenario. React developers score a 8/10 in terms of ease of adoption. It is not a perfect solution but a pragmatic approach towards achieving iOS & Android without starting afresh in two new languages.


Technical Aspects

Core Stack

Capacitor.js (from @capacitor/core and @capacitor/cli packages)

Platform-specific packages (from @capacitor/ios and @capacitor/android packages)

React app running within native WebView

Official & community-created Capacitor plugins

Typical Process

Set up Capacitor, initialize a project, add both iOS and Android UI

Test on device with live reload

Add plugins if required

npm run build, npx cap sync, publish using native IDE

Important Constraints:

Version compatibility of Capacitor plugins

Native permission configuration manually

Insufficient simulators for hardware functionality

npx cap sync needed for each web build

Error messages are found in the JS console and native console

React Developer Adoption Rating: 8/10

Reference:

Ready to Build Your AI Product?

Whether you're extending a React web app to mobile or planning a cross-platform product from scratch, we can help you choose the right stack and ship faster.

Book Consultation

Related Posts

When is the Best Time to Go Mobile?

When is the Best Time to Go Mobile?

Don't rush into mobile app development. Learn why Progressive Web Apps offer faster deployment, easier maintenance, and better user reach than native apps for most startups.

October 22, 2025 Read More →
AI development services equity stake instead of cash

AI development services equity stake instead of cash

Most AI developers won't work for equity alone—and you shouldn't rely on it. Discover the real costs, hidden risks, and what actually works when you can't pay cash for world-class AI development.

February 5, 2026 Read More →
Essential Production Tracking Tools

Essential Production Tracking Tools

When production nearly went down, this checklist of monitoring tools and DevOps practices saved the day. Essential production health signals and guardrails every engineering team needs.

October 23, 2025 Read More →