Mobile engineer building B2C fintech-grade Android apps — the kind where a dropped connection mid-transfer, a stolen unlocked phone, or a schema migration gone wrong are design inputs, not afterthoughts. Primary stack: Android · Kotlin · Jetpack Compose · Kotlin Multiplatform. IIIT Allahabad.
object Chinmay {
val core = listOf("Android", "Kotlin", "Jetpack Compose", "KMP")
val breadth = listOf("iOS / SwiftUI", "Flutter", "React Native")
val domain = listOf("digital banking", "payments", "ledgers", "KYC onboarding")
val obsessions = listOf(
"what NOT to share in KMP",
"eventual consistency as a UX contract",
"a test suite you actually trust",
)
val default = "boring, well-understood tools — until the novel one earns its place"
}The user taps Send with no signal. What does a serious banking client do? Not spin. Not lie. It persists the intent, shows the truth, and reconciles later.
The offline transfer state machine
stateDiagram-v2
direction LR
[*] --> PENDING: submit · local validation passes · opId assigned
PENDING --> SYNCING: worker picks it up · network available
SYNCING --> CONFIRMED: 2xx · server id returned
SYNCING --> CONFLICT: 409 · needs resolution
SYNCING --> FAILED: 4xx · terminal reason
SYNCING --> PENDING: 5xx / IO · backoff + full jitter · attempts < ceiling
SYNCING --> FAILED: attempts == ceiling
CONFLICT --> PENDING: user re-applies
CONFLICT --> FAILED: user cancels
CONFIRMED --> [*]
FAILED --> [*]
- Idempotency key (
opId, client-generated) persisted before any network attempt → a retried request the server already saw returns the original result. - Optimistic UI — the transfer appears instantly as
PENDING, de-emphasised, with retry / cancel. The app never claims success it can't verify. - Backoff is exponential with full jitter and a ceiling — so every device that went offline in an outage doesn't stampede the server when it returns.
- Conflict resolution is per operation type, not one global rule.
The engine lives in offline-sync-engine (9 tests, standalone); it gets wired into argent-android behind WorkManager.
What I share vs. what I deliberately keep native
flowchart TD
subgraph AND["📱 Android"]
A1["Jetpack Compose<br/>Material 3 · Vico charts"]
A2["ViewModel · collectAsState"]
end
subgraph IOS["🍎 iOS"]
I1["SwiftUI<br/>Swift Charts"]
I2["ObservableObject · SKIE · async/await"]
end
subgraph SHARED["🟣 shared — Kotlin Multiplatform"]
S1["domain — portfolio math, validation, business rules"]
S2["data — repositories, sync, DTO ↔ domain mappers"]
S3["network — Ktor + serialization"]
S4["persistence — SQLDelight"]
end
A2 --> S1
I2 --> S1
S1 --> S2 --> S3
S2 --> S4
A1 -. expect/actual .-> SEC["biometrics · secure storage"]
I1 -. expect/actual .-> SEC
Shared: everything that's expensive to get wrong twice — domain logic, data,
networking, persistence. One implementation, one test suite, run on JVM and
Kotlin/Native. Native: all UI, navigation, charts, notifications, biometric
prompts — the things users actually feel. The decision, module by module, is
written up in SHARING.md.
Built in basis-kmp — shared domain + SHARING.md done, Android app runs, iOS framework links.
|
🏦 argent‑android retail digital banking Multi‑module Kotlin/Compose. Foundation shipped — convention plugins, a currency‑safe domain layer with tests, Hilt‑wired app, green CI. Next: the offline transfer state machine (offline‑sync‑engine behind WorkManager), biometric Keystore, cert pinning. kotlin compose multi‑module offline‑first fintech |
🧩 basis‑kmp shared Kotlin core · Android + iOS One financial core — valuation, cost basis, allocation — shared via Koin, with
fully native Compose and SwiftUI UIs. Domain + tests done, Android app runs,
iOS framework links. Ships kmp compose swiftui koin ios |
|
🧠 slate‑ai on‑device + cloud notes assistant A real RAG pipeline in pure Kotlin — sentence‑aware chunking, embeddings, cosine retrieval — and a routing policy that keeps short lookups on‑device and only escalates to the cloud when the task needs it. 12 tests, Compose app. on‑device‑ai litert rag compose |
🏗️ modulith Android architecture template Gradle convention plugins so a module build file is ~2 lines, plus a
gradle convention‑plugins architecture ci |
|
📡 argent‑track‑sdk KMP analytics & attribution SDK A self‑contained KMP SDK replacing CleverTap + AppsFlyer — durable event queue, push/in‑app campaigns, install attribution, and a client‑side PII denylist. Android + iOS from one codebase. kmp analytics attribution sdk |
📱 argent‑ios native Swift · MVVM SIP/investment, KYC, bank‑account & mandate flows with a generic token‑refreshing network layer. UIKit + SwiftUI. swift mvvm fintech ios |
|
📒 ledger‑core KMP library Double‑entry ledger: balanced journal entries, idempotent postings, a
currency‑safe kmp ledger double‑entry |
💳 pay‑sheet Compose module Card input with Luhn + brand detection, tokenization, a 3‑D‑Secure‑style step‑up state machine, PCI notes. 11 tests, sample app. compose payments 3ds |
🔄 offline‑sync‑engine library Durable queue, exponential backoff + full jitter, pluggable per‑operation conflict strategies. 9 tests. offline‑first workmanager |
|
🔐 mobile‑security‑notes lib + writeups Keystore AES‑GCM, keystore biometrics redaction |
⚡ android‑perf‑lab perf infra Baseline Profile + Macrobenchmark modules, baseline‑profiles macrobenchmark |
🧪 compose‑lab experiments A custom custom‑layout recomposition |
|
🤖 argent‑rag bilingual RAG backend FastAPI + ChromaDB + MongoDB + Gemini. Language‑detecting retrieval, grounded generation, multimodal image queries — English + Hindi collections. python fastapi rag gemini chromadb |
||
|
🔁 argent‑http‑core Ktor client factory Refresh‑on‑401 with careful failure classification — 401/403 force logout,
5xx/network keep the session. Optional‑bearer auth, pure unit‑tested
ktor token‑refresh auth |
||
|
🧭 argent‑checkout MVI checkout state machine Pure‑Kotlin payment‑checkout state machine — three reducers driving every
UPI flow. A kotlin mvi state‑machine |
||
|
📉 argent‑risk‑engine credit-underwriting policy core Pure‑Python loan‑amount policy — SMS‑income waterfall, bureau servicing history, risk segmentation and a FOIR cap combine into a pre‑approved amount. Decile‑direction is declared per model so ascending and descending scorecards can't silently invert each other's risk bands. 26 tests, zero I/O. python credit‑risk decision‑engine |
||
Each repo is built the same way: scaffold →
./gradlew buildgreen → feature commits → tests → CI → README. Honest history, no big‑bang dumps.
A wiki for becoming an Android engineer, from zero to shipping on the Play Store. Each stage is a written note paired with a repo that runs. Start at the wiki or follow the learning path in order.
| Stage | Repo | One line |
|---|---|---|
| 🌀 Coroutines | Learn-Kotlin-Coroutines | network, Room, timeouts, error handling — the hard 20% |
| 🌊 Flow | Learn-Kotlin-Flow | operators, search, retry, backpressure |
| 🏛️ MVVM | MVVM-Architecture-Android | Kotlin + Hilt + Retrofit + Coroutines + StateFlow |
| 🗺️ Roadmap | android-developer-roadmap | nine stages, fundamentals → shipping |
| ☕ Java → Kotlin | from-java-to-kotlin | every concept side by side, with the why |
| Principle | In practice |
|---|---|
| Design for the failure case first | No signal, stolen device, mid-migration — that's where the architecture is decided |
| Share logic, not UI | KMP: domain + data shared, UI native. Knowing what not to share is the skill |
| Measure before claiming a win | A perf number ships with its device, build type and iteration count — or it doesn't ship |
| Trust the test suite | Hand-written fakes over brittle mocks; cover the logic that moves money |
| Boring by default | Proven tools until a new one earns its place |