03 - Project Tour
A guided walk through the flutter_app/ folder structure. By the end of this page you'll know where every file lives and what it does.
Top-level Layout
flutter_app/Tree
flutter_app/
├── android/ # Native Android wrapper (Gradle, AndroidManifest)
├── ios/ # Native iOS wrapper (Xcode, Info.plist, Podfile)
├── web/ # Web entry (index.html, manifest.json, favicon)
├── windows/ # Windows desktop (optional target)
├── linux/ # Linux desktop (optional target)
├── macos/ # macOS desktop (optional target)
├── assets/
│ └── images/ # 41 Lottie/SVG/PNG assets (RISE logo, illustrations, icons)
├── lib/ # ★ All Dart source code lives here
│ ├── config/
│ ├── models/
│ ├── services/
│ ├── screens/
│ ├── widgets/
│ ├── app.dart
│ └── main.dart
├── test/ # Unit/widget tests (mostly empty, TBD)
├── pubspec.yaml # Dependencies and asset registration
└── pubspec.lock # Locked dependency versions
The android/, ios/, web/ folders are auto-generated platform wrappers. You rarely touch them. 99% of your work happens in lib/.
The lib/ Folder
flutter_app/lib/Tree
lib/
├── config/ # Compile-time constants and config
│ ├── api_config.dart # Base URL, routes, env flag, timeouts
│ ├── routes.dart # Named routes for all 16 stages
│ ├── theme.dart # MaterialApp theme (RISE colors, Inter font)
│ └── assets.dart # Static paths to Lottie/SVG/PNG assets
│
├── models/ # Plain Dart classes with fromJson factories
│ ├── lead.dart # Lead (leadId, mobile, state)
│ ├── pan_result.dart # PAN verification response
│ ├── bank_result.dart # Bank verification response + isPreVerified
│ ├── otp_result.dart # OTP verify response
│ ├── journey_status.dart # Journey stage + progress
│ ├── nominee.dart # Nominee data
│ └── api_response.dart # Generic ApiResponse<T> wrapper
│
├── services/ # Business logic / external interfaces
│ ├── api_service.dart # ★ 60+ API methods, single file
│ ├── storage_service.dart # Singleton SharedPreferences wrapper
│ └── analytics_service.dart # Event tracking stub (debugPrint)
│
├── screens/ # One file per stage screen
│ ├── stage0_arrival.dart # Splash + session init + resume detection
│ ├── stage1_registration.dart # Mobile + name + T&C
│ ├── stage2_otp.dart # Mobile OTP verification
│ ├── stage3_email.dart # Email (Google / KRA / Manual OTP)
│ ├── stage4_pan.dart # PAN entry + NSDL verify
│ ├── stage5_digilocker.dart # DigiLocker WebView + mock bypass
│ ├── stage6_bank.dart # UPI RPD or manual or Decentro pre-verified
│ ├── stage7_liveness.dart # Camera selfie + HyperVerge
│ ├── stage8_signature.dart # Draw signature on canvas
│ ├── stage9_personal.dart # Personal details + income + F&O + nominees
│ ├── stage10_income.dart # Deprecated (redirects to stage 9)
│ ├── stage11_validation.dart # Backend compliance validation (animated)
│ ├── stage12_document.dart # AOF PDF generation
│ ├── stage13_esign.dart # eMudhra/HyperVerge eSign WebView
│ ├── stage14_account.dart # CBOS account creation
│ └── stage15_congrats.dart # Success screen + Razorpay fund transfer
│
├── widgets/ # Reusable widgets
│ ├── loading_overlay.dart # Full-screen Lottie loader
│ ├── session_timer.dart # 15-min inactivity timeout + warning
│ ├── back_button_handler.dart # Intercepts device back button
│ ├── progress_bar.dart # JourneyProgressBar (16-stage striped)
│ ├── striped_progress_painter.dart # CustomPainter for striped fill
│ ├── error_dialog.dart # Error dialog + snackbar helpers
│ ├── otp_input.dart # 4-digit OTP box input
│ └── consent_checkbox.dart # Consent checkbox with rich text
│
├── app.dart # MaterialApp root (theme, routes)
└── main.dart # Entry point, orientation lock, storage init
The Five Sub-folders Explained
config/
Compile-time constants. Nothing here has state. All values are static. Read once at startup, never change.
| File | Purpose | Jump to |
|---|---|---|
api_config.dart | All backend endpoint paths as getters. Environment flag. Timeouts. | 09 - Config |
routes.dart | Static route names (/, /otp, etc.) and stage → route map for resume logic. | 09 - Config |
theme.dart | MaterialApp ThemeData. RISE brand colors, Inter font, 8px button radius, AppBar style. | 09 - Config |
assets.dart | Static path constants for Lottie JSONs, SVGs, PNGs. | 09 - Config |
models/
Dart classes that mirror backend response shapes. Each has a fromJson factory. No methods beyond data access. Immutable where possible.
flutter_app/lib/models/api_response.dartDart
class ApiResponse<T> {
final bool success;
final String? message;
final String? errorCode;
final T? data;
final String displayMessage;
ApiResponse({
required this.success,
this.message,
this.errorCode,
this.data,
required this.displayMessage,
});
static ApiResponse<T> ok<T>(T data, [String? msg]) => ...
static ApiResponse<T> fail<T>(String msg, [String? code]) => ...
}
services/
Where the business logic and external interactions live. Three files only.
| File | Purpose | Jump to |
|---|---|---|
api_service.dart | 60+ methods, one per backend endpoint. Handles auth, headers, error handling, stage tracking. | 07 - ApiService |
storage_service.dart | Singleton. Wraps SharedPreferences. Stores leadId, sessionId, token, currentStage, last activity. | 07 - ApiService |
analytics_service.dart | Stub. Currently just debugPrints events. Plug in Firebase/CleverTap later. | 07 - ApiService |
screens/
One file per stage. Each file contains everything for that stage: the widget, local state, event handlers, API calls, validation, UI building. No BLoCs, no separate controllers.
Each stage is self-contained. To understand Stage 6, open stage6_bank.dart - it's all there. No need to hunt across 5 files.
See 06 - Stage Walkthrough for a full trace of Stage 1.
widgets/
Reusable UI pieces. Five wrapper widgets handle cross-cutting concerns (loading, session timeout, back button, progress, error). No business logic.
See 08 - Widgets Reference for the full catalog.
pubspec.yaml - Dependencies
flutter_app/pubspec.yamlYAML
name: ekyc_app
description: MOSL EKYC 3.0 - Digital Account Opening Journey
version: 3.0.0+1
environment:
sdk: '>=3.2.0 <4.0.0'
dependencies:
flutter:
sdk: flutter
http: ^1.2.0 # REST client used by ApiService
shared_preferences: ^2.2.2 # Key-value storage (StorageService)
path_provider: ^2.1.2 # File paths (for signature save)
google_sign_in: ^6.1.6 # Stage 3 email Google OAuth
file_picker: ^8.0.0 # Stage 9 income proof upload
url_launcher: ^6.2.2 # Open external URLs (T&C, Razorpay redirect)
webview_flutter: ^4.4.3 # Stage 5 DigiLocker, Stage 13 eSign
permission_handler: ^11.1.0 # Camera/location permissions
sms_autofill: ^2.3.0 # Stage 2 OTP auto-read
signature: ^5.4.1 # Stage 8 signature canvas
geolocator: ^11.0.0 # GPS for Stage 7 liveness
razorpay_flutter: ^1.3.7 # Stage 15 mobile payment SDK
image_picker: ^1.0.7 # Camera/gallery for selfie
google_fonts: ^6.2.1 # Inter font from Google Fonts
lottie: ^3.3.1 # Lottie animations (loader, tick, congrats)
flutter_svg: ^2.2.0 # SVG rendering (RISE logo, illustrations)
flutter:
uses-material-design: true
assets:
- assets/images/ # Registers all 41 asset files
assets/images/
41 files. Copied from the old EkycDevProject app as part of the visual migration.
| Type | Count | Examples |
|---|---|---|
| Lottie animations (JSON) | 5 | ic_loader.json, ic_tick_animation.json, congratulation_animation.json, no_connection.json, riselogo.json |
| SVG illustrations | 12 | ic_rise_logo.svg, ic_register_illustration.svg, ic_pan_illustrator.svg, ic_selfieimage.svg, ... |
| PNG icons | ~21 | ic_tick_green.png, ic_calender.png, digilocker.png, ic_gpay.png, ... |
| WebP images | 3 | location.webp, location_on.webp, upi.webp |
All assets are referenced via AppAssets constants in lib/config/assets.dart. Never hardcode a path string in a screen file - always use the constant.
Entry Points
flutter_app/lib/main.dartDart
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'app.dart';
import 'services/storage_service.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// Lock to portrait mode
await SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown,
]);
// Initialize singleton storage (async)
await StorageService.getInstance();
runApp(const EkycApp());
}
main.dart does three things: lock orientation, init storage, launch the root widget. The actual MaterialApp is in app.dart.