Chapter 1 — Why Kotlin Multiplatform, Honestly
- The problem you already know
- What Kotlin Multiplatform actually is
- What Compose Multiplatform is, and why it’s a separate decision
- The sharing spectrum
- How KMP differs from Flutter and React Native
- Where KMP genuinely wins
- Why Android developers have an unfair advantage right now
- Where KMP will let you down (read this part twice)
- Why this is a good moment, specifically
- The app we’ll build: Atlas
- How this book works
- What you’ll have by the end
- Summary
Chapter 2 — How Kotlin Multiplatform Actually Works
- The magic trick, explained
- The one idea that unlocks everything: common code vs platform code
- Source sets: where your code lives, and what it can see
- The source set hierarchy: why
iosMainexists - Targets: what your code compiles to
expect/actual: the mechanism for “write once, adapt per platform”- When not to reach for
expect/actual(the honest version) - klib: the format that makes shared code shippable
- Gradle: how it’s all wired together
- Putting it together: the life of a shared function
- How this changes the way you’ll code
- Summary
Chapter 3 — Setting Up and Running on Both Platforms
- The goal, and the shape of getting there
- What you’re installing, and why
- Installing the toolchain
- Verify before you trust: preflight checks and KDoctor
- Creating the project with the wizard
- The anatomy of what you got
- Running on Android: the easy win
- Surviving your first Xcode encounter
- Running on iOS
- What just happened
- When the first run goes sideways
- Summary
Chapter 4 — Compose Multiplatform Fundamentals
- The good news, stated plainly
- The shape of a Compose Multiplatform app
- Previews now work in common code
- What’s genuinely different on iOS
- Building Atlas’s first shared screen
- A first taste of resources
- Summary
Chapter 5 — Design System, Theming, and Resources
- Why a design system, and why define it once
- Atlas’s color scheme, light and dark
- Typography and custom fonts
- Images and the resources system in depth
- Strings, localization, and right-to-left
- Adapting to screen size
- Summary
Chapter 6 — Navigation and App Structure
- The navigation problem, and why it’s harder here
- The landscape, and Atlas’s choice
- Setting up navigation
- Type-safe routes
- Atlas’s navigation graph
- The bottom navigation bar
- The iOS realities you must respect
- Summary
Chapter 7 — Architecture for a Multiplatform App
- Why architecture matters more here
- The layers
- The dependency rule
- What lives in common versus platform
- The multiplatform ViewModel
- Modeling UI state
- Unidirectional data flow
- Atlas’s blueprint
- Summary
Chapter 8 — Networking with Ktor
- Ktor’s shape: core in common, engine per platform
- Configuring a production-grade client
- Modeling the data: DTOs
- DTO to domain: why the boundary exists
- Making the call: the remote data source
- Error handling that survives reality
- Authentication
- Wiring the seam shut
- Summary
Chapter 9 — Coroutines and Flow Across Platforms
- The good news: coroutines are multiplatform
- Structured concurrency, and why it matters more here
- Dispatchers across platforms
- Flow: the reactive backbone
- The iOS consumption problem
- SKIE: making Kotlin feel native in Swift
- Where this leaves Atlas
- Summary
Chapter 10 — Local Persistence with Room KMP
- Why a local database, and why Room
- Setting up Room for KMP
- Entities: pure Kotlin in commonMain
- DAOs: reactive queries in shared code
- The database class and the constructor mechanism
- The one platform leaf: the database builder
- Type converters and migrations
- Summary
Chapter 11 — Dependency Injection with Koin
- The problem DI solves
- Why Koin
- Modules: declaring how things are built
- The platform module: the bridge for platform leaves
- Initializing Koin
- Koin and Compose: resolving ViewModels
- Koin on the native iOS side
- Summary
Chapter 12 — Repositories and Offline-First
- The offline-first principle
- Single source of truth
- The cache-then-network pattern
- Modeling result state honestly
- Atlas’s offline-first repository
- The Saved feature: offline by nature
- Staleness: when to refresh
- A note on testing offline behavior
- Summary
Chapter 13 — expect/actual in Depth and Platform Abstractions
- What you already know, made systematic
- expect/actual in depth
- The limits, now concrete
- The better default: interface + DI
- The decision rule
- Designing a clean platform abstraction
- The template Part IV will follow
- Summary
Chapter 14 — Permissions and Platform Services
- Why permissions deserve their own chapter
- Two models, genuinely different
- The unified approach: moko-permissions
- Platform setup you cannot skip
- Requesting permission from Compose
- Atlas’s permission gate
- Permission UX principles
- Summary
Chapter 15 — Location
- The template, made concrete
- The Android implementation
- The iOS implementation
- Binding and consuming
- Accuracy versus battery
- Practical realities
- Summary
Chapter 16 — Maps
- Why maps are the honest limit of shared UI
- The interop primitives
- The map decision: MapKit on iOS, Google Maps on Android
- The common declaration and Android side
- The iOS side: MapKit through UIKitView
- Bridging a third-party SDK: the Google-Maps-on-iOS pattern
- Markers, camera, and the route foundation
- Interop gotchas
- Summary
Chapter 17 — Sensors
- Sensors are streams
- The Android side: SensorManager and friends
- The iOS side: CoreMotion
- Binding, and the battery reality
- Availability: not every device has every sensor
- Putting it together: route tracking
- Summary
Chapter 18 — Native UI Interop: The Escape Hatch
- The escape hatch is a feature, not a failure
- The four directions of interop
- Embedding native inside Compose
- Embedding Compose inside native (incremental adoption)
- Calling platform-only and third-party SDKs
- Sharing state across the boundary
- Memory: respect the boundary
- When not to use the escape hatch
- Summary
Chapter 19 — Logging
- Why logging earns a chapter
- Kermit: the multiplatform logger
- Levels and tags
- Logging discipline
- Integrating with networking and errors
- Release versus debug
- Summary
Chapter 20 — Analytics and Crash Reporting
- Production observability is a different problem
- Analytics: a clean event taxonomy
- Crash reporting: the honest landscape
- The iOS symbolication problem
- Privacy and consent
- Wiring it together
- Summary
Chapter 21 — Error Handling and Resilience
- Resilience is a property, not a feature
- The app-wide error model
- Mapping errors to humane UI
- Retry and backoff
- Offline-first as resilience
- Graceful degradation
- The boundary discipline
- Summary
Chapter 22 — Configuration, Secrets, and Feature Flags
- Why configuration is a production concern
- Compile-time config with BuildKonfig
- Secrets: the rules
- Secure runtime storage: the token leaf, finally
- Feature flags
- The debug menu
- Summary
Chapter 23 — Testing Multiplatform Code
- Why testing matters more in multiplatform
- A strategy, not a coverage number
- Unit tests in common code
- Fakes over mocks
- Repository and ViewModel tests
- Compose Multiplatform UI tests
- Summary
Chapter 24 — Performance, App Size, and Memory
- Performance is a feature, and a measured one
- iOS binary size
- Startup time
- Compose performance
- Memory and leaks
- Profiling on both platforms
- Summary
Chapter 25 — CI/CD and Releasing Both Apps
- The shipping problem
- Continuous integration: catch problems before they ship
- Building and signing
- Automating with Fastlane
- The two store pipelines
- Don’t forget the dSYMs
- A release checklist
- Summary
- You built a production app
