A disciplined Flutter client, built to turn a powerful foundation into a seamless mobile product experience.
A production-minded mobile foundation for authenticated applications. Identity, payments, access control, media, AI, real-time delivery, push notifications, product analytics, in-app updates, localization, client telemetry, and reusable design primitives meet hereβnot as disconnected demos, but as one cohesive mobile application.
Built under the same creed as Rexone Core and Rexone Web: clear in thought, exact in structure, simple in use, and strong enough to endure what comes after launch.
Typed Β· Modular Β· Localized Β· Observable Β· Push-ready Β· Analytics-enabled Β· API-driven Β· Fully Tested
Explore the foundation Β· Ecosystem Architecture Β· Development Law Β· Run it locally Β· Meet the architecture Β· E2E Testing Β· Connect the API
Important
ποΈ Unified Ecosystem: For the complete cross-platform architecture, feature parity matrix, and communication protocols between Core, Web, and Mobile, see ECOSYSTEM.md.
π Constitutional Law: All development must strictly adhere to the architecture, design system, and state laws in LAW.md. Zero exceptions.
A capable backend and a polished web app are only parts of the whole product. The mobile application must navigate device lifecycles, volatile network conditions, push notifications, app store version migrations, real-time socket events, platform sessions, biometric/passcode verification, and structured error telemetry.
Rexone Mobile exists so that work does not have to be reinvented for every mobile application built on Rexone Core.
This is not a template of screens pretending to be an architecture. Feature modules, shared services, models, bindings, design primitives, and telemetry pipelines have exact and deliberate responsibilities:
- Modules own a product feature end to end β pages, controllers, and (when needed) that feature's HTTP client β behind a single barrel export.
- Shared services are thin, single-responsibility clients for transport that is not feature-owned: HTTP, Action Cable, Firebase, OneSignal, storage, and client logs.
- Design primitives enforce consistent spacing, typography, and theme tokens across light and dark modes.
- Observability listeners automatically capture uncaught Flutter and platform errors and ship structured diagnostic payloads to Rexone Core's client log store.
The client is designed to bend around the product, never to make the product kneel before the foundation.
Rexone Mobile follows the same doctrine as the ecosystem it serves:
Clarity before cleverness. Precision before haste. Simplicity without weakness. Strength without spectacle.
The difficult part of mobile engineering is rarely rendering another screen. It is preserving a codebase that remains understandable when routes multiply, background workers fire, push payloads arrive while the app is backgrounded, API contracts evolve, and multiple developers build in parallel.
So the ambition was never to build the most complex state tree possible.
It was to build a clear mobile foundationβstrong enough to carry ambitious products, flexible enough to surrender its shape to them, and disciplined enough that any developer can trace data from interaction to API and back without archaeology.
| Foundation | What is ready | Details |
|---|---|---|
| Identity | Email/password flow, OTP verification, recovery, Google sign-in, platform sessions | Authentication & security |
| Profile | Settings account row opens Profile; camera/gallery photo pick (local preview only) | Profile |
| Push Notifications | OneSignal push messaging, permission management, user tag syncing, and click routing | Push notifications |
| Product Analytics | Firebase Analytics screen tracking, auth lifecycle events, and telemetry | Product analytics |
| In-App Upgrades | Upgrader alert system supporting soft and hard store version prompts | In-app version upgrader |
| Commerce | Products, Stripe Checkout WebView, subscriptions, and cancel/resume workflows | Payments & entitlements |
| AI Assistant | Non-blocking queued chat, persistent room history, and Action Cable notifications | AI capabilities |
| Real Time | Action Cable WebSocket client, subscription channels, and global toast dispatching | Real-time delivery |
| Observability | Flutter and platform error capture with automated client log delivery to Rexone Core | Client observability & telemetry |
| Design System | Centralized design tokens, theme extensions, custom components, and light/dark modes | Design system |
| Localization | English, Spanish, and Burmese with dynamic runtime switching and X-Locale backend sync |
Localization |
| Testing (E2E) | Real on-device automated user journey specs via Flutter Integration Test Driver | End-to-End Testing |
| Quality | Strongly typed Dart models, analyzer compliance, and automated test suite | Quality & testing |
Rexone Mobile keeps framework concerns explicit, responsibilities separated, and external providers isolated.
flowchart LR
User[User & Gestures] --> UI[Module Pages & Design Components]
UI --> Controllers[Module Controllers]
Controllers --> FeatureSvc[Feature Services]
Controllers --> SharedSvc[Shared Services]
FeatureSvc --> API[GetConnect HTTP Client]
SharedSvc --> API
API --> Core[Rexone Core API]
Core <-->|Action Cable| Socket[Socket Service]
Socket --> SocketCtrl[Socket Controller]
SocketCtrl --> Controllers
SocketCtrl --> UI
OneSignal[OneSignal Push Service] --> Controllers
Controllers --> Analytics[Firebase Analytics]
Runtime[Flutter & Platform Errors] --> LogService[Log Service]
LogService --> Core
lib/modules/owns product features. Each module keeps its pages, controllers, and optional feature service together, and exposes them through a barrel file (auth.dart,payment.dart, β¦).lib/controllers/holds only app-wide coordinators that do not belong to one feature β today,SocketController.lib/services/holds shared infrastructure: HTTP (ApiService), Action Cable, Firebase Analytics, OneSignal, storage, device permissions, and client logs.lib/design/centralizes design tokens, theme definitions, extensions, and reusable UI components.lib/bindings/handles centralized dependency injection for shared services and permanent controllers. Feature controllers that are route-scoped (Payment, Checkout, AI, Profile) are bound on theirGetPage.lib/models/contains strongly typed JSON:API models, pagination metadata (PaginationMeta,PaginatedResponse), and response envelopes.lib/locales/contains multi-language translations and runtime dictionary updates.lib/config/andlib/constants/manage environment definitions, typed JSON keys (JsonKeys), log constants (LogConstants), and application constants.integration_test/houses end-to-end integration specifications, test robots, and test data factories.test_driver/houses the Flutter driver entrypoint bridging device execution with test reporting.
- Smart Email Discovery: Automatically checks user registration and confirmation state via
GET /peek. - 6-Digit Password: In-memory password handling for sign-in and registration (credentials never leak to persistent storage or route arguments).
- Unconfirmed Drop-off Recovery: Returning unconfirmed users route directly to email confirmation OTP, bypassing credentials setup.
- Escalating Attempt Protection: Reactive password retry limits and cooldown counters driven dynamically by rexone-core.
- Email Confirmation: 6-digit email OTP verification with countdown-guarded resend capabilities.
- Google Sign-In: Native Google OAuth flow with Rexone Core challenge token support for first-time signups.
- Active Session Enforcement: Sends
X-Platform: mobileto ensure single-device active session rules enforced by the backend cache. - Session Replacement Handling: Detects active session invalidation and gracefully routes the user to sign-in with localized feedback.
- Own feature module at
lib/modules/profile/(route-scopedProfileControlleron/profile). - Opened from the Settings account row (
AppRoutes.toProfile). - Prefills full name, username, and email from the signed-in
UserModel. Email is read-only. - Edit badge on the avatar opens a camera or gallery sheet (
image_picker). Save PUTs name/username on/v1/users/currentand uploads a picked avatar. - Camera and photo-library prompts go through shared
PermissionService(same Settings dialog pattern as the AI microphone).
The mobile client enforces a synchronized three-tier administrative hierarchy:
super_admin: Full authority across all features, screens, and administrative tools.admin: Full authority across domain operations (feedbacks,payments,ai,assets,logs), strictly excluded fromusersandiam.- Partial Admins (
*_adminnaming convention): Users holding the baseuserrole plus a specific*_adminrole (e.g.feedback_admin). Any role withadminin its name is an admin role. Permissions in admin roles grant access to both standard and admin endpoints, whereas permissions in non-admin roles (such asuser) only grant access to non-admin features.
- Powered by OneSignal Flutter SDK (
onesignal_flutter). - Native push notifications for Android and iOS (
remote-notificationbackground modes). - User identification and tag synchronization (
syncUser(user)andclearUser()) hooked directly into authentication state changes. - Click listeners that route notifications and track conversion events via
AnalyticsService.
- Powered by Firebase Analytics (
firebase_core&firebase_analytics). - Automatic screen tracking via
FirebaseAnalyticsObserverregistered inGetMaterialApp.navigatorObservers. - Pre-defined event tracking for sign-up, sign-in, sign-out, password resets, onboarding, and error captures via
Constants.analytics. - User ID tagging synchronized with authenticated sessions.
- Powered by Upgrader (
upgrader). - Configured in
main.dartwrapping the root application builder. - Checks App Store and Play Store releases to display customizable update dialogs for outdated installations.
- Product catalogue with one-time and recurring pricing and pagination support.
- In-app Stripe Checkout handoff via WebView (
webview_flutter). - Subscription state management (Active, Scheduled for Cancellation, Expired).
- Safe end-of-period cancellation and resumption guarded by destructive confirmation dialogs.
- Non-blocking conversational AI assistant backed by Rexone Core and DeepSeek.
- Multi-room management with persistent chat history and pagination support.
- Real-time response completion notifications delivered via Action Cable.
- Room deletion and chat clearing guarded by destructive confirmation prompts.
- Real-time WebSocket connection to Rexone Core via Action Cable (
SolidCable). - Auto-reconnect and token refresh on authentication.
- Centralized
SocketControllerdispatches notifications and manages global toast feedback.
- Global error capture through
FlutterError.onErrorandPlatformDispatcher.instance.onError. - Structured diagnostic payloads (message, stack trace, device metadata, OS version, app version, local storage keys) delivered directly to Rexone Core's
POST /v1/log/clients. - Environment names validated against canonical backend schemas (
development,staging,production).
- Centralized design entry point via
import 'package:rexone_mobile/design/design.dart';. - Complete design tokens:
Design.spacing,Design.typography,Design.icons, andDesign.timers. - Theme extensions for theme-aware colors and typography (
context.colors,context.typo). - Reusable components:
AppButton,AppInputField,AppPasswordField,AppDialog,AppLoading,AppPage, andAppSnackbar. - Cohesive light and dark themes with persistent user preferences.
- Fully localized into:
- π¬π§ English (
en_US) - πͺπΈ Spanish (
es_ES) - π²π² Burmese (
my_MM)
- π¬π§ English (
- Complete parity across all user-facing texts with dynamic runtime GetX translation reload.
- Automatically sends
X-LocaleandAccept-Languageheaders on all HTTP requests to ensure backend responses match the user's selected language.
Rexone Mobile pairs reactive GetX UI with real-time audio and AI capabilities:
- Live Voice Dictation (STT):
- Microphones stream normalized 16-bit PCM chunks to Core's ActionCable
SpeechLiveChannelin real time. - Interactive
VoiceLevelBarswave animation visualizes live amplitude and voice input levels. - Seamless fallback with automatic cancellation and error handling.
- Microphones stream normalized 16-bit PCM chunks to Core's ActionCable
- Text-to-Speech (TTS) Playback:
- Direct binary audio stream playback via
just_audio/AudioPlayerwithout base64 overhead. - Message-level speech synthesis button with animated loading states and playing indicators.
- Background completion notifications (
tts_ready) dynamically link generated MP3 assets to assistant message bubbles.
- Direct binary audio stream playback via
- Conversational AI Chat:
- Non-blocking queued AI chat execution with persistent conversation rooms and message history.
- Optimistic UI updates with live thinking indicators and ActionCable socket synchronization.
Rexone Mobile includes on-device E2E tests built with package:integration_test and Flutter Driver. Tests exercise real user flows on active iOS Simulators or Android Emulators without mocking UI behavior.
rexone_mobile/
βββ integration_test/
β βββ auth/
β β βββ password_test.dart # Password acceptance, rejection, and retries
β β βββ password_reset_test.dart # Forgot password request flow
β β βββ sign_in_test.dart # End-to-end sign-in, drop-off recovery & home navigation
β β βββ sign_out_test.dart # Sign out & session termination
β β βββ sign_up_test.dart # Full registration & email confirmation
β β βββ sso_test.dart # Google SSO button presence & interaction
β βββ data/
β β βββ users.dart # Test user definitions & dynamic factory
β βββ robots/ # Test Robot helper classes
βββ test_driver/
β βββ integration_test.dart # Flutter Driver bridge entrypoint
βββ scripts/
βββ test.sh # Full test suite runner (Unit + E2E)
βββ test_unit.sh # Flutter unit test runner
βββ test_e2e.sh # Mobile E2E runner CLI
Rexone Mobile provides specialized and unified test runner scripts in scripts/:
# 1. Run FULL test suite (Unit + E2E)
./scripts/test.sh all -d emulator-5554
# 2. Run ONLY Unit tests (Flutter Test) - fast feedback loop
./scripts/test_unit.sh
# or: flutter test
# 3. Run ONLY E2E tests (Flutter Drive / Integration Test)
./scripts/test_e2e.sh all -d emulator-5554
# Run specific E2E flows
./scripts/test_e2e.sh sign-in -d emulator-5554
./scripts/test_e2e.sh sign-up -d emulator-5554
./scripts/test_e2e.sh password -d emulator-5554
./scripts/test_e2e.sh password-reset -d emulator-5554
./scripts/test_e2e.sh sign-out -d emulator-5554
./scripts/test_e2e.sh sso -d emulator-5554
# Or run on iOS Simulator
./scripts/test_e2e.sh sign-in -d "iPhone 16 Pro"Or run via Flutter Driver directly:
flutter drive \
--driver=test_driver/integration_test.dart \
--target=integration_test/auth/sign_in_test.dart \
-d emulator-5554- Flutter SDK:
>= 3.11.5 - Dart SDK:
>= 3.11.5 - Android Studio / VS Code with Flutter extensions
- Xcode (for iOS development on macOS)
- CocoaPods (for iOS dependency management)
Verify your environment:
flutter doctor- Clone the repository:
git clone git@github.com:rex-9/rexone-mobile.git
cd rexone-mobile- Install dependencies:
flutter pub get- Configure environment variables:
Create
.env.dev,.env.uat, or.env.prodin the project root:
APP_NAME=Rexone
APP_VERSION=1.0.0
API_BASE_URL=http://10.0.2.2:3000
GOOGLE_SERVER_CLIENT_ID=your_google_server_client_id.apps.googleusercontent.com
ONE_SIGNAL_APP_ID=your_onesignal_app_id
ANDROID_APP_ID=com.rexone.mobile
IOS_APP_ID=com.rexone.mobile- Configure Firebase & Google Services:
- Android: Copy
android/app/google-services.json.exampletoandroid/app/google-services.jsonand configure your Firebase project values. - iOS: Copy
ios/Runner/GoogleService-Info.plist.exampletoios/Runner/GoogleService-Info.plistand configure your Firebase project values.
Note
google-services.json and GoogleService-Info.plist are included in .gitignore to prevent credential exposure.
flutter run --dart-define=APP_ENV=.env.devflutter run --dart-define=APP_ENV=.env.uatflutter run --dart-define=APP_ENV=.env.prodRun static analysis:
flutter analyze lib/ test/ integration_test/Run unit and widget tests:
flutter test test/Run on-device integration tests:
./scripts/test.sh all -d emulator-5554flutter build apk --release --dart-define=APP_ENV=.env.prodflutter build appbundle --release --dart-define=APP_ENV=.env.prodflutter build ios --release --dart-define=APP_ENV=.env.prodrexone_mobile/
βββ android/ # Android native project & Gradle config
βββ ios/ # iOS native project & CocoaPods config
βββ integration_test/ # On-device integration tests & test robots
βββ lib/
β βββ bindings/ # GetX DI for shared services and permanent controllers
β βββ config/ # App configuration and environment resolution
β βββ constants/ # Constants, analytics event keys, locale keys, HTTP status
β βββ controllers/ # App-wide coordinators only (SocketController)
β βββ design/ # Design system (tokens, components, extensions, themes, icons)
β β βββ components/ # Reusable atoms and molecules (Button, Input, Password, Dialog, Loading)
β β βββ elements/ # Design tokens (Colors, Spacing, Typography, Icons, Timers)
β β βββ extensions/ # Theme context extensions
β βββ helpers/ # Utility helpers (API JSON:API parser, flags, validators)
β βββ locales/ # Multi-language translations (en_US, es_ES, my_MM)
β βββ models/ # Strongly typed models and JSON:API response envelopes
β βββ modules/ # Feature modules (pages + controllers + feature services)
β β βββ splash/ # Launch / session restore
β β βββ auth/ # Welcome, password, signup, OTP, recovery
β β βββ home/ # Main dashboard
β β βββ payment/ # Plans, Stripe Checkout WebView, subscriptions
β β βββ profile/ # Account profile, avatar upload
β β βββ setting/ # Theme, language, and account row
β β βββ ai/ # Assistant chat, rooms, history
β βββ routes/ # GetX route declarations and auth route guards
β βββ services/ # Shared transport (API, Socket, Log, Analytics, Push, Storage, Permissions)
βββ scripts/
β βββ rebrand.sh # Unified mobile rebranding (Name + Package + Icon)
β βββ update_app_name.sh # App display name updater (Android, iOS, .env)
β βββ update_package_name.sh # Package identifier / Bundle ID updater
β βββ update_app_icon.sh # Launcher icons generator
β βββ update_app_version.sh # Version and build number incrementer
β βββ test.sh # Full test suite runner (Unit + E2E)
β βββ test_unit.sh # Flutter unit test runner
β βββ test_e2e.sh # E2E integration test CLI runner
βββ test/ # Unit, controller, and localization tests (88 tests)
β βββ controllers/ # Socket controller tests
β βββ mocks/ # In-memory test service doubles
β βββ modules/ # Auth, Notification, Feedback, Setting, Payment, AI controller tests
β βββ services/ # Speech and core service tests
βββ test_driver/
β βββ integration_test.dart # Flutter Driver test bridge
βββ pubspec.yaml
Tip
Recommended: For full, synchronized rebranding across all 3 platforms (Core Backend, Web SPA, and Mobile App), run the master rebrand engine from rexone-core:
cd ../rexone-core && ./scripts/rebrand.shFor standalone mobile development or isolated updates, you can use the local scripts below:
# 1. Standalone Mobile Rebrand (Name + Package ID + App Icon)
./scripts/rebrand.sh "New App Name" "com.company.newapp" "path/to/icon.png"
# 2. Update App Display Name only
./scripts/update_app_name.sh "New App Name"
# 3. Update Package Name / Bundle ID only
./scripts/update_package_name.sh com.company.newapp
# 4. Generate Launcher Icons from assets/brand/logo.png
./scripts/update_app_icon.sh
# 5. Bump Version and Build Number
./scripts/update_app_version.sh 1.1.0This application is built on top of the Rexone Ecosystem (rex-9). When creating derivative products or white-label applications:
- Developers and creators are warmly encouraged to preserve ecosystem credit in documentation to support the project.
- All development must strictly adhere to the constitutional engineering standards in LAW.md and ECOSYSTEM.md.
Built with Clarity & Simplicity Driven Development, by Rex (Rex9).
A software engineer, full-stack architect, and long-time practitioner of meditation.
I build systems the same way I approach the path itself: with a clear mind, deliberate steps, and no unnecessary weight.
Built with β€οΈ by Rex9 on Rexone Ecosystem