This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
This project uses pnpm@9.15.3. Node.js 22+ is required. Ensure both are on PATH before running any commands:
export PATH="/opt/homebrew/opt/ruby/bin:$PATH" # required for pod commands on macOS# Install all workspace dependencies
pnpm install
# Start all dev servers (host + all mini apps) via mprocs
pnpm start
# Run on iOS / Android
pnpm run:host:ios
pnpm run:host:android
# Install iOS CocoaPods (run after adding native dependencies)
pnpm pods
# Run across all packages
pnpm lint
pnpm test
pnpm typecheck
# Run for a single package
pnpm --filter host test
pnpm --filter trading lintThis is a React Native Fintech Super App using Re.Pack and Module Federation V2 (Rspack-based) to load mini apps at runtime as separate JS bundles.
| Package | Role |
|---|---|
packages/host |
Native shell — owns the native binary, all native dependencies, top-level navigation, and MF remote wiring |
packages/auth |
Auth mini app — exposes AuthProvider, SignInScreen, AccountScreen |
packages/sdk |
Shared library — KrakenWebSocketService, PriceProvider, hooks, utilities, types, getSharedDependencies() for MF |
packages/trading |
Trading mini app — live asset list, Skia chart with OHLC history, trade bottom sheet |
packages/wallet |
Wallet mini app — real-time portfolio balance using live prices |
- Host loads remotes eagerly (
eager: true) and is the only app that runs natively. - Mini apps set
eager: false, expose only./App(theirMainNavigator), and consumeauthas a remote. - All shared deps (react, react-native, navigation libs, sdk) are declared as singletons via
getSharedDependencies()fromsdk. - Each mini app's bundler output
uniqueNamemust be unique (e.g.sas-host,sas-trading). - TypeScript declarations for all federated imports live in
packages/host/src/declarations.d.ts.
// In host — lazy load a remote module via React.lazy + Suspense
const TradingApp = React.lazy(() =>
randomDelay().then(() => import('trading/App'))
);
<ErrorBoundary name="Trading">
<React.Suspense fallback={<Placeholder label="Trading" />}>
<TradingApp />
</React.Suspense>
</ErrorBoundary>The randomDelay() (250–350ms) is intentional for demo purposes — it makes the loading state visible. Remove it for production.
All native deps live in host — mini apps declare them as peerDependencies only. When adding a new native dep:
- Add it to
host/package.jsondependencies - Add it to
sdk/lib/dependencies.jsonif it should be a MF shared singleton - Add it as
peerDependencyin each mini app that uses it - Add a
pathsentry in the mini app'stsconfig.jsonpointing to../host/node_modules/<dep> - Run
pnpm podsto reinstall iOS pods
packages/sdk is a shared singleton federated across all mini apps. It exports:
KrakenWebSocketService— singleton WebSocket to Kraken, shared across Trading and WalletPriceProvider/PriceContext— React context wrapping the WS serviceusePrices()/useAssetPrice(symbol)— price subscription hooks (updates wrapped inuseTransition)useHistoricalPrices(krakenPair)— fetches OHLC history from Kraken REST APIuseFlashAnimation(value)— Reanimated hook for green/red flash on value changeuseConnectionStatus()— WebSocket connection status hookConnectionBanner— UI component showing reconnecting/disconnected stateASSETS,ASSET_MAP,colors,formatPrice,formatValue,getAssetIconUri
AuthProvider (from auth remote) uses a render-prop pattern — it calls children with { isLoading, isSignout }. Host's App.tsx gates the navigation container behind auth state. Initial state is isLoading: true to prevent an unauthenticated shell flash before token restore completes.
- Leaf components:
PriceCell(trading) andValueCell(wallet) isolateuseAssetPricesubscriptions so only the price node re-renders on ticks. The outer row (AssetRow,HoldingRow) owns Reanimated shared values for the flash animation and never re-renders on price ticks. - useTransition: All price state updates in
usePricesare wrapped instartTransition— price ticks are non-priority and won't block user interactions. - startTransition on chart:
setChartDatainAssetDetailsScreenis wrapped inReact.startTransitionto defer chart rebuilds. - React Compiler:
babel-plugin-react-compileris enabled across all packages for automatic memoization.
| App | Port |
|---|---|
| host | 8081 |
| auth | 9003 |
| trading | 9001 |
| wallet | 9002 |
Each mini app has a mocks/ folder with local stubs for federated modules (e.g. auth/AuthProvider). These are used when running a mini app standalone without the host.
Each package has an rspack.config.ts. The loader used is @callstack/repack/babel-swc-loader. Asset transforms use getAssetTransformRules() — mini apps use {inline: true}.
Host has a Jest test suite (pnpm --filter host test). Key mocks in packages/host/jest.setup.js:
react-native-gesture-handler/jestSetup@bottom-tabs/react-navigation— mocked (native-only, can't run in Jest)react-native-bootsplash— mocked@callstack/repack/client— mocked withauth,trading,walletcontainer stubs