PPrepLearn
Progress Β· 0/6 phases

πŸ—“οΈ πŸ—“οΈ 60-Day Plan β€” All Days Reference

8 min read Β· Notion

Use this as your daily reference. Duplicate one row into your tracker for each day you study. Each day has a specific milestone β€” not β€œlearn X” but β€œship Y.”


πŸ“¦ Phase 1 β€” KMP Foundations (Days 1–12)

DayTopicDaily Milestone
1KMP Project SetupKMP Wizard project. Android + iOS + Desktop all compile. Platform() shows different name on each.
2Gradle KMP Configurationlibs.versions.toml fully written. shared/build.gradle.kts compiles all 4 targets cleanly.
3Source Sets & HierarchyappleMain intermediate source set created and compiles. Source set hierarchy diagram drawn.
4Source Set DependenciesAll deps placed per source set. No Android import in commonMain. Verified with compiler.
5expect/actual BasicsPlatform() + randomUUID() + currentTimeMillis() in commonMain. actual in all 3 platforms.
6expect/actual: Settings & LoggerAppSettings + AppLogger + ConnectivityObserver working on Android + iOS + Desktop.
7expect/actual: Crypto & SecuritySecureStorage interface. Android EncryptedSharedPreferences + iOS Keychain both work.
8Convention Pluginsbuild-logic module. KmpLibraryConventionPlugin applies to shared. No duplicated Gradle config.
9Static Analysisdetekt + ktlint running. BinaryCompatibilityValidator added. API dump committed.
10Phase 1 Project: KMP Skeleton3 platforms show Platform().name from same shared class. ./gradlew **:shared:**allTests green.
11Domain LayerUser + Post models. UserRepository interface. 5 use cases. Zero framework imports in domain.
12Clean Architecture in KMPBoundaries verified. Mappers written. DTO β‰  domain model β‰  UI model all separate.

πŸ“ Phase 2 β€” Shared Business Logic (Days 13–28)

DayTopicDaily Milestone
13Ktor Client SetupcreateHttpClient() with ContentNegotiation + Auth + Logging + Retry. Engine injected per platform.
14Ktor DTOs & Error HandlingUserDto @Serializable. safeApiCall wrapper. NetworkResult sealed class.
15Ktor Remote Data SourcesUserRemoteDataSource: getUsers, getUserById, createUser, uploadAvatar all working.
16SQLDelight SchemaUser.sq + Post.sq with all queries. ./gradlew generateSqlDelightInterface runs clean.
17SQLDelight Driver expect/actualcreateDatabaseDriver() actual for Android + iOS + Desktop. DB opens on all platforms.
18SQLDelight Flow IntegrationgetAllUsers() returns Flow<List<User>>. Emits on every table change. mapToList(IO) used.
19Repository ImplementationUserRepositoryImpl: offline-first. Emits local immediately, refreshes from network async.
20Repository: Create & UpdatecreateUser + updateUser + deleteUser all working. SQLDelight transactions used for bulk ops.
21Koin: DI Module SetupnetworkModule + databaseModule + repositoryModule. sharedModules() function exported.
22Koin: Android & iOS ModulesandroidModule with Context. iosModule. startKoin called correctly on both platforms.
23Koin: ViewModel ModuleviewModelModule with viewModelOf(). koinViewModel() in Compose. koinScreenModel() in Voyager.
24Shared ViewModelUserListViewModel: StateFlow<UserListState> + Channel<UserListEffect>. init observes + refreshes.
25ViewModel: State MachineLoading β†’ Success β†’ Error states. Refresh updates isRefreshing not isLoading. Effects fire once.
26ViewModel: Create & DetailCreateUserViewModel with form validation. UserDetailViewModel with posts sub-list.
27Offline-First: TTL & Cache InvalidationCache TTL in SQLDelight (updatedAt column). Stale check in repository before network call.
28Phase 2 Project: Full Data LayerFakeRepository tests pass with Turbine on JVM + iOS. Offline-first flow verified. allTests green.

🎨 Phase 3 β€” Compose Multiplatform UI (Days 29–42)

DayTopicDaily Milestone
29CMP Entry PointsApp() in commonMain. MainActivity + MainViewController + Desktop main(). All load same Composable.
30ContentView.swift + Koin InitContentView wraps ComposeUIViewController. KoinInitializer.init() in SwiftUI @main App.
31Material 3 ThemeLightColorScheme + DarkColorScheme + AppTypography + AppShapes. AppTheme() composable.
32Design TokensDimensions, AppIcons, AppColors objects. All components use tokens, no hardcoded values.
33Voyager Tab NavigationTabNavigator with Home + Search + Profile tabs. BottomNavigationBar. TabNavigationItem.
34Voyager Stack NavigationNavigator + SlideTransition. UserListScreen pushes UserDetailScreen. Back stack works.
35UserListScreenLoading/Empty/Error/Content states. PullRefresh. Voyager LocalNavigator for navigation.
36UserDetailScreenUser profile header. Posts LazyColumn. Follow button with loading state.
37Shared ComponentsUserCard, PostCard, AppButton (3 variants), AppTextField (with error), ConfirmDialog.
38Compose Resourcesstrings.xml (EN + HI). painterResource for images. fontResource. stringResource used everywhere.
39CreateUserScreenForm with validation. isSubmitting state disables button. Error messages below fields.
40SettingsScreenTheme toggle. Account info. Logout with ConfirmDialog. All state in SettingsViewModel.
41Adaptive LayoutsWindowSizeClass used. Phone: single panel. Tablet/Desktop: 2-panel master-detail.
42Phase 3 Project: Full CMP AppAndroid + iOS + Desktop: all 5 screens working. Navigation correct. Adaptive layout on desktop.

πŸ“± Phase 4 β€” Platform APIs & iOS Interop (Days 43–54)

DayTopicDaily Milestone
43SKIE Installation & Configskie block in shared/build.gradle.kts. Build succeeds. Check Swift output has no manual wrappers.
44SKIE: StateFlow β†’ AsyncSequenceAuthState sealed class. Swift for-await loop over viewModel.authState. Exhaustive switch works.
45SKIE: Suspend β†’ async/throwslogin() suspend fun called as async throws in Swift. Error mapped to Swift Error type.
46SecureStorage: AndroidAndroidSecureStorage with EncryptedSharedPreferences. saveString + getString + clear tested.
47SecureStorage: iOS KeychainIosSecureStorage with SecItem APIs. Save + retrieve token. Survives app restart.
48Image Picker: AndroidActivityResultContracts.PickVisualMedia. ByteArray returned. Upload via Ktor multipart.
49Image Picker: iOSUIImagePickerController delegate. ByteArray from UIImageJPEGRepresentation. Upload tested.
50Push NotificationsNotificationHandler in commonMain parses payload. AndroidFMS + iOS APNs delegate both route to it.
51GPS & Location: AndroidAndroidLocationService with FusedLocationProvider. getCurrentLocation() tested.
52GPS & Location: iOSIosLocationService with CLLocationManager. requestPermission() returns Bool. Flow works.
53Biometric AuthBiometricManager expect/actual. Android BiometricPrompt. iOS LAContext evaluatePolicy.
54Phase 4 Project: Native FeaturesLogin with biometrics. Photo upload. Push notification routing. GPS nearby users. SKIE verified.

πŸš€ Phase 5 β€” Production & CI/CD (Days 55β€”60)

DayTopicDaily Milestone
55Testing: commonTest + TurbineUserRepositoryTest with TestSqlDriver + FakeRemote. runTest used. JVM + iOS sim both pass.
56Testing: ViewModel + PaparazziUserListViewModelTest state machine tested. Paparazzi: UserCard in light/dark/landscape.
57GitHub Actions: CI PipelinePR workflow: JVM tests + screenshot tests + lint in < 5 min. iOS tests on main branch only.
58GitHub Actions: Build Pipelinebuild-android job: release AAB signed + artifact. build-ios job: XCFramework + archive.
59Fastlane: Deployfastlane android deploy_internal uploads AAB. fastlane ios deploy_testflight uploads IPA.
60Capstone: Production KMP Appgit tag v1.0.0 β†’ Play Store internal + TestFlight automatically. All checklists green.

πŸ“Š Daily habit

  1. Open this table. Find today’s row.
  2. Study the topic. Write the code.
  3. Hit the daily milestone β€” not β€œread about it” but β€œship it.”
  4. Log in tracker: tick Runs on Android / iOS / Desktop when each target works.
  5. Tick Code in commonMain if you wrote platform-agnostic shared code today.
  6. Write one sentence in Key concept learned β€” your own words, not copied.

πŸ’‘ The rule: if the code only runs on one platform, it doesn’t count as KMP. Every day’s milestone must be verified on at least 2 targets.

Related