@chat-app/mobile
Expo + React Native client for Netralax on iOS and Android.
Prerequisites
- Node 22+, pnpm 9+
- Xcode (iOS) / Android Studio (Android) — only needed for local prebuild + emulator runs; EAS Build runs everything in the cloud.
- An Expo account (free) — required for
eas initbelow. - Optional:
npm i -g eas-clifor the CLI commands. If you skip globals, prefix everyeasinvocation withnpx eas-cli.
Phase 0 quickstart
# From the repo root.
pnpm install
# One-time: claim an EAS project ID. This rewrites the placeholder
# `extra.eas.projectId` in app.json and links the local repo to your
# Expo dashboard. Commit the resulting app.json change.
cd apps/mobile
npx eas-cli init
# Sign in to Expo if you haven't.
npx eas-cli login
# Build a development client (custom dev-client APK + iOS simulator
# bundle). First iOS build prompts for Apple ID — free signing works
# for development distribution.
npx eas-cli build --platform all --profile development
When the builds finish, EAS gives you a QR code / install link. Install the dev client on your device, then start the Metro server from the repo root:
pnpm mobile:dev # = pnpm --filter @chat-app/mobile dev = expo start --dev-client
Open the dev client on the device, scan the QR code, and Netralax's Landing screen should render.
Day-to-day
pnpm mobile:dev # Metro server
pnpm mobile:ios # native iOS run (local Xcode)
pnpm mobile:android # native Android run (local Android Studio)
pnpm mobile:typecheck # tsc --noEmit
Architecture notes
- Expo Router (file-based) — screens live under
app/. expo-secure-store— Keychain / Keystore-backed secret store, wrapped bylib/secretStore.tsto implement@chat-app/shared'sSecretStore.@react-native-async-storage/async-storage— Supabase session-token storage, surfaced vialib/sessionStorage.ts.expo-sqlite— local encrypted history (slated for a later phase).react-native-libsodium— crypto primitives, wrapped bylib/cryptoBackend.tsto implement@chat-app/shared'sCryptoBackend. Registered once at boot inapp/_layout.tsx.@chat-app/shared— business logic shared with the desktop; the mobile adapters plug into itsCryptoBackend+SecretStoreinterfaces, and every chat / auth call goes through the namespace exports.
Env vars
Copy .env.example to .env.local and fill in the same Supabase host +
anon key the desktop uses. Expo bundles only EXPO_PUBLIC_*-prefixed
vars into the JS, which is what the three required values use.
EAS Builds and Environment Variables
Production and preview builds load EXPO_PUBLIC_* from EAS Secrets —
.env.local is only honoured by expo start locally. Without the
secrets configured, an APK installs but env.ts throws on first read
and <BootError> renders.
Required secrets (create once per project):
npx eas-cli secret:create --scope project --name EXPO_PUBLIC_SUPABASE_URL --value '<project-supabase-url>'
npx eas-cli secret:create --scope project --name EXPO_PUBLIC_SUPABASE_ANON_KEY --value '<sb_publishable_key>'
npx eas-cli secret:create --scope project --name EXPO_PUBLIC_AUTH_REDIRECT_URL --value 'netralax://auth/callback'
Check with npx eas-cli secret:list.
Roadmap
See docs/superpowers/specs/2026-05-13-mobile-deployment-roadmap.md.