| .. | ||
| .idea | ||
| .vscode | ||
| android | ||
| ios | ||
| lib | ||
| linux | ||
| macos | ||
| test | ||
| web | ||
| windows | ||
| .gitignore | ||
| .metadata | ||
| analysis_options.yaml | ||
| nomadcode_app.iml | ||
| pubspec.lock | ||
| pubspec.yaml | ||
| push-notification-todo.md | ||
| README.md | ||
nomadcode-app
The Flutter-first NomadCode client application.
Client Module Standard
The Flutter host application in this monorepo is standardized under apps/client/. This directory serves as the reference architecture for other projects (such as ../iop and ../alt) to replicate.
Directory Layout
lib/src/app/: Root application routing, bootstrap settings (bootstrap.dart), global configurations, and state setup.lib/src/features/: Feature-specific UI surfaces, business logic, and local UI state. Keep layout decoupled from shared integration protocols.lib/src/integrations/: Adapters and lifecycle hooks for external system boundaries. Any connection initialization or platform-specific service logic should reside here under strict interfaces.
Naming Conventions
- Flutter Host Path: Always kept as
apps/client/to act as the primary client skeleton. - Dart Package Name: Standardized as
nomadcode_app. When cloning, this package name can be customized to match target project identities (e.g.iop_client_app,alt_client_app) inpubspec.yaml, while maintaining the same directory layout.
Bootstrap
NomadCode features a standardized, platform-safe bootstrap layer in lib/src/app/bootstrap.dart:
- Common Initialization Path:
bootstrapNomadCodeClient()performs synchronous preparation, setups UI configurations (e.g., fullscreen system overlays), and initializes Firebase + Mattermost push notification boundaries. - Platform-Specific Guard: Native modules and background tasks (such as Firebase Messaging background handlers) are cleanly guarded inside integration-specific or native layers, preventing background crashes or initialization collision.
- No-Op Defaults: External transport components (such as the proto-socket lifecycle engine) initialize with safe no-op adapters by default to guarantee bootstrap safety.
Platform Targets
We prioritize and validate two primary platforms in this milestone, while ensuring others can be added seamlessly:
- Web & Android (Primary Targets): Fully validated in the main bootstrap configuration. Local notification integration and web socket configurations are verified to build and bootstrap without compilation errors.
- iOS (Future Expansion): iOS is treated as a first-class citizen using the same Dart APIs and integration facade boundaries (
MattermostPushClient,ProtoSocketLifecycle). Native iOS APNS and notification delegate handlers can be wired later into the same Dart interfaces without modifying the core bootstrap logic.
Integration Boundaries
apps/client/lib/src/integrations/ groups all external-system adapters behind small Dart interfaces:
integrations/mattermost/—MattermostPushClientinterface,MattermostPushPluginClientadapter (the only production reference toMattermostPushPlugin.instance),MattermostPushHostIntegration(initialize + auth handoff + navigation callbacks), andMattermostAuthService.integrations/proto_socket/—ProtoSocketEndpointConfigandProtoSocketLifecyclefacade over the localproto_socketDart path dependency. Bootstrap does not auto-connect; enabling and wiring a real connector are deferred to the next milestone.
For detailed integration boundaries, platform targets, and clone handoff guidelines, see push-notification-todo.md.
Mattermost Push Notification Integration
Mattermost push notification delivery is implemented via the local mattermost_push_plugin path dependency.
Architecture & Responsibility Split
To maintain a clean and maintainable codebase, the responsibilities are split between the host application and the plugin as follows:
Host Application (apps/client) Responsibilities:
- Firebase Configuration: Contains the standard Firebase configuration files (
android/app/google-services.json) and performs the standardFirebase.initializeApp()call in Dart main. - Mattermost Authentication: Handles login and session lifecycles, and passes the user authentication token and server signing key through the
MattermostPushClientboundary. The productionMattermostPushPluginClientadapter owns the plugin singleton calls. - Navigation Callbacks: Registers standard Flutter navigation callbacks
onNavigateToChannelandonNavigateToThreadto handle workspace channel and CRT thread routing upon user interaction. - FCM Token Sync: Listens to device token registrations via
onDeviceTokenReadyand registers the token with the Mattermost server.
Mattermost Push Plugin (mattermost_push_plugin) Responsibilities:
- Native Android FCM Service: Intercepts background/foreground FCM notifications securely via a custom Kotlin FCM service.
- Signature Verification: Validates incoming push payload signatures against stored public signing keys (using
JJWT). - System Notification Builder: Displays structured notifications with local avatar caches, thread summaries, and action buttons.
- Inline Reply / Dismiss Actions: Receives native background actions, records responses in a Room database, and forwards replies/ACKs directly to the Mattermost API via custom OkHttp adapters.
Cloning & Handoff Checklist
For sibling repositories (../iop and ../alt) aiming to align with this standard structure:
Sibling Specific Alignment Guidelines:
../iop: Avoid emphasizing legacy Portal naming conventions. Reorganize/rename legacy mobile paths to theapps/clientstandard. Align folder structures undersrc/app,src/features, andsrc/integrations. Do not clone NomadCode product-specific screens—only the integration and bootstrap skeletons.../alt: Retain ALT-specific Riverpod-based dependency graph andgo_routerfor app routing. However, extract external adapters intolib/src/integrations/matching the common Dart facade interfaces (MattermostPushClient,ProtoSocketLifecycle) to align the bootstrap pipeline.
Common Replacement Checklist:
When cloning this host template into a new environment, replace the following values:
- Dart Package Name: Rename
nomadcode_appto your target app package identifier inpubspec.yaml. - Display & App Naming: Adjust launcher configurations, bundle identifiers, and target product names in native assets (
android/app/src/main/AndroidManifest.xml,ios/Runner/Info.plist). - Firebase Configuration: Replace
google-services.json(Android) andGoogleService-Info.plist(iOS) with target project project credentials. - Endpoint Defaults: Update
ProtoSocketEndpointConfiginitialization defaults in environment configurations to route to your target backends. - Mattermost Server Configurations: Update server URLs, authentications, and asymmetrical public keys matching the target deployment environment.
Verification
To ensure code stability and structure correctness, run the following verification checks within this directory:
- Unit Tests:
flutter test - Static Analysis:
flutter analyze --no-fatal-infos - Web Build Validation:
flutter build web