04 - Architecture
The architecture in 2 minutes. For full component diagrams and sequence flows, see the Frontend Architecture HTML.
This page is a quick-read summary. For interactive component diagrams, sequence diagrams, and UML-style architectural flows, open frontend_architecture.html in the project root. That file is the source of truth for visual architecture.
The 4 Layers
The app is a strict 4-layer architecture. Data flows top-to-bottom (higher layers depend on lower layers, never the reverse).
| # | Layer | Folder | Responsibility |
|---|---|---|---|
| 1 | Presentation | lib/screens/, lib/widgets/ |
Stage screens, wrapper widgets. UI rendering, user input, form validation, calling services. |
| 2 | Service | lib/services/ |
ApiService (backend calls), StorageService (persistence), AnalyticsService (events). |
| 3 | Domain | lib/models/ |
Plain data classes with fromJson factories. No logic. |
| 4 | Configuration | lib/config/ |
Compile-time constants: base URLs, routes, theme, asset paths. |
Dependency Rule
Each layer only depends on layers below it.
- Screens import
services/,models/,config/,widgets/— but never each other. - Services import
models/,config/— but neverscreens/. - Models import nothing project-specific.
- Config imports nothing project-specific.
Navigation is done via named routes (Navigator.pushReplacementNamed), not by importing the target screen class. This keeps screens decoupled.
Data Flow (in one sentence)
User interacts with a Screen, which calls an ApiService method, which HTTPs the Backend, which returns JSON that fromJson-factories into a Model, wrapped in ApiResponse<T>, and the screen does setState to re-render.
Why No State Management Library?
You might expect BLoC, Provider, or Riverpod. The app deliberately uses vanilla setState everywhere. Here's why:
Each stage is a self-contained screen. State does not need to be shared across 5 screens at once. setState is sufficient. No BLoC boilerplate, no provider tree, no stream subscriptions. Fewer files, easier to debug.
Shared state that does cross screens (leadId, token, sessionId) lives in the StorageService singleton.
Cross-Cutting Concerns
Loading spinners, session timeouts, back button handling, progress bars - these are handled by wrapper widgets, composed around screen content.
Typical screen wrapper compositionDart
return BackButtonHandler(
child: SessionTimer(
child: Scaffold(
appBar: AppBar(title: const Text('Bank Verification')),
body: LoadingOverlay(
isLoading: _isLoading,
message: 'Verifying...',
child: Column(
children: [
const JourneyProgressBar(currentStage: 6),
_buildBody(),
],
),
),
),
),
);
Each wrapper is independent and optional. If Stage 0 doesn't need back button handling, just omit BackButtonHandler. No mixin, no inheritance, no base class.
Why Single ApiService?
Instead of one repository per feature (common in BLoC-based apps), the entire backend is exposed through a single ApiService class with ~60 methods.
Pro: All endpoints discoverable in one file. Auth, headers, error handling, stage tracking are centralized. New developers only need to read one file to understand the API surface.
Con: File is large (~1100 lines). Mitigated by grouping methods with section comments per stage.
Where Logic Lives
| What | Where |
|---|---|
| Form validation (client-side) | Screen file (e.g. _validateMobile) |
| API call with auth + error handling | ApiService method |
| Persistent state (leadId, token) | StorageService singleton |
| Transient UI state (loading, view state) | Screen's State<T> class (setState) |
| Navigation | Navigator.pushReplacementNamed via routes in AppRoutes |
| Theme / colors / fonts | lib/config/theme.dart |
| Environment-specific URLs | lib/config/api_config.dart (compile-time) |
| Mock URL detection (dev only) | Inline in Stage 5 and Stage 6 screens, guarded by ApiConfig.isDev |
| Business logic decisions | Mostly backend. Frontend mirrors backend responses. |
Full Diagrams
Open these HTML files in your browser for the interactive visual architecture:
- frontend_architecture.html — component diagram, 5 sequence diagrams, layered architecture, platform build pipeline, mock mode strategy, patterns, appendices
- ui_old_and_new.html — stage-by-stage comparison with the old RISE app