- Run
yarn docstringsto check documentation coverage for both the mobile app and SDK. This generatesdocs/coverage/app.jsonanddocs/coverage/sdk.jsonso you can diff coverage changes in version control. - Run
yarn docstrings:appto check only the mobile app exports. - Run
yarn docstrings:sdkto focus on@selfxyz/mobile-sdk-alphaonly. - Add
--detailsto any command when you want a full per-file JSON breakdown for ad-hoc analysis—the default snapshots include only top-level totals and a small sample of undocumented exports to keep the tracked files compact.
Run the docstring reports locally before committing to track coverage changes. The reports are advisory—use them to identify documentation gaps but they won't block builds.
The app uses @react-navigation/native with createStaticNavigation for type-safe navigation. Screens are organized by feature modules and use platform-specific initial routes.
// Navigation setup pattern
export const navigationScreens = {
...systemScreens,
...passportScreens,
...homeScreens,
...proveScreens,
...settingsScreens,
...recoveryScreens,
...devScreens,
};
// Platform-specific initial routes
initialRouteName: Platform.OS === 'web' ? 'Home' : 'Splash';Custom modal system using useModal hook with callback registry for handling button presses and dismissals.
const { showModal, dismissModal, visible } = useModal({
titleText: 'Modal Title',
bodyText: 'Modal content',
buttonText: 'Action',
onButtonPress: async () => {
// Handle button press
},
onModalDismiss: () => {
// Handle modal dismiss
},
});Always check platform before implementing platform-specific code:
if (Platform.OS === 'ios') {
// iOS-specific implementation
} else {
// Android-specific implementation
}Critical for NFC and other native functionality:
// Initialize native modules before any native operations
const modulesReady = await initializeNativeModules();
if (!modulesReady) {
console.warn(
'Native modules not ready, proceeding with limited functionality',
);
}- Custom hooks for complex state management (
useModal,useHapticNavigation) - Zustand for global state management
- React Navigation state for screen-specific data
- AsyncStorage: Simple key-value storage
- SQLite: Complex data (proof history)
- Keychain: Sensitive data (biometrics, encryption keys)
- Comprehensive mocks in
jest.setup.jsfor all native modules - Module mapping for clean imports
- Test-specific TypeScript configuration
All React Native native modules are mocked with realistic return values:
jest.mock('react-native-keychain', () => ({
SECURITY_LEVEL_ANY: 'MOCK_SECURITY_LEVEL_ANY',
setGenericPassword: jest.fn(),
getGenericPassword: jest.fn(),
resetGenericPassword: jest.fn(),
ACCESSIBLE: {
WHEN_UNLOCKED: 'AccessibleWhenUnlocked',
// ... other constants
},
}));- Use
renderHookfor custom hook testing - Mock console.error to avoid test output clutter
- Test error boundaries and recovery mechanisms
- E2E testing with Maestro for platform-specific flows
- iOS: Custom PassportReader Swift module
- Android: Custom RNPassportReaderModule Kotlin implementation
- Unified JavaScript interface with platform detection
- MRZ Key: Derived from passport number, DOB, and expiry date
- CAN (Card Access Number): 6-digit number for PACE authentication
- PACE: Password Authenticated Connection Establishment
- BAC Fallback: Basic Access Control when PACE fails
- Multiple BAC attempts with delays
- Graceful degradation from PACE to BAC
- Real-time status updates and haptic feedback
- Comprehensive error boundaries
export const scan = async (inputs: Inputs) => {
return Platform.OS === 'android'
? await scanAndroid(inputs)
: await scanIOS(inputs);
};src/
├── components/ # Reusable UI components
├── screens/ # Screen components by feature
├── navigation/ # Navigation configuration
├── hooks/ # Custom React hooks
├── utils/ # Shared utilities
├── types/ # TypeScript type definitions
├── stores/ # State management
└── providers/ # Context providers
- Use
@/alias for src imports:import { Component } from '@/components' - Use
@tests/alias for test imports:import { mockData } from '@tests/utils' - Platform-specific imports with conditional rendering
yarn ios/yarn androidfor platform-specific buildsyarn testfor Jest testingyarn test:e2e:ios/yarn test:e2e:androidfor E2E- Fastlane for deployment automation
- Yarn workspaces for monorepo management
- Platform-specific native modules
- Tamagui for UI components
- React Navigation for routing
- Sensitive data not logged in production
- Secure storage with Keychain
- Proper cleanup of sensitive data
- Certificate validation for passport data
- Zero-knowledge proof generation
- Selective attribute revelation
- Privacy-preserving age verification
- Identity commitment privacy
try {
const result = await riskyOperation();
return result;
} catch (error) {
console.error('Operation failed:', error);
// Graceful degradation
return fallbackValue;
}- Lazy load screens and components
- Bundle size optimization with tree shaking
- Memory leak prevention in native modules
- Proper cleanup in useEffect and component unmount
- Always check Platform.OS before platform-specific code
- Different implementations for iOS/Android when needed
- Platform-specific testing strategies
- Conditional rendering for platform differences