Native App Configuration
Date: 2026-05-20 Status: Accepted
Decision
Seven configuration decisions for the new native iOS (Swift) and Android (Kotlin) apps that replace the existing FlutterFlow app (com.range.day). These decisions were made after reviewing the legacy FlutterFlow app’s iOS and Android configs in tmp/range_day/.
Context
The legacy FlutterFlow app has ~70k users across iOS and Android. The new native apps must replace the old app as an in-place update (same app store listings), not a new listing. This constraint drives several decisions below.
1. Bundle ID / Package Name
Decision: Keep com.range.day on both platforms.
The new apps are updates to the existing app store listings, not new apps. Changing the bundle ID would create a separate listing, requiring 70k users to manually find and install the new app, and losing all existing ratings and reviews.
Implementation: update the current scaffolds from com.trexarms.rangedaypro to com.range.day.
2. Firebase Project for Push Notifications
Decision: Reuse the existing range-day Firebase project (T.REX ARMS-owned GCP account). Keep existing app entries.
- Firebase is only needed for FCM (Android push delivery). iOS uses APNs directly.
- Since the bundle ID stays the same, the existing Firebase app entries work as-is. FCM tokens refresh naturally on app update.
- No Firebase SDK on the server. The Axum server makes direct HTTP calls to APNs (iOS) and FCM (Android) APIs.
- No other Firebase services are needed (auth, crashlytics, analytics are handled by RDP’s own stack).
3. Deep Linking Strategy
Decision: Native deep linking only. No Branch.io.
- Apple Universal Links (iOS) + Android App Links for direct deep linking.
- Host
apple-app-site-associationandassetlinks.jsonon the RDP domain. - Build a simple invite flow:
/invite/:coderoute on the server/marketing site.- User has app installed: Universal Link opens directly to invite/enrollment screen.
- User doesn’t have app: landing page with app store buttons and invite code displayed.
- After install, user taps the same link again (Universal Links now work) or enters the code manually during signup.
- Branch.io’s deferred deep linking (remember link through install) is not needed for MVP. Coaches onboard church security team members directly; a second tap or manual code entry is acceptable friction.
- No third-party SDK dependency, no monthly cost. Can revisit if organic/viral growth makes deferred linking valuable.
4. Custom URL Scheme
Decision: Keep rangeday:// on both platforms.
Must match the existing app since the new app is an in-place update with the same bundle ID. Existing links in the wild (emails, texts, QR codes) continue to work.
5. MVP Permissions
Decision: Five permissions for MVP, based on documented feature requirements.
| Permission | Features |
|---|---|
| Camera | QR code scanning for event check-in, photo/video capture of drills |
| Photo Library / Storage | Save and upload photos/videos from range days |
| Microphone | Audio recording when capturing video of drills |
| Push Notifications | Event reminders, challenge invites, friend requests, score updates |
| Calendar | Save range days and events to device calendar with reminders |
Not needed for MVP:
- Contacts — legacy app had it, MVP spec doesn’t require it
- Location (GPS) — locations are text-based addresses, no GPS needed
- Bluetooth — shot timer BLE integration is explicitly post-MVP
iOS Permission Descriptions (Info.plist)
| Key | Description |
|---|---|
| NSCameraUsageDescription | ”Range Day uses your camera to scan QR codes for event check-in, and to capture photos and videos of your drills.” |
| NSMicrophoneUsageDescription | ”Range Day needs microphone access to record audio when capturing video of your drills.” |
| NSPhotoLibraryUsageDescription | ”Range Day needs access to your photo library to save and upload photos and videos from your range days.” |
| NSCalendarsUsageDescription | ”Range Day can save your upcoming range days and events to your calendar with reminders.” |
| Push Notifications prompt | ”Stay up to date with event reminders, challenge invites, and friend requests.” |
Android declares permissions in the manifest without custom descriptions.
6. Rich Push Notifications
Decision: Defer past v1.
MVP push notifications are all transactional and text-only. Rich push (images in notifications) requires a Notification Service Extension on iOS but no additional permissions. The same APNs/FCM infrastructure supports both. Add when there’s a concrete use case (product announcements, marketing pushes, score summary graphics).
7. Android Target SDK
Decision: Bump targetSdk from 35 to 36.
The legacy FlutterFlow app was already at 36. Google Play requires targeting recent SDK levels. Bumping now while the app is a scaffold carries zero risk.
Consequences
- The
apps/ios/andapps/android/scaffolds need bundle ID updates fromcom.trexarms.rangedayprotocom.range.day - Android
build.gradle.ktsneeds targetSdk bumped to 36 - Permission declarations and Info.plist descriptions need to be added to both platform configs
- Firebase
google-services.jsonneeds to be added to the Android project (from existing Firebase project) - Deep linking infrastructure (
apple-app-site-association,assetlinks.json,/invite/:coderoute) is implementation work for a later milestone - No Branch.io SDK to integrate — simplifies both build pipelines