Skip to content

0002 - Use React + Capacitor Over React Native

Status: Accepted Date: 2026-03-21 Author: Manuel Nucci

Context

Feel Pro Club (FPC) must run on three platforms: iOS, Android, and the web. The web experience is not optional — it serves as the entry point for the invitation flow. When a user receives an invitation link, they land on a web page that shows what they're joining (community details, who invited them, what to expect) before being prompted to download the native app. This requires a fast-loading, lightweight, genuine web experience.

Two main approaches were evaluated:

  1. React Native + react-native-web — Write a single React Native codebase and export it to the web using react-native-web.
  2. React (web-first) + Capacitor — Build a standard React web application and wrap it for native iOS/Android using Capacitor.

Key findings from evaluating React Native for web:

  • Many React Native components don't map cleanly to web equivalents, leading to layout inconsistencies and workarounds.
  • Third-party React Native library support for web is inconsistent — many popular libraries don't support the web target at all.
  • Styling via StyleSheet diverges from standard CSS, making it harder to achieve a polished, web-native feel.
  • The resulting web bundle is significantly heavier than a standard React application.
  • The web output feels like a mobile app running in a browser rather than a proper web experience.

Decision

We will use React + Capacitor to build FPC as a web-first application that also runs natively on iOS and Android.

  • The application is built as a standard React app using the web ecosystem (React 19, Vite, Tailwind CSS, shadcn/ui, React Router).
  • Capacitor wraps the web app into native iOS and Android shells, providing access to native device APIs (camera, push notifications, haptics, filesystem) through its plugin system.
  • The web app is deployed independently and serves as the primary experience for invitation links, onboarding previews, and desktop access.

Consequences

Positive

  • First-class web experience — Standard HTML/CSS/JS means fast page loads, proper SEO, and a natural web feel for the invitation flow.
  • Single codebase — One React codebase serves web, iOS, and Android without platform-specific forks.
  • Full web ecosystem access — Any React/web library works out of the box (shadcn/ui, TanStack Query, Zustand, React Hook Form, i18next, etc.) with no compatibility concerns.
  • Lower hiring bar — Standard React and web development skills transfer directly; no need for React Native expertise.
  • Progressive enhancement — Native capabilities are added incrementally via Capacitor plugins rather than being a requirement from day one.

Negative

  • Native performance ceiling — Complex animations, gesture-heavy interactions, and native list virtualization are harder to achieve compared to React Native's direct native rendering.
  • Non-native UI feel — The app won't automatically adopt platform-specific UI conventions (iOS navigation patterns, Android Material Design) without explicit effort.
  • Smaller plugin ecosystem — Capacitor's plugin ecosystem is smaller than React Native's, which may require writing custom plugins for less common native APIs.

Mitigations

  • FPC is a community and content management app, not a game or media-heavy application — performance-intensive native rendering is not a core requirement.
  • CSS animations, web APIs, and Capacitor's built-in plugins (camera, push notifications, geolocation, haptics) cover the vast majority of FPC's native needs.
  • Custom Capacitor plugins can be written for edge cases that the existing ecosystem doesn't cover.
  • Platform-specific styling can be applied via CSS media queries and Capacitor's platform detection API where needed.