Skip to content

Fintech Super App refresh — React Native micro-frontends showcase#170

Draft
burczu wants to merge 42 commits intomainfrom
super-app-showcase-refresh
Draft

Fintech Super App refresh — React Native micro-frontends showcase#170
burczu wants to merge 42 commits intomainfrom
super-app-showcase-refresh

Conversation

@burczu
Copy link
Copy Markdown

@burczu burczu commented May 7, 2026

Summary

A full rebuild of the Super App Showcase into a production-grade Fintech demo app demonstrating React Native micro-frontend architecture with Re.Pack and Module Federation V2.

  • Trading mini app — live crypto asset list (Kraken WebSocket), Skia chart with OHLC history, trade bottom sheet and success screen, Reanimated flash animations
  • Wallet mini app — real-time portfolio balance, per-asset holdings with live value updates
  • Auth mini app — dark Fintech sign-in screen, AuthProvider gating the tab bar
  • SDK — singleton KrakenWebSocketService shared across all mini apps, PriceProvider, hooks, utilities
  • Host shell — dark theme, native bottom tabs, MF remote wiring, React Compiler

Key patterns demonstrated

  • Leaf-component isolation (PriceCell, ValueCell) so only the price node re-renders on ticks
  • useTransition / startTransition marking price updates as non-priority
  • Shared singleton WebSocket — one connection across Trading and Wallet via MF
  • Historical chart seeding from Kraken OHLC REST API
  • TypeScript MF module declarations for all federated remotes

What's in this PR

  • Full app implementation (US-1 through US-9)
  • Bug fixes from Codex review (auth bootstrap state, Jest setup, TS declarations, stale configs)
  • Performance improvements (PriceCell/ValueCell leaf split, startTransition on chart, useFlashAnimation in SDK)
  • Docs: rewritten README with screenshots, GIF, architecture diagram, and docs/MODULE_FEDERATION_DEMO_GUIDE.md

Still to do (post-merge)

  • Fill in _TBD_ bundle size and CI time tables in MODULE_FEDERATION_DEMO_GUIDE.md with real measured numbers

🤖 Generated with Claude Code

burczu and others added 30 commits April 27, 2026 14:06
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add react-native.config.js to trading and wallet so react-native start
  uses Re.Pack/Rspack instead of falling back to Metro (root cause of
  servers never starting)
- Add resolve.modules to trading/wallet rspack configs so rspack finds
  native peer deps (reanimated, skia, victory-native, etc.) in host's
  node_modules at build time
- Add @swc/helpers and react as devDependencies in sdk so SWC-injected
  helper imports resolve when rspack processes sdk TypeScript source
- Declare native libs and super-app-showcase-sdk as MF shared singletons
  so host provides one JS instance per native module bridge and one
  PriceContext/KrakenWebSocketService across all mini apps
- Add GestureHandlerRootView to host App.tsx root (trading exposes
  MainNavigator directly, not App, so the standalone wrapper never ran)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Required for Reanimated 4 worklet transpilation in host, trading, and wallet.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add babel-plugin-react-compiler to host, trading, and wallet for
  automatic memoization with React 19
- Add ConnectionStatus type and onStatusChange() to KrakenWebSocketService
  with connecting / connected / reconnecting / disconnected states
- Add useConnectionStatus() hook exported from sdk
- Show "Connecting to market…" / "Reconnecting…" banner in AssetListScreen
  and WalletScreen until first BTC price tick arrives (not just until WS
  connects — ensures banner is visible on every cold open of the tab)
- Rewrite README for Fintech Super App: ASCII architecture diagram, stack
  table, package roles, setup instructions, port reference

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Trading tab: chart.line.uptrend.xyaxis
Wallet tab: creditcard

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add react-native-bottom-tabs and @bottom-tabs/react-navigation as MF
shared singletons so trading mini app reads the same
BottomTabBarHeightContext provided by host's tab navigator. Use
useBottomTabBarHeight() in AssetDetailsScreen to compute the exact
native tab bar height (including home indicator) instead of guessing
with safe area insets.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Plain React refs are not readable inside Reanimated worklets (UI thread),
causing the flash to always use the initial value (green). Replacing with
useSharedValue makes the direction correctly accessible on the UI thread.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Hoist @types/* packages to root node_modules via public-hoist-pattern in .npmrc so TypeScript can find them across all workspace packages
- Add getSharedDependencies as a TypeScript implementation in sdk/src so it is accessible via the react-native exports condition (customConditions in @react-native/typescript-config)
- Add missing peer deps as devDependencies in trading (reanimated, gesture-handler, bottom-sheet, victory-native) and wallet (reanimated) so pnpm symlinks them for IDE resolution
- Add resolveJsonModule to sdk tsconfig and index.d.ts for the CJS entry point

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
public-hoist-pattern[]=@types/* in .npmrc was hoisting @types/react to root
node_modules, which pnpm picked up as an optional peer when resolving
react-native. Packages with and without typescript in scope then produced two
distinct peer-resolution hashes, creating separate physical instances of
react-native, react-native-reanimated, and react-native-worklets. Rspack
resolved each from a different path, causing both initialisation routines to
run in the same binary and triggering "RCTText registered twice".

Fixes:
- Remove public-hoist-pattern for @types/* from .npmrc
- Add @types/react and typescript devDeps to sdk so its react-native peer hash
  matches host/trading/wallet (single instance across all packages)
- Replace native devDeps in trading/wallet with tsconfig paths pointing to
  ../host/node_modules so the IDE can resolve types without pnpm creating
  duplicate instances
- Regenerate pnpm-lock.yaml; now a single instance of react-native,
  react-native-reanimated, and react-native-worklets

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add TypeScript-source exports consumed by mini apps via the react-native
package-exports condition (customConditions: ["react-native"]):

- sharedDeps.ts: TS implementation of getSharedDependencies, fixing TS2305 in
  rspack.config.ts files that import it from the SDK
- theme.ts: shared colors constant (was duplicated in trading and wallet)
- utils/formatPrice.ts: shared formatPrice/formatValue helpers
- components/ConnectionBanner.tsx: single source-of-truth for the live WS
  connection status banner (was duplicated in trading and wallet)
- constants.ts: add ASSET_MAP for O(1) symbol lookup
- index.ts: re-export all new symbols plus ConnectionStatus type

Delete index.d.ts which was shadowing the react-native source entry and
breaking host typecheck under moduleResolution: node.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
trading:
- Delete ConnectionBanner (now from SDK)
- AssetRow: extract flash-animation logic into useFlashAnimation hook,
  replace inline price formatter with formatPrice from SDK
- AssetDetailsScreen: merge split reanimated imports, use formatPrice from SDK
- AssetListScreen: import ConnectionBanner from SDK

wallet:
- Delete ConnectionBanner (now from SDK)
- HoldingRow: remove ASSETS.find lookup (caller now passes asset prop),
  extract flash-animation into useFlashAnimation hook, use formatPrice/
  formatValue from SDK
- WalletScreen: fix TotalBalance calculation (was returning hardcoded 0 for
  assets not in a static map), use ASSET_MAP for O(1) lookup, pass asset prop
  to HoldingRow

Flash animation is kept as a local hook in each mini app rather than exported
from SDK to avoid pulling react-native-reanimated into the SDK peer graph.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
AuthProvider:
- Replace loose {type, token} action shape with a discriminated union so
  each action carries only the fields it needs and the reducer is exhaustive
- signIn/signUp: dispatch only after SecureStore.setItem resolves, not after
  the catch block, so a storage failure never puts the app in a signed-in state
- signOut: dispatch unconditionally (storage failure is best-effort; the user
  is still considered signed out in JS)

AuthService:
- Mark TOKEN_KEY as private readonly

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…tubs

React Navigation v7 removed the independent prop from NavigationContainer.
The mini-app standalone App.tsx files (used only for local dev without a host)
were passing independent={true}, causing a TS2322 type error. The prop is not
needed here since there is no outer navigation context when running standalone.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add useHistoricalPrices(krakenPair) hook to SDK that fetches the last 60
one-minute candles from Kraken's public OHLC REST endpoint on mount and
returns the close prices as number[].

AssetDetailsScreen seeds its 60-tick buffer from this data so the chart
renders immediately on open. A seededRef ensures the seed runs exactly once
— it fires on the first non-empty response regardless of any live WebSocket
ticks that may have already landed in the buffer. Subsequent ticks continue
appending as before.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Use victory-native's yAxis prop to render 4 price tick labels on the right
side of the chart. Labels are formatted as compact values ($95.2k for prices
≥ 1000, $150 for ≥ 1, $0.452 for sub-dollar assets). Font is resolved via
Skia's matchFont using the system font, with a null fallback so the chart
renders gracefully if font loading fails.

Add @shopify/react-native-skia to trading's tsconfig paths so TypeScript
resolves the import from host/node_modules without a devDep.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ction

- Delete duplicate theme.ts from trading and wallet; all files now import
  colors directly from super-app-showcase-sdk
- Add getAssetIconUri(symbol) util to SDK; remove inline ICON_BASE_URL
  constant that was duplicated in AssetRow and HoldingRow
- Fix ConnectionBanner: was hiding when btcPrice > 0 (fragile BTC proxy);
  now hides when status === 'connected' using useConnectionStatus directly
- Restyle AccountScreen to match the app's dark Fintech theme; remove
  react-native-paper dependency and MD3Colors from this screen

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add Account tab to TabsNavigator with person.crop.circle SF Symbol
- Wrap AccountScreenRemote in a NativeStackNavigator so the "Account"
  title renders in a native header matching the Wallet/Trading pattern
- Restyle AccountScreen: ScrollView content area with 16px padding,
  Sign Out button pinned to the bottom above the tab bar using
  useBottomTabBarHeight, styled to match the Trade button (primary color)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Restore the original problem → solution → app → architecture sections
updated for the Fintech Super App refresh. Covers the full stack, package
structure, key design decisions (shared singletons, peer deps in host,
useTransition for price updates), and setup/running instructions.

Two TODO markers left for owner to fill in: app screenshot/GIF and
updated architecture diagram image.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add 250–350ms random delay to each mini app lazy import so the
  Suspense fallback is visible during demos
- Restyle Placeholder and SplashScreen to use the dark theme background
  with a primary-blue ActivityIndicator, replacing white SafeAreaView
  with MD3Colors that were inconsistent with the rest of the app

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…d bottom-tabs mocks

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
burczu and others added 12 commits May 6, 2026 13:21
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ries

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ice ticks

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…e-renders

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants