15 - Master Dev Help

A single lookup sheet: "I want to change X in the Flutter app — which file do I open?" Pick a category from the index below, scan the table, click through to the file or to the detailed page that explains the pattern.

How to use this page

This is a cheat-sheet, not a tutorial. Every row answers one question: where does this live? For the why and the how of a topic, click the "see also" link in each section to jump to the full guide.

Entry Point & Routing

I want to change…Open this fileNotes
App bootstrap / MaterialApp / theme wiringlib/main.dart
lib/app.dart
main() runs platform init then pushes App as the root widget.
The route table (all stage screens)lib/config/routes.dartSingle source of truth for route names and the stageRoutes map used by resume logic.
Initial screen after splashlib/screens/stage0_arrival.dartHandles fresh vs resume flow, calls getJourneyStatus() and navigates.
Deep-link handlinglib/app.dart (MaterialApp onGenerateRoute)Named routes from routes.dart are matched here.

Screens (one per stage)

Every eKYC stage is a single Stateful widget under lib/screens/stage<N>_<name>.dart. The pattern is: capture input → call api.* → navigate or show error. See 06 - Stage Walkthrough for an end-to-end trace.

StageFileWhat happens here
0 — Arrival / splashlib/screens/stage0_arrival.dartDevice init, session resume logic, route picker.
1 — Registrationlib/screens/stage1_registration.dartMobile, name, consents, signup call.
2 — OTP verificationlib/screens/stage2_otp.dartOTP input, resend, verifyOtp call.
3 — Email verificationlib/screens/stage3_email.dartEmail input, email OTP.
4 — PAN confirmationlib/screens/stage4_pan.dartPAN confirm / entry, KRA pre-fill.
5 — Aadhaar via DigiLockerlib/screens/stage5_digilocker.dartDigiLocker webview / callback handling.
6 — Bank verificationlib/screens/stage6_bank.dartAccount + IFSC, penny-drop SDK, result confirm.
7 — Liveness + photo matchlib/screens/stage7_liveness.dartCamera permission, liveness SDK, face-match result.
8 — Signaturelib/screens/stage8_signature.dartSignature pad, upload.
9 — Personal details + nomineeslib/screens/stage9_personal.dartOccupation, income, FATCA, nominee flow, income-proof upload.
10 — Income proof (optional)lib/screens/stage10_income.dartAlternative income-proof path (OneMoney AA).
11 — Final validationlib/screens/stage11_validation.dartSummary screen before document generation.
12 — Document generationlib/screens/stage12_document.dartPolls AOF generation, shows status.
13 — eSignlib/screens/stage13_esign.dartLaunches eSign flow + handles callback.
14 — Account creationlib/screens/stage14_account.dartPolls CBOS account creation status.
15 — Congrats / activationlib/screens/stage15_congrats.dartSuccess state, payment CTA, downstream sync.

Widgets (reusable)

All shared widgets live in lib/widgets/. See 08 - Widgets Reference for props and usage.

WidgetFileUsed for
LoadingOverlaylib/widgets/loading_overlay.dartFull-screen spinner over a screen during async calls.
SessionTimerlib/widgets/session_timer.dartInactivity countdown + session-expired dialog.
BackButtonHandlerlib/widgets/back_button_handler.dartShows "Exit journey?" confirmation on Android back / swipe.
ProgressBarlib/widgets/progress_bar.dart
lib/widgets/striped_progress_painter.dart
Journey progress header (stage N of 15).
ErrorDialoglib/widgets/error_dialog.dart.show (returns Future), .showSuccess (void snackbar).
ConsentCheckboxlib/widgets/consent_checkbox.dartLegal text checkbox with link support.
OtpInputlib/widgets/otp_input.dartAutofill-aware OTP boxes.

Services (API, storage, analytics)

Only three services exist — on purpose. All backend calls go through ApiService. See 07 - ApiService.

ServiceFileResponsibility
ApiServicelib/services/api_service.dartEvery HTTP call. Headers, JWT, _post / _get helpers, ApiResult<T> wrapper. If the backend is involved, it goes here.
StorageServicelib/services/storage_service.dartSharedPreferences-backed persistence for leadId, JWT, resume state, device id. Singleton via getInstance().
AnalyticsServicelib/services/analytics_service.dartEvent tracking wrapper (mostly no-op in dev, Clevertap-bound in prod).

Models & data classes

All DTOs are plain Dart classes with fromJson factories under lib/models/. No code generation, no freezed — everything is hand-written so the Flutter build is simple. Grep for the class name when you need to update a backend-matching DTO.

Config, Theme & Assets

I want to change…Open this fileNotes
Backend base URL per environmentlib/config/api_config.dartSet via --dart-define=ENV=dev|uat|prod.
Theme colors / fontslib/config/theme.dartSingle AppTheme with a Material 3 color scheme and Google Font Inter.
Route nameslib/config/routes.dartConstants only; no registration logic.
Asset paths (Lottie, images, svg)lib/config/assets.dartOne constant per asset so refactors are one-file changes.
Register a new assetpubspec.yaml → flutter.assetsThen add a constant in lib/config/assets.dart.
Change the app name / bundle id / iconandroid/app/build.gradle
ios/Runner/Info.plist
android/app/src/main/res/
ios/Runner/Assets.xcassets/
Platform-specific. Don't forget to regenerate launcher icons if changing.

State & data flow

No global state manager. Each screen is a StatefulWidget that owns its own local state. Cross-screen data goes through StorageService (persisted) or via the backend (source of truth). See 05 - Coding Patterns for the reasoning.

Need…Use…Notes
Local screen state (form inputs, toggles)setState in a StatefulWidgetNo Bloc, no Provider, no Riverpod.
Data that survives app restart (leadId, JWT, resume)StorageServiceAsync singleton via StorageService.getInstance().
Cross-screen communication (current stage, user name)Fetch from backend via ApiService → never pass via constructors across stages.Keeps stage screens independently launchable (important for resume).
Error handlingApiResult<T> returned from every ApiService callCheck .success and use .displayMessage or .errorCode.

Platform-specific files

PlatformRoot folderWhat lives there
Androidandroid/Gradle build files, AndroidManifest.xml, launcher icons, runtime permissions, Google Services config.
iOSios/Info.plist, Runner Xcode project, app icons, push entitlements.
Webweb/index.html, favicon, manifest. Used by flutter build web.
Windows / macOS / Linuxwindows/ / macos/ / linux/Desktop shells; not part of the shipping product but kept buildable.

Build, Run & Environments

I want to…Run thisNotes
Run on a connected device in devflutter run --dart-define=ENV=devDefault flavour = dev. See 01 - Getting Started.
Run on web (Chrome)flutter run -d chrome --dart-define=ENV=devSome native plugins stub out on web — see plugin docs.
Point at a different backend--dart-define=API_BASE_URL=http://<host>:5000Set inside api_config.dart.
Build a release APKflutter build apk --release --dart-define=ENV=prodSigned with Play upload key in CI.
Build a release IPAflutter build ipa --release --dart-define=ENV=prodRequires Apple signing set up in Xcode.
Build web for stagingflutter build web --release --dart-define=ENV=uatDrops output to build/web.
Refresh dependencies after pullingflutter pub getOr flutter clean && flutter pub get if things get weird.

Debugging & Logging

I want to…Use thisNotes
See network requests liveDevTools → Network tab
or debugPrint inside ApiService
Every request already logs the URL and status code in dev mode.
Inspect the widget treeDevTools → Widget Inspector (Flutter)Select an element on the device to jump to its source.
Debug layout issuesDevTools → Layout ExplorerOr add debugPaintSizeEnabled = true in main.dart.
Debug a specific screen in isolationPush it directly from a dev-only buttonEvery stage screen can be launched standalone; data comes from the backend.
Set a breakpoint in VS Code / Android StudioClick the gutter next to a line → run with debuggerHot reload still works during a breakpoint.
Check what's stored locallyDevTools → StorageService getters in a watch expressionKeys: leadId, jwtToken, resumePage, currentStage, deviceId.

See 10 - Debugging for the full guide.

Static Analysis (Sonar)

I want to…Run thisNotes
Run the analyzerflutter analyzeUses analysis_options.yaml (which includes very_good_analysis).
Auto-fix all safe issuesdart fix --applyBig diff — review before committing.
Generate the HTML Sonar reportnode scripts/to_sarif.jssarif htmlFull workflow: 14 - Sonar Analysis.
Run the bulk fixersscripts/fix_unawaited.js
scripts/fix_inference.js
scripts/fix_with_opacity.js
Each script is self-documenting. Re-run flutter analyze --write=... before re-running a fixer.

Common "Where do I add…"

New thingAdd it hereDon't forget
A new stage screenlib/screens/stage<N>_<name>.dart
Register route in lib/config/routes.dart
Add to stageRoutes map for resume logic
Update StageDefinitions in the backend constants in lockstep.
A new backend API calllib/services/api_service.dart → new method returning Future<ApiResult<T>>Reuse _post / _get; they handle auth + error envelope.
A new DTO / modellib/models/<name>.dartPlain Dart class with fromJson factory. No codegen.
A new shared widgetlib/widgets/<name>.dartFollow the wrapper style of existing widgets; see 08 - Widgets Reference.
A new asset (Lottie, PNG, SVG)assets/… + pubspec.yaml + lib/config/assets.dartAll three steps or it won't load.
A new color / font weightlib/config/theme.dartKeep everything in the theme — do not inline colors in screens.
A new environment (e.g. STAGE)lib/config/api_config.dart
README for CI / launcher scripts
Flutter flavours are optional — --dart-define is the primary switch.
A platform permissionandroid/app/src/main/AndroidManifest.xml
ios/Runner/Info.plist
Both platforms. Runtime check in Dart via permission_handler.
A new push channel / deep linkandroid + iOS config + lib/app.dart onGenerateRouteTest with adb shell am start -W -a android.intent.action.VIEW -d <url>.
Still lost?

Open 03 - Project Tour for the folder-by-folder walkthrough, 06 - Stage Walkthrough for an end-to-end trace of Stage 1, or 11 - How-To Guides for task-oriented recipes.