npm package: @ridwan-retainer/app-shell
Description: Foundational runtime shell for app lifecycle, providers, and navigation
Latest version: 0.1.1

# @ridwan-retainer/app-shell

A comprehensive, production-ready application runtime framework for React Native apps. Provides lifecycle management, state management, navigation, error handling, remote configuration, and more out of the box.

[![npm version](https://badge.fury.io/js/@ridwan-retainer%2Fapp-shell.svg)](https://www.npmjs.com/package/@ridwan-retainer/app-shell)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

## 📋 Table of Contents

- [Features](#features)
- [Installation](#installation)
- [Quick Start](#quick-start)
- [Architecture](#architecture)
- [API Reference](#api-reference)
  - [Lifecycle Management](#lifecycle-management)
  - [State Management](#state-management)
  - [Navigation](#navigation)
  - [Error Handling](#error-handling)
  - [Loading & Splash](#loading--splash)
  - [Remote Config](#remote-config)
  - [Adapters](#adapters)
- [Complete Examples](#complete-examples)
- [Best Practices](#best-practices)
- [Migration Guide](#migration-guide)
- [Troubleshooting](#troubleshooting)

## ✨ Features

### Core Features
- **🔄 Lifecycle Management**: Comprehensive app lifecycle hooks and state management
- **🏪 State Management**: Built-in Zustand stores for theme, settings, feature flags, and telemetry
- **🧭 Navigation**: Type-safe React Navigation integration with deep linking
- **❌ Error Handling**: Global error boundaries with Sentry integration
- **⏳ Loading States**: Sophisticated loading and splash screen management
- **🔧 Remote Config**: Firebase Remote Config integration for feature flags
- **🔌 Adapter System**: Plugin architecture for extending functionality
- **📦 Provider Composition**: Clean provider nesting and composition
- **📝 TypeScript**: Full type safety throughout
- **⚡ Performance**: Optimized rendering and state updates
- **✅ Well-tested**: Extensive test coverage

### State Stores
- **Theme**: Dark/light mode with custom theme support
- **Settings**: App-wide settings persistence
- **Feature Flags**: Runtime feature toggles
- **Telemetry**: Usage tracking and analytics

## 📦 Installation

```bash
npm install @ridwan-retainer/app-shell
```

### Required Peer Dependencies

```bash
npm install @react-navigation/native \
            react-native-screens \
            react-native-safe-area-context \
            react \
            react-native
```

### Optional Peer Dependencies

For full functionality:

```bash
# For AsyncStorage persistence
npm install @react-native-async-storage/async-storage

# For Remote Config
npm install @react-native-firebase/app @react-native-firebase/remote-config

# For Error Tracking
npm install @sentry/react-native

# For Splash Screens
npm install react-native-bootsplash
```

## 🚀 Quick Start

### Basic Setup

```typescript
import { LifecycleProvider } from '@ridwan-retainer/app-shell';
import { NavigationContainer } from '@react-navigation/native';

function App() {
  return (
    <LifecycleProvider
      onInitialize={async () => {
        // Initialize your app (API clients, analytics, etc.)
        console.log('App initializing...');
      }}
      onReady={() => {
        // App is ready to use
        console.log('App ready!');
      }}
    >
      <NavigationContainer>
        <YourAppContent />
      </NavigationContainer>
    </LifecycleProvider>
  );
}
```

### With Error Boundary

```typescript
import {
  LifecycleProvider,
  ErrorBoundary,
  ErrorFallback,
} from '@ridwan-retainer/app-shell';

function App() {
  return (
    <ErrorBoundary
      FallbackComponent={ErrorFallback}
      onError={(error, stackTrace) => {
        console.error('App error:', error, stackTrace);
        // Report to error tracking service
      }}
    >
      <LifecycleProvider>
        <YourApp />
      </LifecycleProvider>
    </ErrorBoundary>
  );
}
```

### With All Features

```typescript
import {
  LifecycleProvider,
  ErrorBoundary,
  LoadingProvider,
  RemoteConfigProvider,
  initializeSentry,
} from '@ridwan-retainer/app-shell';

// Initialize Sentry
initializeSentry({
  dsn: 'your-sentry-dsn',
  environment: __DEV__ ? 'development' : 'production',
});

function App() {
  return (
    <ErrorBoundary>
      <LifecycleProvider
        onInitialize={async () => {
          // Load critical data
          await loadAuthState();
          await initializeAnalytics();
        }}
      >
        <RemoteConfigProvider>
          <LoadingProvider>
            <NavigationContainer>
              <YourApp />
            </NavigationContainer>
          </LoadingProvider>
        </RemoteConfigProvider>
      </LifecycleProvider>
    </ErrorBoundary>
  );
}
```

## 🏗 Architecture

### Provider Hierarchy

```
ErrorBoundary (Top-level error catching)
  └─ LifecycleProvider (App lifecycle management)
      └─ RemoteConfigProvider (Feature flags & config)
          └─ LoadingProvider (Loading states & splash)
              └─ NavigationContainer (React Navigation)
                  └─ Your App Content
```

### Data Flow

```
User Action → State Update → Zustand Store → Component Re-render
               ↓
         Side Effects (Persistence, Analytics, etc.)
```

## 📚 API Reference

### Lifecycle Management

#### `<LifecycleProvider />`

Manages app lifecycle and initialization.

```typescript
import { LifecycleProvider } from '@ridwan-retainer/app-shell';

<LifecycleProvider
  onInitialize={async () => {
    // Run once on app start
    await loadUserData();
    await connectWebSocket();
  }}
  onReady={() => {
    // Called when initialization completes
    console.log('App is ready!');
  }}
  onBackground={() => {
    // App moved to background
    saveCurrentState();
  }}
  onForeground={() => {
    // App returned to foreground
    refreshData();
  }}
>
  {children}
</LifecycleProvider>
```

**Props:**
```typescript
{
  onInitialize?: () => Promise<void> | void;
  onReady?: () => void;
  onBackground?: () => void;
  onForeground?: () => void;
  onError?: (error: Error) => void;
  children: ReactNode;
}
```

#### `useAppState()`

Monitor app foreground/background state.

```typescript
import { useAppState } from '@ridwan-retainer/app-shell';

function DataSync() {
  const appState = useAppState();

  useEffect(() => {
    if (appState === 'active') {
      syncData();
    }
  }, [appState]);

  return null;
}
```

**Returns:** `'active' | 'background' | 'inactive'`

#### `useStartupType()`

Determine if app is cold start or warm start.

```typescript
import { useStartupType } from '@ridwan-retainer/app-shell';

function Analytics() {
  const startupType = useStartupType();

  useEffect(() => {
    logEvent('app_start', { type: startupType });
  }, []);
}
```

**Returns:** `'cold' | 'warm'`

#### `LifecycleManager`

Programmatic lifecycle control.

```typescript
import { LifecycleManager } from '@ridwan-retainer/app-shell';

// Get lifecycle instance
const lifecycle = LifecycleManager.getInstance();

// Listen to events
lifecycle.on('initialize', async () => {
  await setupApp();
});

lifecycle.on('ready', () => {
  console.log('App ready');
});

// Trigger lifecycle phase
await lifecycle.initialize();
```

### State Management

All stores are built with Zustand and include:
- Type-safe actions and selectors
- Automatic persistence (where applicable)
- Optimized re-renders

#### Theme Store

```typescript
import { useTheme, useThemeActions } from '@ridwan-retainer/app-shell';

function ThemeToggle() {
  const theme = useTheme();
  const { toggleTheme, setTheme } = useThemeActions();

  return (
    <View>
      <Text>Current theme: {theme.mode}</Text>
      <Button title="Toggle Theme" onPress={toggleTheme} />
      <Button title="Dark Mode" onPress={() => setTheme('dark')} />
      <Button title="Light Mode" onPress={() => setTheme('light')} />
    </View>
  );
}
```

**Theme Type:**
```typescript
{
  mode: 'light' | 'dark';
  colors: {
    primary: string;
    background: string;
    text: string;
    border: string;
    // ... more colors
  };
}
```

**Custom Theme:**
```typescript
import { useThemeActions } from '@ridwan-retainer/app-shell';

const customTheme = {
  mode: 'dark',
  colors: {
    primary: '#FF6B6B',
    background: '#1A1A1A',
    text: '#FFFFFF',
    // ...
  },
};

const { setCustomTheme } = useThemeActions();
setCustomTheme(customTheme);
```

#### Settings Store

```typescript
import {
  useSettings,
  useSettingsActions,
} from '@ridwan-retainer/app-shell';

function SettingsScreen() {
  const settings = useSettings();
  const { updateSetting, resetSettings } = useSettingsActions();

  return (
    <View>
      <Switch
        value={settings.notifications}
        onValueChange={(value) =>
          updateSetting('notifications', value)
        }
      />
      <Switch
        value={settings.analytics}
        onValueChange={(value) =>
          updateSetting('analytics', value)
        }
      />
      <Button title="Reset" onPress={resetSettings} />
    </View>
  );
}
```

**Built-in Settings:**
```typescript
{
  notifications: boolean;
  analytics: boolean;
  [key: string]: any; // Custom settings
}
```

#### Feature Flags Store

```typescript
import {
  useFeatureFlag,
  useFeatureFlagActions,
} from '@ridwan-retainer/app-shell';

function NewFeature() {
  const isEnabled = useFeatureFlag('new_feature');
  const { setFlag } = useFeatureFlagActions();

  // Enable for testing
  useEffect(() => {
    if (__DEV__) {
      setFlag('new_feature', true);
    }
  }, []);

  if (!isEnabled) return null;

  return <NewFeatureComponent />;
}
```

**Actions:**
```typescript
{
  setFlag: (key: string, value: boolean) => void;
  setFlags: (flags: Record<string, boolean>) => void;
  resetFlags: () => void;
}
```

#### Telemetry Store

```typescript
import {
  useTelemetry,
  useTelemetryActions,
} from '@ridwan-retainer/app-shell';

function ScreenView({ screenName }: { screenName: string }) {
  const { trackEvent } = useTelemetryActions();

  useEffect(() => {
    trackEvent('screen_view', { screen: screenName });
  }, [screenName]);

  return null;
}

// Usage
function ProfileScreen() {
  return (
    <>
      <ScreenView screenName="profile" />
      <ProfileContent />
    </>
  );
}
```

**Telemetry Actions:**
```typescript
{
  trackEvent: (name: string, properties?: Record<string, any>) => void;
  trackScreen: (screenName: string) => void;
  setUserId: (userId: string) => void;
  clearUserId: () => void;
}
```

### Navigation

#### `<NavigationContainer />`

Type-safe navigation container wrapper.

```typescript
import { NavigationContainer } from '@ridwan-retainer/app-shell';

type RootStackParamList = {
  Home: undefined;
  Profile: { userId: string };
  Settings: undefined;
};

function App() {
  return (
    <NavigationContainer<RootStackParamList>
      linking={{
        prefixes: ['myapp://'],
        config: {
          screens: {
            Home: 'home',
            Profile: 'profile/:userId',
            Settings: 'settings',
          },
        },
      }}
      onReady={() => {
        console.log('Navigation ready');
      }}
    >
      <RootNavigator />
    </NavigationContainer>
  );
}
```

#### `useTypedNavigation()`

Type-safe navigation hook.

```typescript
import { useTypedNavigation } from '@ridwan-retainer/app-shell';

type RootStackParamList = {
  Home: undefined;
  Profile: { userId: string };
};

function HomeScreen() {
  const navigation = useTypedNavigation<RootStackParamList>();

  const goToProfile = (userId: string) => {
    // Type-safe: TypeScript knows userId is required
    navigation.navigate('Profile', { userId });
  };

  return <Button title="View Profile" onPress={() => goToProfile('123')} />;
}
```

#### `useTypedRoute()`

Type-safe route params hook.

```typescript
import { useTypedRoute } from '@ridwan-retainer/app-shell';

type ProfileScreenParams = {
  userId: string;
  tab?: 'posts' | 'photos';
};

function ProfileScreen() {
  const route = useTypedRoute<ProfileScreenParams>();

  const { userId, tab = 'posts' } = route.params;

  return (
    <View>
      <Text>User ID: {userId}</Text>
      <Text>Active Tab: {tab}</Text>
    </View>
  );
}
```

#### `navigationRef`

Programmatic navigation without hooks.

```typescript
import { navigationRef } from '@ridwan-retainer/app-shell';

// Navigate from anywhere (e.g., push notification handler)
function handleNotificationPress(notificationData: any) {
  if (navigationRef.isReady()) {
    navigationRef.navigate('Notification', {
      id: notificationData.id,
    });
  }
}
```

### Error Handling

#### `<ErrorBoundary />`

Catch and handle React errors.

```typescript
import { ErrorBoundary, ErrorFallback } from '@ridwan-retainer/app-shell';

<ErrorBoundary
  FallbackComponent={ErrorFallback}
  onError={(error, errorInfo) => {
    // Log to error tracking service
    Sentry.captureException(error, { extra: errorInfo });
  }}
  onReset={() => {
    // Reset app state if needed
    resetAppState();
  }}
>
  <App />
</ErrorBoundary>
```

**Props:**
```typescript
{
  FallbackComponent: React.ComponentType<FallbackProps>;
  onError?: (error: Error, errorInfo: ErrorInfo) => void;
  onReset?: () => void;
  resetKeys?: string[]; // Keys that trigger reset when changed
  children: ReactNode;
}
```

#### `<ErrorFallback />`

Default error UI component.

```typescript
import { ErrorFallback } from '@ridwan-retainer/app-shell';

// Use as-is
<ErrorBoundary FallbackComponent={ErrorFallback}>

// Or customize
function CustomErrorFallback({ error, resetError }: FallbackProps) {
  return (
    <View>
      <Text>Something went wrong</Text>
      <Text>{error.message}</Text>
      <Button title="Try Again" onPress={resetError} />
    </View>
  );
}
```

#### `useErrorHandler()`

Programmatically handle errors.

```typescript
import { useErrorHandler } from '@ridwan-retainer/app-shell';

function DataLoader() {
  const handleError = useErrorHandler();

  const loadData = async () => {
    try {
      const data = await fetchData();
      return data;
    } catch (error) {
      // This will trigger the nearest ErrorBoundary
      handleError(error);
    }
  };

  return <Button onPress={loadData} />;
}
```

#### `initializeSentry()`

Initialize Sentry error tracking.

```typescript
import { initializeSentry } from '@ridwan-retainer/app-shell';

initializeSentry({
  dsn: 'your-sentry-dsn',
  environment: __DEV__ ? 'development' : 'production',
  enableInExpoDevelopment: false,
  debug: __DEV__,
  tracesSampleRate: 1.0,
});
```

### Loading & Splash

#### `<LoadingProvider />`

Manage loading states and splash screen.

```typescript
import { LoadingProvider } from '@ridwan-retainer/app-shell';

<LoadingProvider
  onReady={() => {
    console.log('App ready, hiding splash');
  }}
>
  {children}
</LoadingProvider>
```

#### `useLoadingState()`

Control loading states.

```typescript
import { useLoadingState } from '@ridwan-retainer/app-shell';

function DataFetcher() {
  const { setLoading, clearLoading } = useLoadingState();

  const fetchData = async () => {
    setLoading('data_fetch', 'Loading data...');
    try {
      const data = await api.getData();
      return data;
    } finally {
      clearLoading('data_fetch');
    }
  };

  return <Button onPress={fetchData} />;
}
```

#### `useAppReady()`

Check if app is ready.

```typescript
import { useAppReady } from '@ridwan-retainer/app-shell';

function App() {
  const isReady = useAppReady();

  if (!isReady) {
    return <SplashScreen />;
  }

  return <MainApp />;
}
```

#### `useSplashControl()`

Manually control splash screen.

```typescript
import { useSplashControl } from '@ridwan-retainer/app-shell';

function Initializer() {
  const { hideSplash } = useSplashControl();

  useEffect(() => {
    const init = async () => {
      await loadCriticalData();
      await setupServices();
      hideSplash(); // Hide splash when ready
    };
    init();
  }, []);

  return null;
}
```

### Remote Config

#### `<RemoteConfigProvider />`

Integrate Firebase Remote Config.

```typescript
import { RemoteConfigProvider } from '@ridwan-retainer/app-shell';

<RemoteConfigProvider
  defaults={{
    enable_new_feature: false,
    api_timeout: 5000,
    theme_color: '#007AFF',
  }}
  minimumFetchInterval={3600} // 1 hour
>
  {children}
</RemoteConfigProvider>
```

#### `useFeatureFlag()`

Check feature flags from Remote Config.

```typescript
import { useFeatureFlag } from '@ridwan-retainer/app-shell';

function ExperimentalFeature() {
  const isEnabled = useFeatureFlag('enable_new_ui');

  if (!isEnabled) return null;

  return <NewUIComponent />;
}
```

#### `useConfigValue()`

Get any config value.

```typescript
import { useConfigValue } from '@ridwan-retainer/app-shell';

function ApiClient() {
  const timeout = useConfigValue<number>('api_timeout', 5000);
  const baseUrl = useConfigValue<string>('api_base_url', 'https://api.example.com');

  // Use in fetch config
  return { timeout, baseUrl };
}
```

#### `useRemoteConfig()`

Access full Remote Config API.

```typescript
import { useRemoteConfig } from '@ridwan-retainer/app-shell';

function ConfigDebug() {
  const { config, isLoading, refresh } = useRemoteConfig();

  return (
    <View>
      <Text>Config: {JSON.stringify(config, null, 2)}</Text>
      <Button title="Refresh" onPress={refresh} disabled={isLoading} />
    </View>
  );
}
```

### Adapters

The adapter system allows you to extend app-shell functionality.

#### Creating an Adapter

```typescript
import { AdapterDefinition } from '@ridwan-retainer/app-shell';

interface AnalyticsAdapter {
  trackEvent: (event: string, properties?: any) => void;
  trackScreen: (screenName: string) => void;
  setUserId: (userId: string) => void;
}

const analyticsAdapter: AdapterDefinition<AnalyticsAdapter> = {
  name: 'analytics',
  version: '1.0.0',
  
  initialize: async (config) => {
    // Initialize analytics SDK
    await AnalyticsSDK.init(config.apiKey);
    
    return {
      trackEvent: (event, properties) => {
        AnalyticsSDK.track(event, properties);
      },
      trackScreen: (screenName) => {
        AnalyticsSDK.screen(screenName);
      },
      setUserId: (userId) => {
        AnalyticsSDK.identify(userId);
      },
    };
  },
  
  cleanup: async () => {
    // Cleanup if needed
    await AnalyticsSDK.flush();
  },
};
```

#### Using an Adapter

```typescript
import { AdapterRegistry, useAdapter } from '@ridwan-retainer/app-shell';

// Register adapter
AdapterRegistry.register(analyticsAdapter);

// Use in component
function TrackingComponent() {
  const analytics = useAdapter<AnalyticsAdapter>('analytics');

  useEffect(() => {
    analytics?.trackScreen('home');
  }, []);

  const trackClick = () => {
    analytics?.trackEvent('button_click', { button: 'subscribe' });
  };

  return <Button onPress={trackClick} />;
}
```

## 💡 Complete Examples

### Example 1: Production App Setup

```typescript
import {
  ErrorBoundary,
  LifecycleProvider,
  LoadingProvider,
  RemoteConfigProvider,
  NavigationContainer,
  initializeSentry,
} from '@ridwan-retainer/app-shell';

// Initialize error tracking
initializeSentry({ dsn: SENTRY_DSN });

function App() {
  return (
    <ErrorBoundary>
      <LifecycleProvider
        onInitialize={async () => {
          // Initialize critical services
          await initAuth();
          await loadUserPreferences();
          await connectAnalytics();
        }}
        onReady={() => {
          console.log('App initialization complete');
        }}
        onBackground={() => {
          // Save state when backgrounded
          saveAppState();
        }}
        onForeground={() => {
          // Refresh data when foregrounded
          refreshData();
        }}
      >
        <RemoteConfigProvider
          defaults={{
            enable_new_ui: false,
            api_timeout: 5000,
          }}
        >
          <LoadingProvider>
            <NavigationContainer
              linking={{
                prefixes: ['myapp://'],
                config: { screens: { /* ... */ } },
              }}
            >
              <MainNavigator />
            </NavigationContainer>
          </LoadingProvider>
        </RemoteConfigProvider>
      </LifecycleProvider>
    </ErrorBoundary>
  );
}
```

### Example 2: Theme Switcher

```typescript
import {
  useTheme,
  useThemeActions,
} from '@ridwan-retainer/app-shell';

function ThemeSwitcher() {
  const theme = useTheme();
  const { toggleTheme, setCustomTheme } = useThemeActions();

  const applyCustomTheme = () => {
    setCustomTheme({
      mode: 'dark',
      colors: {
        primary: '#FF6B6B',
        background: '#1A1A1A',
        text: '#FFFFFF',
        border: '#333333',
        error: '#FF4444',
        success: '#44FF44',
      },
    });
  };

  return (
    <View style={{ backgroundColor: theme.colors.background }}>
      <Text style={{ color: theme.colors.text }}>
        Current Mode: {theme.mode}
      </Text>
      <Button title="Toggle Theme" onPress={toggleTheme} />
      <Button title="Custom Theme" onPress={applyCustomTheme} />
    </View>
  );
}
```

### Example 3: Feature Flag System

```typescript
import {
  useFeatureFlag,
  useFeatureFlagActions,
} from '@ridwan-retainer/app-shell';

// Admin panel to toggle features
function FeatureFlagsPanel() {
  const { setFlag } = useFeatureFlagActions();

  return (
    <View>
      <FlagToggle
        name="new_ui"
        label="New UI Design"
        onToggle={(value) => setFlag('new_ui', value)}
      />
      <FlagToggle
        name="beta_features"
        label="Beta Features"
        onToggle={(value) => setFlag('beta_features', value)}
      />
    </View>
  );
}

// Feature component that respects flag
function NewUIFeature() {
  const isEnabled = useFeatureFlag('new_ui');

  if (!isEnabled) {
    return <LegacyUI />;
  }

  return <NewUI />;
}
```

### Example 4: Navigation with Deep Linking

```typescript
import {
  NavigationContainer,
  useTypedNavigation,
  useTypedRoute,
} from '@ridwan-retainer/app-shell';

type RootParamList = {
  Home: undefined;
  Article: { id: string; source?: string };
  Profile: { userId: string };
};

function App() {
  return (
    <NavigationContainer<RootParamList>
      linking={{
        prefixes: ['myapp://', 'https://myapp.com'],
        config: {
          screens: {
            Home: '',
            Article: 'article/:id',
            Profile: 'user/:userId',
          },
        },
      }}
    >
      <Stack.Navigator>
        <Stack.Screen name="Home" component={HomeScreen} />
        <Stack.Screen name="Article" component={ArticleScreen} />
        <Stack.Screen name="Profile" component={ProfileScreen} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

function HomeScreen() {
  const navigation = useTypedNavigation<RootParamList>();

  const openArticle = (id: string) => {
    navigation.navigate('Article', { id, source: 'home_feed' });
  };

  return <ArticleList onArticlePress={openArticle} />;
}

function ArticleScreen() {
  const route = useTypedRoute<{ id: string; source?: string }>();
  const { id, source } = route.params;

  // Track where user came from
  useEffect(() => {
    trackEvent('article_view', { id, source });
  }, [id, source]);

  return <ArticleContent id={id} />;
}
```

## ✅ Best Practices

### 1. Initialize Early

Place lifecycle initialization as high as possible in component tree:

```typescript
// App.tsx - root file
<LifecycleProvider onInitialize={initializeApp}>
  <RestOfApp />
</LifecycleProvider>
```

### 2. Use Error Boundaries

Wrap different app sections with error boundaries:

```typescript
<ErrorBoundary> {/* Top-level */}
  <Navigation>
    <ErrorBoundary> {/* Per-screen */}
      <ComplexScreen />
    </ErrorBoundary>
  </Navigation>
</ErrorBoundary>
```

### 3. Centralize State

Use provided stores for app-wide state:

```typescript
// Don't create separate state management for theme, settings, etc.
// Use built-in stores
const theme = useTheme();
const settings = useSettings();
```

### 4. Type Your Navigation

Always type your navigation stack:

```typescript
type RootStackParamList = {
  Home: undefined;
  Detail: { id: string };
};

const navigation = useTypedNavigation<RootStackParamList>();
```

### 5. Handle Loading States

Use loading provider for async operations:

```typescript
const { setLoading, clearLoading } = useLoadingState();

const loadData = async () => {
  setLoading('data', 'Loading...');
  try {
    await fetchData();
  } finally {
    clearLoading('data');
  }
};
```

### 6. Remote Config Defaults

Always provide defaults for remote config:

```typescript
<RemoteConfigProvider
  defaults={{
    feature_enabled: false, // Safe default
    timeout: 5000,
  }}
>
```

## 🐛 Troubleshooting

### Issue: "Provider not found"

**Solution**: Ensure providers are in correct order:

```typescript
<ErrorBoundary>
  <LifecycleProvider>
    <LoadingProvider>
      {/* Your app */}
    </LoadingProvider>
  </LifecycleProvider>
</ErrorBoundary>
```

### Issue: Navigation types not working

**Solution**: Define param list type:

```typescript
type RootParamList = {
  Home: undefined;
  // ...
};

const navigation = useTypedNavigation<RootParamList>();
```

### Issue: Remote Config not updating

**Solution**: Check fetch interval and force refresh:

```typescript
const { refresh } = useRemoteConfig();
await refresh();
```

### Issue: Theme changes not persisting

**Solution**: Ensure AsyncStorage is linked:

```bash
npm install @react-native-async-storage/async-storage
cd ios && pod install
```

## 📖 Migration Guide

### From 0.0.x to 0.1.0

No breaking changes. Initial release.

## 🤝 Contributing

Contributions welcome! Submit PRs to GitHub repository.

## 📄 License

MIT © [Ridwan Hamid](https://github.com/RidwanHamid501)

## 🔗 Links

- [npm Package](https://www.npmjs.com/package/@ridwan-retainer/app-shell)
- [GitHub Repository](https://github.com/RidwanHamid501/app-factory/tree/main/packages/app-shell)
- [React Navigation](https://reactnavigation.org)
- [Zustand](https://github.com/pmndrs/zustand)
- [Sentry React Native](https://docs.sentry.io/platforms/react-native/)

## 📞 Support

- [GitHub Issues](https://github.com/RidwanHamid501/app-factory/issues)
- [Discussions](https://github.com/RidwanHamid501/app-factory/discussions)