End-to-end encrypted mobile chat app using the Nostr Double Ratchet protocol.
- End-to-end encryption - Messages encrypted using Double Ratchet (Signal protocol)
- Decentralized - Uses Nostr relays, no central server
- Offline support - Messages queued when offline, sent when connected
- QR code invites - Easy contact sharing via QR codes or links
- Cross-platform - Android and iOS
- Flutter with Riverpod for state management
- Rust native library (ndr-ffi) for cryptography via FFI
- SQLite for local message storage
- Secure storage for private keys
- Flutter 3.24+
- For Android: Android SDK
- For iOS: macOS with Xcode
flutter build apk --release- Build the native library on macOS (see
ios/Frameworks/README.md) - Run:
flutter build ios --releaseThe release workflow auto-detects signing configuration from GitHub Actions secrets. If all required secrets for a platform are present, signing is enabled. If none are present, unsigned artifacts are built. Partial secret setup fails the workflow.
Required macOS signing secrets:
MACOS_SIGNING_IDENTITY(for example:Developer ID Application: Example Corp (TEAMID))MACOS_CERTIFICATE_P12(base64-encoded.p12that includes private key)MACOS_CERTIFICATE_PASSWORD
Optional macOS notarization secrets (enable notarization when all are set):
MACOS_NOTARIZE_APPLE_IDMACOS_NOTARIZE_APP_PASSWORD(app-specific password)MACOS_NOTARIZE_TEAM_ID
Required Android signing secrets:
ANDROID_KEYSTORE_B64(base64-encoded.jks/.keystore)ANDROID_KEYSTORE_PASSWORDANDROID_KEY_ALIASANDROID_KEY_PASSWORD
# Install dependencies
flutter pub get
# Run code generation (freezed, riverpod)
dart run build_runner build
# Run tests
flutter test
# Run analyzer
flutter analyzelib/
├── config/ # Providers, router, theme
├── core/ # FFI bindings, services
├── features/ # Feature modules
│ ├── auth/ # Identity management
│ ├── chat/ # Messaging
│ ├── invite/ # QR invites
│ └── settings/ # App settings
└── shared/ # Common utilities
MIT