App Configuration
The main app configuration is managed through app.json:
{
"expo": {
"name": "incidents-app",
"slug": "incidents-app",
"version": "1.0.0",
"orientation": "portrait",
"scheme": "fluxomobile",
"userInterfaceStyle": "automatic",
"newArchEnabled": true
}
}
Environment Variables
The app uses environment variables for sensitive configuration:
EXPO_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
EXPO_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
All public environment variables must be prefixed with EXPO_PUBLIC_ to be accessible in the app.
Supabase Configuration
The Supabase client is configured in src/services/supabase.ts:
import { createClient } from '@supabase/supabase-js'
import * as SecureStore from 'expo-secure-store'
const supabaseUrl = process.env.EXPO_PUBLIC_SUPABASE_URL as string
const supabaseAnonKey = process.env.EXPO_PUBLIC_SUPABASE_ANON_KEY as string
const ExpoSecureStoreAdapter = {
getItem: SecureStore.getItemAsync,
setItem: SecureStore.setItemAsync,
removeItem: SecureStore.deleteItemAsync
}
export const supabase = createClient(
supabaseUrl,
supabaseAnonKey,
{
auth: {
storage: ExpoSecureStoreAdapter,
persistSession: true,
autoRefreshToken: true,
detectSessionInUrl: false
}
}
)
Key Configuration Options
- storage: Uses Expo Secure Store for encrypted session storage
- persistSession: Keeps users logged in across app restarts
- autoRefreshToken: Automatically refreshes auth tokens
- detectSessionInUrl: Disabled for mobile (deep linking not used for auth)
iOS-specific settings in app.json:{
"ios": {
"supportsTablet": true,
"bundleIdentifier": "com.yourcompany.incidentsapp"
}
}
Build Properties
{
"plugins": [
[
"expo-build-properties",
{
"ios": {
"useFrameworks": "static"
}
}
]
]
}
Android-specific settings in app.json:{
"android": {
"adaptiveIcon": {
"backgroundColor": "#E6F4FE",
"foregroundImage": "./assets/images/android-icon-foreground.png",
"backgroundImage": "./assets/images/android-icon-background.png",
"monochromeImage": "./assets/images/android-icon-monochrome.png"
},
"edgeToEdgeEnabled": true,
"predictiveBackGestureEnabled": false,
"package": "com.yourcompany.incidentsapp"
}
}
edgeToEdgeEnabled allows content to draw behind system bars for a modern look.
Theme Configuration
Theme settings are managed through the custom useTheme hook:
export type ThemeMode = "light" | "dark" | "system";
export type ActiveTheme = "light" | "dark";
const THEME_KEY = "app_theme_preference";
export const useTheme = () => {
const systemColorScheme = useSystemColorScheme();
const [themeMode, setThemeMode] = useState<ThemeMode>("light");
// Determine active theme based on user preference
const activeTheme: ActiveTheme =
themeMode === "system"
? (systemColorScheme ?? "light")
: themeMode;
const setTheme = async (mode: ThemeMode) => {
await SecureStore.setItemAsync(THEME_KEY, mode);
setThemeMode(mode);
};
return { themeMode, activeTheme, setTheme, isLoading };
};
Theme Constants
Define theme colors in constants/theme.ts:
export const Colors = {
light: {
text: '#000',
background: '#F7FAFC',
card: '#FFFFFF',
primary: '#0099ff',
border: '#E2E8F0',
},
dark: {
text: '#FFFFFF',
background: '#0B0B0B',
card: '#1A1A1A',
primary: '#0099ff',
border: '#2D3748',
},
};
Notification Configuration
Notification preferences are managed per user role:
hooks/settings/use-notifications.ts
export const useNotifications = (storageKey: string) => {
const [notifications, setNotifications] = useState(false);
const initializeNotifications = async () => {
const value = await SecureStore.getItemAsync(storageKey);
setNotifications(value === 'true');
};
const handleNotificationToggle = async (value: boolean) => {
await SecureStore.setItemAsync(storageKey, String(value));
setNotifications(value);
};
return {
notifications,
initializeNotifications,
handleNotificationToggle
};
};
Storage Keys
guest_notifications - Guest user notification preferences
employee_notifications - Employee notification preferences
Deep Linking Configuration
The app is configured with a custom URL scheme:
{
"scheme": "fluxomobile"
}
This allows deep links like:
fluxomobile://incidents/123
fluxomobile://settings
Font Configuration
Fonts are loaded in the root layout:
import {
Poppins_400Regular,
Poppins_500Medium,
Poppins_600SemiBold,
Poppins_700Bold,
} from "@expo-google-fonts/poppins";
import { useFonts } from "expo-font";
export default function RootLayout() {
const [loaded] = useFonts({
DtmF: require("../assets/fonts/DebiUsarEsteFontRegular.ttf"),
PoppinsRegular: Poppins_400Regular,
PoppinsMedium: Poppins_500Medium,
PoppinsSemiBold: Poppins_600SemiBold,
PoppinsBold: Poppins_700Bold,
});
useEffect(() => {
if (loaded) SplashScreen.hideAsync();
}, [loaded]);
if (!loaded) return null;
return <Stack screenOptions={{ headerShown: false }} />;
}
Splash Screen Configuration
Splash screen settings in app.json:
{
"plugins": [
[
"expo-splash-screen",
{
"image": "./assets/images/splash-icon.png",
"imageWidth": 200,
"resizeMode": "contain",
"backgroundColor": "#ffffff",
"dark": {
"backgroundColor": "#000000"
}
}
]
]
}
Plugins Configuration
Required Expo plugins:
{
"plugins": [
"expo-router",
"react-native-bottom-tabs",
"expo-secure-store",
"expo-font",
"@react-native-community/datetimepicker",
"expo-barcode-scanner",
[
"expo-build-properties",
{
"ios": {
"useFrameworks": "static"
}
}
]
]
}
Security Configuration
Secure Storage
All sensitive data is stored using Expo Secure Store:import * as SecureStore from 'expo-secure-store';
// Store session
await SecureStore.setItemAsync('guest_session', JSON.stringify(session));
// Retrieve session
const session = await SecureStore.getItemAsync('guest_session');
Route Protection
Each role has protected routes via layout guards:app/(empleado)/_layout.tsx
export default function EmpleadoLayout() {
useEffect(() => {
const checkEmpleado = async () => {
const { data } = await supabase.auth.getSession();
if (!data.session) {
router.replace('/(auth)/login');
return;
}
const { data: profile } = await supabase
.from('profiles')
.select('role')
.eq('id', data.session.user.id)
.single();
if (profile?.role !== 'empleado') {
router.replace('/(auth)/login');
}
};
checkEmpleado();
}, []);
return <Stack screenOptions={{ headerShown: false }} />;
}
TypeScript Configuration
The app uses TypeScript with strict mode:
{
"extends": "expo/tsconfig.base",
"compilerOptions": {
"strict": true,
"paths": {
"@/*": ["./*"]
}
}
}
Next Steps
Guest Features
Learn about guest user functionality
Employee Features
Explore employee capabilities