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-association and assetlinks.json on the RDP domain.
  • Build a simple invite flow: /invite/:code route 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.

PermissionFeatures
CameraQR code scanning for event check-in, photo/video capture of drills
Photo Library / StorageSave and upload photos/videos from range days
MicrophoneAudio recording when capturing video of drills
Push NotificationsEvent reminders, challenge invites, friend requests, score updates
CalendarSave 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)

KeyDescription
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/ and apps/android/ scaffolds need bundle ID updates from com.trexarms.rangedaypro to com.range.day
  • Android build.gradle.kts needs targetSdk bumped to 36
  • Permission declarations and Info.plist descriptions need to be added to both platform configs
  • Firebase google-services.json needs to be added to the Android project (from existing Firebase project)
  • Deep linking infrastructure (apple-app-site-association, assetlinks.json, /invite/:code route) is implementation work for a later milestone
  • No Branch.io SDK to integrate — simplifies both build pipelines