Mobile Application
The mobile application is built with React Native and Expo, featuring authentication, navigation, and dark mode support.
Tech Stack
Section titled “Tech Stack”- React Native with Expo (~54.0)
- React Navigation (native stack)
- NativeWind (Tailwind CSS for React Native)
- Zustand (state management)
- TanStack Query (data fetching)
- Better Auth (authentication)
- Jest + React Native Testing Library (testing)
- EAS Build (builds and deployment)
Prerequisites
Section titled “Prerequisites”- Node.js 24.10.0
- pnpm 10.5.2
- Expo CLI (installed automatically)
- iOS Simulator (for iOS development on macOS)
- Android Studio or Android Emulator (for Android development)
Getting Started
Section titled “Getting Started”1. Install Dependencies
Section titled “1. Install Dependencies”From the repository root:
pnpm install2. Environment Setup
Section titled “2. Environment Setup”Copy the environment file:
cp apps/mobile/.env.example apps/mobile/.envEdit .env and configure:
EXPO_PUBLIC_API_URL=http://localhost:30003. Start Development Server
Section titled “3. Start Development Server”From the repository root:
pnpm dev:mobileOr from the mobile folder:
cd apps/mobilepnpm devThis will start the Expo development server. You can then:
- Press
ito open iOS simulator - Press
ato open Android emulator - Scan the QR code with Expo Go app on your physical device
Project Structure
Section titled “Project Structure”apps/mobile/├── src/│ ├── app/ # App-level components│ │ ├── app-providers.tsx│ │ └── app-container.tsx│ ├── features/ # Feature modules│ │ ├── auth/│ │ │ ├── screens/│ │ │ │ ├── login-screen.tsx│ │ │ │ ├── register-screen.tsx│ │ │ │ └── reset-password-screen.tsx│ │ │ ├── components/│ │ │ │ ├── login-form.tsx│ │ │ │ └── forgot-password-modal.tsx│ │ │ └── schemas/│ │ │ ├── auth.schema.ts│ │ │ ├── forgot-password.schema.ts│ │ │ └── reset-password.schema.ts│ │ ├── home/│ │ │ ├── home-screen.tsx│ │ │ └── components/│ │ │ ├── posts-list.tsx│ │ │ └── post-card.tsx│ │ └── profile/│ │ └── profile-screen.tsx│ ├── navigation/ # Navigation configuration│ │ ├── types.ts│ │ ├── root-navigator.tsx│ │ └── use-linking.ts│ ├── components/ # Shared components│ │ ├── atoms/ # Atomic components│ │ │ ├── button.tsx│ │ │ ├── input.tsx│ │ │ └── password-input.tsx│ │ ├── organisms/ # Complex components│ │ │ └── slide-up-modal.tsx│ │ └── index.ts│ ├── common/ # Common utilities│ │ └── hooks/│ │ ├── use-auth-initialization.ts│ │ └── use-theme.ts│ ├── api/ # API queries│ │ └── queries/│ │ └── posts-queries.ts│ ├── store/ # Zustand stores│ │ ├── auth-store.ts│ │ └── theme-store.ts│ ├── theme/ # Theme configuration│ │ └── colors.ts│ ├── i18n/ # Internationalization│ │ ├── index.ts│ │ └── config.ts│ └── lib/ # External library configs│ ├── auth-client.ts│ └── query-client.tsx├── config/ # App configuration│ └── env.config.ts├── App.tsx # App entry point├── app.config.ts # Expo configuration├── eas.json # EAS Build configuration└── package.jsonDevelopment
Section titled “Development”Running on Specific Platforms
Section titled “Running on Specific Platforms”# iOSpnpm ios
# Androidpnpm android
# Web (for quick testing)pnpm webType Checking
Section titled “Type Checking”pnpm typecheckLinting
Section titled “Linting”pnpm lintTesting
Section titled “Testing”# Run testspnpm test
# Run tests in watch modepnpm test:watchAuthentication
Section titled “Authentication”The mobile app uses Better Auth with the same configuration as the web apps. Users can:
- Sign up with email and password
- Sign in with email and password
- Sign out
- Reset password via email
Authentication state is managed globally with Zustand and persists across app restarts.
Deep Links (Reset Password)
Section titled “Deep Links (Reset Password)”- Scheme:
lonestone://reset-password?token=...(configurable viaEXPO_PUBLIC_SCHEMEinapps/mobile/.envandCLIENTS_MOBILE_SCHEMEinapps/api/.env) - Important: Expo Go does not support custom schemes; you need a dev build or an installed app with this scheme to test
Testing Deep Links
Section titled “Testing Deep Links”# 1. Generate native iOS/Android projects with your custom schemepnpm expo prebuild --clean --no-install
# 2. Install the dev build on iOS simulator (required!)pnpm expo run:ios
# 3. Test the deep link (replace "lonestone" with your project's scheme)xcrun simctl openurl booted "lonestone://reset-password?token=dd8MiuMnEjAJy4JFH4MbBFgq"
# Alternative: Via uri-scheme utilitynpx uri-scheme open "lonestone://reset-password?token=YOUR_TOKEN" --iosUniversal Links (to be implemented)
Section titled “Universal Links (to be implemented)”The current flow uses a simple deeplink. To switch to Universal Links (iOS) / App Links (Android):
- Prepare the
apple-app-site-association/assetlinks.jsonfiles on your domain - Use the utility script
pnpm create:universallinksto generate the base configuration - Update the iOS/Android config (entitlements, manifest) and align the API to send the universal URL
Dark Mode
Section titled “Dark Mode”The app supports automatic dark mode based on system preferences. Users can also toggle dark mode manually using the useTheme hook:
import { useTheme } from '@/common/hooks/use-theme'
function MyComponent() { const { colorScheme, toggleColorScheme, isDark } = useTheme()
return ( <Button onPress={toggleColorScheme}> Toggle {isDark ? 'Light' : 'Dark'} Mode </Button> )}Building
Section titled “Building”Development Builds
Section titled “Development Builds”For features that don’t work with Expo Go:
# Build for iOSeas build --profile development --platform ios
# Build for Androideas build --profile development --platform androidInstall the development build on your device, then start the dev server with pnpm dev.
Preview Builds
Section titled “Preview Builds”For internal testing:
# iOS and Androideas build --profile preview --platform all
# iOS onlyeas build --profile preview --platform ios
# Android only (APK)eas build --profile preview --platform androidProduction Builds
Section titled “Production Builds”For app store submission:
eas build --profile production --platform allThe mobile app has a dedicated GitHub Actions workflow (.github/workflows/mobile-ci.yml) that:
- Runs linting and type checking
- Executes tests
- Builds preview versions on pull requests
- Builds production versions on main branch pushes
Troubleshooting
Section titled “Troubleshooting”Metro bundler issues
Section titled “Metro bundler issues”Clear the cache:
pnpm dev --clearEnvironment variables not working
Section titled “Environment variables not working”- Restart the Metro bundler after changing
.env - Ensure variables are prefixed with
EXPO_PUBLIC_ - Check
expo-env.d.tsfor type declarations
Cannot connect to API
Section titled “Cannot connect to API”- On iOS simulator: use
http://localhost:3000 - On Android emulator: use
http://10.0.2.2:3000 - On physical device: use your computer’s IP address (e.g.,
http://192.168.1.100:3000)