Capacitor → React Native
A complete porting plan for Ionic / Capacitor apps that want to move to React Native — with two end-to-end CI/CD options (Expo + EAS Build for the easy paid path, and React Native CLI + GitHub Actions + Fastlane for the cost-sensitive path).
The full plan — including ready-to-paste GitHub Actions YAML for Android and
iOS, the Fastlane match recipe, the Capacitor → RN plugin map, the
mushi-mushi SDK API mapping, the 6-week timeline, and the go/no-go
checklist — lives in the repo at
docs/migrations/capacitor-to-react-native.md.
This page is the public summary; the linked file is the contract.
TL;DR
| Path | Cost / month | Speed to first build | Maintenance | Recommended for |
|---|---|---|---|---|
| A: Expo SDK 55 + EAS Build | $19–$99 | Hours | Lowest | Teams that want zero CI ops |
| B: React Native CLI + GitHub Actions + Fastlane | $0 + GH Actions minutes (or $0 on a self-hosted Mac mini) | 2–3 days | Medium | Cost-sensitive, GitHub-Actions-native teams |
Both paths target React Native 0.83 with the New Architecture (Fabric / Bridgeless) on by default.
Web strategy
You have three options for the web experience after porting the native app:
- Keep Next.js, port only mobile — recommended for SEO-sensitive marketing sites.
- RN Web for the app shell + Next.js for marketing — one app, two surfaces.
- Full RN Web — single codebase, accept SEO trade-offs.
For most teams, option 1 is the right answer. Mushi Mushi happily
publishes both @mushi-mushi/web (to the marketing site) and
@mushi-mushi/react-native (to the new app) against the same project ID and
API key, in parallel.
Mushi Mushi during the migration
The single most important property: you do not change anything on the Mushi side. Same project, same API key, same admin console. Reports from the Capacitor build and the React Native build land in the same inbox.
API mapping at a glance
Capacitor (Mushi.*) | React Native | Notes |
|---|---|---|
Mushi.configure({ projectId, apiKey }) | <MushiProvider projectId apiKey> | Provider replaces the imperative call |
Mushi.report({ description, severity }) | useMushiReport()(...) hook | Returns { submitting, submit } |
Mushi.showWidget() | useMushiWidget().open() | Same effect |
Mushi.setUser({ id, email }) | useMushi().setUser(...) | Same |
Mushi.setMetadata({...}) | useMushi().setMetadata(...) | Same |
Mushi.flushQueue() | Auto on provider mount | Manual via useMushi().flush() |
triggerMode: 'shake' | config.widget.trigger: 'shake' | Same vocabulary |
captureScreenshot: boolean | config.capture.screenshot: 'on-report' | 'auto' | 'off' | Three-way to match web |
Before / after
// BEFORE — Capacitor
import { Mushi } from '@mushi-mushi/capacitor'
await Mushi.configure({
projectId: 'glot-it-prod',
apiKey: process.env.PUBLIC_MUSHI_KEY,
triggerMode: 'shake',
captureScreenshot: true,
})// AFTER — React Native
import { MushiProvider } from '@mushi-mushi/react-native'
export default function App() {
return (
<MushiProvider
projectId="glot-it-prod"
apiKey={process.env.EXPO_PUBLIC_MUSHI_KEY!}
config={{
widget: { trigger: 'shake' },
capture: { screenshot: 'on-report' },
}}
>
<RootNavigator />
</MushiProvider>
)
}Get the snippet from the admin console
The Install SDK card in the admin console (Onboarding, Projects → your project, Settings → Health) now exposes React Native, Expo, and Capacitor tabs alongside React / Vue / Svelte / Vanilla. The snippets are populated with your real project ID and (right after a key mint) your real API key.
The mobile trigger settings additionally persist to the project’s runtime SDK config, so future builds pick them up without a redeploy.
Or use the CLI
cd glot-it-rn
npx mushi-mushi initThe CLI auto-detects react-native, expo, and @capacitor/core and
writes the correct boilerplate. Capacitor users get
Mushi.configure(...) (not the older buggy Mushi.init(...) call).
What’s covered in the full guide
The full plan in
docs/migrations/capacitor-to-react-native.md
includes:
- Decision matrix — should you migrate at all?
- The web question — RN Web vs keep Next.js
- Pre-migration audit checklist (plugins, components, web-only APIs)
- Path A: Expo SDK 55 + EAS Build (one-page recipe)
- Path B (the chosen path): RN CLI + GitHub Actions + Fastlane
- Project bootstrap with the New Architecture
- Selectively pulling in Expo SDK packages without the Expo CLI
- Fastlane
matchfor code signing - Full Android
.github/workflows/android-release.yml - Full iOS
.github/workflows/ios-release.yml - Self-hosted Mac mini break-even table
- Required GitHub secrets in one place
- Capacitor → React Native plugin map (every
@capacitor/*plugin → its RN equivalent) - Mushi Mushi during the migration (full API mapping, dual-shipping plan)
- Recommended timeline (6 weeks, 1 engineer)
- Risks + mitigations
- Final go/no-go checklist
- Curated references
Related reading
@mushi-mushi/react-nativeSDK reference@mushi-mushi/capacitorSDK reference- React Native quickstart
- Capacitor quickstart
- Capacitor bottom-dock notes — for tuning the trigger position above bottom tab bars