React Native has received strong web support over the past few years, eliminating the need to build separate apps for mobile and web. Using Expo to build a cross-platform app makes development faster and easier. API Routes are used to avoid directly accessing Firestore from the client. See the Firebase section below for more details.
Next.js is a powerful framework for building SEO-optimized websites and is used here for building landing pages.
Firebase is a backend service provided by Google that offers a wide range of functionality out of the box for authentication, database management, storage, analytics, crash reporting and other services. I chose it over Supabase because it grants access to the entire Google Cloud Platform ecosystem when needed, and I did not opt for AWS Amplify due to AWS’s higher complexity compared to Google Cloud Platform.
Note that the client app should not interact directly with Firestore. Instead, it should use API Routes, through which the Firebase Admin SDK performs sensitive operations such as reading from and writing to the database. This approach is more secure and offers better control over data flow. Firestore Security Rules should restrict all queries by default so that only the Admin SDK can access the database.
Tailwind CSS is a utility‑first framework that enables rapid UI development. Here, it’s used to style both the website and the mobile app. NativeWind brings Tailwind CSS to React Native, ensuring a consistent styling experience across platforms.
- TypeScript as the programming language
- Prettier for formating code according to the rules
- ESLint for checking code quality and formatting
- Create a new Expo app in Expo Console
- Create a new iOS app in Apple Developer Console
- Create a new Android app in Google Play Console
- Create a new Firebase project in Firebase Console
- Set up App Check following App Attest, DeviceCheck, App Integrity and Recaptcha guides
- Create an App Check debug token for iOS, Android and web apps (use the same token for all platforms)
- In project settings, download
google-services.json
,GoogleService-Info.plist
andservice-account.json
files - Create Firestore database and find your database url for the next step
- Add environment variables to Expo, mark them as Sensitive:
- EXPO_PUBLIC_FIREBASE_API_KEY
- EXPO_PUBLIC_FIREBASE_APP_CHECK_DEBUG_TOKEN
- EXPO_PUBLIC_FIREBASE_APP_ID
- EXPO_PUBLIC_FIREBASE_AUTH_DOMAIN
- EXPO_PUBLIC_FIREBASE_DATABASE_URL
- EXPO_PUBLIC_FIREBASE_MEASUREMENT_ID
- EXPO_PUBLIC_FIREBASE_MESSAGING_SENDER_ID
- EXPO_PUBLIC_FIREBASE_PROJECT_ID
- EXPO_PUBLIC_FIREBASE_RECAPTCHA_SITE_KEY
- EXPO_PUBLIC_FIREBASE_STORAGE_BUCKET
- GOOGLE_SERVICES_FILE_ADMIN
- GOOGLE_SERVICES_FILE_ANDROID
- GOOGLE_SERVICES_FILE_IOS
- Set values in the
app/app.config.ts
file
- Install dependencies
cd app
npm ci
- Pull environment variables:
npx eas login
npm run pull-env
- Start the development server and follow instructions in the terminal
npm run ios
# or
npm run android
# or
npm run web
- Install dependencies
cd website
npm ci
- Start the development server
npm run dev