A concise guide to structure, setup, and daily commands.
- Node.js >= 20 and pnpm 10.15+ (see packageManager in
package.json) - iOS: Xcode 15+, CocoaPods via Bundler (Ruby), iOS Simulator
- Android: Android Studio + SDKs, JDK 17, emulator or device
- macOS: Watchman for fast reloads
pnpm install
# Set up Git hooks (pre-commit and pre-push)
pnpm run setup
# First time setup or to regenerate native projects
pnpm --filter mobile expo:prebuildNote: The
pnpm run setupcommand installs Git hooks that automatically run linting, formatting, copyright checks before commits, and tests before pushes.
pnpm buildThis will build all packages in the monorepo and write out any generated configuration.
In one terminal start Metro:
pnpm mobile:startIn another terminal run a platform target:
# iOS
pnpm ios
# Android
pnpm androidTip: you can also run these from the app folder:
pnpm -C apps/mobile start|ios|androidIf you need to regenerate native projects from scratch:
pnpm -C apps/mobile expo:prebuild:cleanWorkspace packages in packages/* are built to dist/ folders. The Turbo configuration automatically builds packages before running the mobile app or tests, so no manual build step is required for most development.
Note
During local development, the Metro bundler is configured to resolve packages directly from their src/index.ts files. This means you do not need to run a manual build to see your changes reflected in the app.
For active package development with hot-reloading:
# Watch mode - rebuilds packages on file changes (useful for editors/tests)
pnpm dev:packagesTo manually build all packages:
pnpm build:packagesRun a local Algorand node and point the app at it instead of live networks.
Prerequisites: Docker (running) and the AlgoKit CLI
(brew install algorandfoundation/tap/algokit).
pnpm localnet # start the LocalNet (algod :4001, indexer :8980, kmd :4002)
pnpm localnet:use # point the app's testnet slot at LocalNet
pnpm localnet:fund --new 100 # create + fund a throwaway account (prints mnemonic)
pnpm ios # or: pnpm android — app now talks to LocalNet as "testnet"
pnpm localnet:unset # restore live endpoints
pnpm localnet:stop # stop the LocalNetLocalNet reuses the testnet slot; mainnet stays on live infrastructure.
localnet:use fetches the node's genesis hash live, so re-run it after any
pnpm localnet:reset.
pera-react-native/
├── apps/
│ └── mobile/ # React Native app (UI layer)
├── packages/ # Headless business logic packages
│ ├── accounts/ # Account management and state
│ ├── assets/ # Asset management
│ ├── blockchain/ # Algorand-specific code (node/indexer)
│ ├── config/ # Configuration and environment
│ ├── contacts/ # Contact management
│ ├── currencies/ # Currency formatting and preferences
│ ├── devtools/ # Development tools
│ │ └── tsconfig/ # Shared TypeScript configuration
│ ├── kms/ # Key Management System integration
│ ├── platform-integration/# Platform abstraction layer
│ ├── polling/ # Background polling logic
│ ├── settings/ # User settings and preferences
│ ├── shared/ # Common utilities, types, and models
│ ├── swaps/ # Token swap functionality
│ ├── walletconnect/ # WalletConnect integration
│ └── xhdwallet/ # HD wallet crypto helpers
├── tools/ # Development and CI scripts
├── specs/ # OpenAPI specifications
└── docs/ # Project documentation
See workspace definition in pnpm-workspace.yaml.
- Task runner/cache: Turborepo (scripts in
package.json) - Formatting: oxfmt
- Linting: Oxlint via root config
.oxlintrc.json - Dead code / cycles / duplication: fallow via
.fallowrc.jsonc - TypeScript project references via
packages/devtools/tsconfig
pnpm build # build all packages
pnpm build:packages # build only workspace packages
pnpm dev:packages # watch mode for package development
pnpm test # run tests with coverage
pnpm lint # report lint/type-aware issues
pnpm lint:fix # auto-fix lint/type-aware issues
pnpm lint:copyright # add/update necessary copyright headers
pnpm lint:i18n # report i18n errors
pnpm format # format files
pnpm fallow # report unused code, circular deps, duplicationfallow finds cross-module unused exports/files/types/dependencies, circular dependencies, and code duplication — gaps neither Oxlint nor tsc cover. Config lives in .fallowrc.jsonc.
It runs in CI as an advisory, non-blocking job (Dead Code (advisory) in pre-merge.yml) — findings appear in the job summary but never fail a PR. The plan is to triage the existing findings, then ratchet specific rules to blocking with a --baseline so only new findings fail. Removals should be done in reviewed PRs, not via fallow fix.
- Architecture & State Management
- Folder Structure Guide
- Naming Conventions
- Testing Guide
- Style Guide
- Security Best Practices
- Performance Guidelines
- Contributing Guide
For app-specific notes, see apps/mobile/README.md.