Portal is a mobile identity wallet for secure authentication and payments using the Nostr protocol. Built with React Native and Expo, it puts you in complete control of your digital identity and personal data with enterprise-grade security.
- Nostr Authentication: Cryptographically secure authentication with websites and services
- Biometric Security: Face ID, Touch ID, and fingerprint authentication
- Secure Key Management: Private keys never leave your device
- Identity Management: Complete control over your digital identity
- Lightning Payments: One-time Bitcoin Lightning Network payments
- Cashu/eCash Support: Native Cashu token support for eCash payments and transactions
- Subscription Management: Monitor and control recurring payments
- Payment Status Tracking: Real-time payment status with Revolut-style UI
- Wallet Integration: Seamless NWC (Nostr Wallet Connect) integration
- Activity Dashboard: Comprehensive tracking of all authentications and payments
- QR Code Scanner: Quick authentication and payment initiation
- NFC Scanning: Contactless NFC tag scanning for authentication and ticket validation
- Ticket Management: Digital ticket storage, validation, and recovery
- Dark/Light Theme: Adaptive theme system with system preference support
- Intuitive Navigation: Tab-based navigation with detailed activity views
- Local Storage: All sensitive data stored securely on device
- Biometric Protection: Additional security layer for sensitive operations
- No Data Sharing: Zero personal data shared without explicit consent
- Cryptographic Verification: All operations cryptographically verified
- React Native - Cross-platform mobile development (New Architecture enabled)
- Expo SDK 53 - Development platform and SDK
- TypeScript - Type-safe development with strict mode
- Expo Router - File-based navigation with typed routes
- Expo SQLite - Local database storage with migrations
- Expo SecureStore - Secure key storage
- Expo LocalAuthentication - Biometric authentication
- Nostr Protocol - Decentralized identity and messaging
- Custom Rust lib - Core Nostr logic and cryptography (via UniFFI bindings)
- NWC Integration - Nostr Wallet Connect for Lightning payments
- Breez SDK - Lightning Network payments
- Lucide React Native - Icon library
- Biome - Linting and formatting
- Bun - Package manager
- Husky + lint-staged - Git hooks
This project uses Nix flakes to provide a reproducible development environment. Running nix develop gives you:
- Node.js - JavaScript runtime (required by Metro/Expo)
- Bun - Package manager
- OpenJDK 17 - For Android Gradle builds
- Android SDK - Build tools, platform, NDK
- Biome - Linting and formatting
- Expo CLI - Expo development tools
The project uses Husky for Git hooks, installed automatically on bun install:
- pre-commit: Runs lint-staged which applies
biome check --writeon staged files (auto-fixes formatting and import sorting) - pre-push: Runs
typecheckandcheckon the full project to ensure quality before pushing
These same checks run in CI, so if your push passes locally, it passes in CI.
- Nix with flakes enabled
- iOS Simulator (Mac) or Android Studio (for emulators)
-
Clone the repository:
git clone https://github.com/PortalTechnologiesInc/Portal-App.git cd Portal-App -
Enter the Nix development shell:
nix develop
This provides Node.js, Bun, Android SDK, Java, and all required tooling.
-
Install dependencies:
bun install
-
Start the development server:
bun run start
-
Run on device/simulator:
# Android bun run android # iOS (macOS only) bun run ios
- Generate Identity: Create a new Nostr private key or import existing seed phrase/nsec
- Set PIN: Configure a PIN for app lock
- Profile Configuration: Set up your identity information
- Wallet Connection: Connect your NWC-compatible Lightning wallet
- Scan QR Code or NFC Tag: Use built-in scanner or NFC reader from website or service
- Review Request: Examine authentication details and permissions
- Biometric Confirmation: Confirm with Face ID/Touch ID
- Approve/Deny: Complete the authentication process
- Payment Requests: Review incoming payment requests (Lightning or Cashu)
- Status Tracking: Monitor payment progress with real-time updates
- Subscription Control: Manage recurring payments and subscriptions
- Ticket Management: Store, validate, and recover digital tickets via NFC
- Activity History: View complete payment and authentication history
portal-app/
βββ app/ # Expo Router pages (file-based routing)
β βββ (tabs)/ # Tab navigation screens
β β βββ index.tsx # Home screen
β β βββ Activities.tsx
β β βββ Subscriptions.tsx
β β βββ Tickets.tsx
β β βββ Wallet.tsx
β β βββ Settings.tsx
β βββ (onboarding)/ # First-time setup flow
β β βββ generate/ # Key generation
β β βββ import/ # Key import (mnemonic/nsec)
β βββ activity/[id]/ # Dynamic activity detail pages
β βββ subscription/[id]/ # Subscription management
β βββ breezwallet/ # Breez wallet pay/receive
β βββ nfc/ # NFC scanner flow
β βββ qr/ # QR scanner flow
β βββ wallet.tsx # Wallet management
β βββ relays.tsx # Nostr relay configuration
β βββ error.tsx # Error boundary
β βββ [...deeplink].tsx # Deep link catch-all
βββ components/ # Reusable UI components
β βββ ActivityDetail/ # Activity-specific components
β βββ onboarding/ # Onboarding-specific components
β βββ ui/ # Base UI components
βββ context/ # React Context providers
βββ services/ # Core business logic
βββ hooks/ # Custom React hooks
βββ models/ # TypeScript interfaces
βββ constants/ # App constants and configuration
βββ utils/ # Helper functions and utilities
βββ migrations/ # SQLite database migrations
βββ plugins/ # Custom Expo config plugins
βββ scripts/ # Build and device management scripts
βββ debug-scripts/ # Database debugging tools
βββ .github/workflows/ # CI/CD pipeline
- Context-based Architecture: Multiple specialized contexts for different domains
- SQLite Database: Persistent storage for activities, subscriptions, and user data
- Secure Storage: Encrypted storage for sensitive keys and tokens
# Development (runs typecheck + lint first)
bun run start
bun run android
bun run android-release
bun run ios
# Type checking
bun run typecheck
# Linting and formatting (Biome)
bun run lint # lint only
bun run check # lint + format
bun run check:strict # lint + format, warnings as errors
bun run check:fix # lint + format with auto-fix
bun run format # format with auto-write
bun run format:check # format check only
# Testing
bun run test # Jest unit tests (watch mode)import { useThemeColor } from '@/hooks/useThemeColor';
const backgroundColor = useThemeColor({}, 'background');
const textColor = useThemeColor({}, 'textPrimary');import { DatabaseService } from '@/services/DatabaseService';
import { useSQLiteContext } from 'expo-sqlite';
const db = useSQLiteContext();
const dbService = new DatabaseService(db);import { BiometricAuthService } from '@/services/BiometricAuthService';
const authResult = await BiometricAuthService.authenticate();- Create Components: Add to appropriate directory in
components/ - Update Context: Extend existing or create new context providers
- Database Schema: Update database migrations in
migrations/ - Type Definitions: Add interfaces to
models/directory - Navigation: Add routes in
app/directory following Expo Router conventions
The project is fully self-managed β no cloud build services. Build scripts handle APK/IPA creation and device installation:
# Build Android APK (release)
bash scripts/build-android-apk.sh release
# Build and install on connected Android device/emulator
bash scripts/install-android-apk.sh
# Build iOS app (macOS only)
bash scripts/build-ios-ipa.sh
# Install on iOS Simulator
bash scripts/install-ios-ipa.shFor fully reproducible Android builds:
nix build .#android-bundleThis produces a signed AAB bundle using hermetic Nix derivations.
- Fork the repository
- Enter Nix shell:
nix develop - Install dependencies:
bun install - Create a feature branch:
git checkout -b feature/amazing-feature - Make changes β Git hooks will auto-lint staged files on commit
- Push to branch:
git push origin feature/amazing-feature(pre-push runs full typecheck + lint) - Open a Pull Request
- TypeScript: All new code must be written in TypeScript with strict mode
- Theme Support: All components must support dark/light themes
- Biome: Code must pass
bun run check(enforced by Git hooks and CI) - Security First: Follow secure coding practices, especially for key management
- Expo Router: Follow file-based routing conventions for new screens
- Context Usage: Use appropriate context providers for state management
This project is licensed under the MIT License with Common Clause - see the LICENSE file for details.
Portal prioritizes security and privacy:
- π Private Key Security: All private keys stored in device secure enclave
- π Biometric Protection: Additional security layer for sensitive operations
- π‘οΈ No Data Leakage: Zero telemetry or data collection
- β Cryptographic Verification: All operations cryptographically signed and verified
- π Local-First: Everything runs locally on your device
- Documentation: Portal Docs(TBD)
- Issues: GitHub Issues
- Community: Discord Server(TBD)
- Email: support@portal.com(TBD)
Built with β€οΈ by the Portal Team
