π© Feature Flags β
Mobile feature flags are booleans served by Firebase Remote Config (lib/feature-flags/).
Flag Registry (lib/feature-flags/flags.ts) β
Every flag must be declared in FEATURE_FLAG_DEFAULTS before use. The key must exactly match the key in the Remote Config console.
export const FEATURE_FLAG_DEFAULTS = {
in_app_camera_capture: false,
} as const satisfies Record<string, boolean>;
export type FeatureFlagName = keyof typeof FEATURE_FLAG_DEFAULTS;Defaults must be "safe off" β the app must work correctly when the flag is false.
Initialization (lib/feature-flags/remote-config.ts) β
FeatureFlagsProvider calls initRemoteConfig() once on app start. It fetches and activates remote values; on any failure (e.g. no network) it falls back to the in-code defaults β it never throws.
Cache interval:
- Production: 1 hour
- Dev / Staging: 0 (always fetch fresh)
Reading Flags β
import { useFeatureFlag } from '@/hooks/use-feature-flag';
// Single flag (preferred)
const inAppCameraEnabled = useFeatureFlag('in_app_camera_capture');
// Full flag map
import { useFeatureFlags } from '@/hooks/use-feature-flags';
const flags = useFeatureFlags();TypeScript will error on unknown flag names.
One Template, Shared With Web β
Each Firebase project (tell-ia-dev, tell-ia-staging, tell-ia-production) has a single Remote Config template, shared by the mobile app and the web app (apps/agri-frontend/src/lib/remote-config/remote-config.ts, e.g. the app_promo_* keys). Mobile ignores keys it does not declare and logs one dev warning listing them β that is expected, not a signal to delete them.
Adding a Flag β
- Add the key + default to
FEATURE_FLAG_DEFAULTSinlib/feature-flags/flags.ts - Create the key in Remote Config in all three projects β a key missing from staging leaves the feature unreachable for QA
- Use
useFeatureFlag('your_flag_key')in the component - Guard the new behavior:
if (!isEnabled) return <OldBehavior />
Removing a Flag β
Store builds on an older runtime fingerprint never receive the OTA that removes a flag, so they keep reading the console key. The in-code default is false, so deleting a key that is true turns the feature off for those users.
- Code first (JS-only, OTA is fine): delete the key from
FEATURE_FLAG_DEFAULTS, inline the "on" behavior, and drop flag-off tests and Maestro branches. - Leave the console key at its current value.
- Delete the console key from all three projects only once Sentry release adoption shows the older builds have drained.
To edit a template from the CLI, pull it first (firebase remoteconfig:get --project tell-ia-<env> -o template.json), edit, then publish with firebase deploy --only remoteconfig --project tell-ia-<env> using a firebase.json of {"remoteconfig":{"template":"template.json"}}. The console shows unpublished edits as "Just now" β check firebase remoteconfig:versions:list for what is actually live.