LOG 040 · TECHNICAL · 2024-01-01
Replaced our React Native app by shipping the web app through Capacitor
2 min read
Situation
Goodpods is a podcast app with a Next.js web app and, at the time, a separate React Native mobile app. The client had cut our agency team from four full-time developers plus a QA engineer down to two, and we no longer had a dedicated React Native engineer. Every feature the client wanted took us literally 5x as long to add to the React Native app as to the web app, and testing needed physical devices or slow simulators. A proper upgrade off our very old React Native version would have cost a whole sprint, and the client was reluctant to fund that maintenance.
Task
I made the call and pushed for it: build the mobile apps from the web codebase using Capacitor, in parallel with the existing app, with the plan of replacing React Native entirely.
Action
The first hard problem was that our Next.js app was server-rendered, and a Capacitor app is a static bundle running in a native WebView. I added a static SPA build path alongside the normal SSR build, which meant unwinding server-only assumptions across nearly every page, so one codebase produced both the website and the app bundle. I got the app building and running on iOS first, then Android. The next problem was Firebase auth: we supported Google, Apple, Twitter and Facebook sign-in, and each behaves differently in a native app than in a browser. A good Capacitor plugin handled the Firebase side, so I worked through the providers one at a time on both platforms. Facebook was the worst by far, mostly their admin platform rather than code: getting our package approved to connect and completing all their required surveys. We only wrote native code where the web genuinely could not do the job: custom Swift and Java plugins for the audio player, plus code for offline mode and downloads.
Result
95% of the web codebase shipped to native unchanged. We replaced the app in the existing store listings, and ratings improved rather than dipped, because the web app was a superset of the old app’s features: dark mode, leaderboards and a better library all arrived at once, and the app was snappier. We judged it good enough through production crash monitoring, testing on real devices, and positive user feedback. The React Native codebase was retired, and from then on every web release could ship to iOS and Android after a quick test.