CASE STUDY / 01 ANDROID + iOS
Trendy.
One experience.
Two platforms.
From a product that catches your eye to a cart that keeps up. A closer look at building a shared mobile shopping experience with Kotlin and Compose.
- Product
- Mobile commerce
- Platforms
- Android & iOS targets
- Interface
- Compose Multiplatform
- Data & state
- Firebase · Kotlin Flow
THE CHALLENGE
Make shopping feel like one continuous journey.
A shopper moves between discovery, product details and their cart. Those screens need to agree on the product, the quantity and what happens next—even when the data changes.
Trendy approaches that problem with shared Compose screens, feature-level ViewModels and repository-backed data flows. The repository includes product browsing, categories, account management, a cart, checkout and product administration.
This case study follows the catalog-to-cart slice. The decisions below describe the implementation in the repository and its engineering tradeoffs; they are not claims about production adoption or measured business results.
TOUCH THE EXPERIENCE
A small shop.
A real interaction.
Pick a product, choose a quantity and build a cart. Change your mind, remove an item, or start again.
- DiscoverBrowse the sample catalog or filter by category.
- ChooseOpen a product and select between 1 and 10 items.
- RefineEdit your cart and see the subtotal update.
This is a browser recreation of the shopping flow, inspired by the app’s interface. Products and prices are illustrative. The original app screenshots are below.
Products
No sample products in this category. Choose another category to continue.
Discounted Products
Categories
Your cart
Your cart is empty. Find something you like to get started.
Sample prices in USD. No shipping or tax calculation.
A LITTLE PREVIEW OF THE JOURNEY
Ready for the next step.
Your selection totals .
The app continues to checkout. This demo ends here: no order is placed, no payment is taken and no personal details are collected.
Browser recreation · Sample products · No sign-in or payment
BEHIND THE INTERFACE
Three decisions.
The reasoning behind the build.
COMPOSE MULTIPLATFORM
Share the experience. Keep the platform boundary.
Trendy puts its shopping screens and business logic in commonMain. The Android host and the iOS ComposeUIViewController connect to the same App entry point, while platform-specific integrations live outside the shared UI.
What this enables
One shared implementation can carry a product interaction across Android and iOS, reducing the number of separate UI paths to maintain.
The tradeoff
Sharing the UI does not remove platform work. Lifecycle behavior, native integrations and the feel of each platform still need separate verification.
FEATURE MODULES · KOIN
Give features a boundary, not a database dependency.
Catalog, product details, cart and checkout have their own feature modules. ViewModels receive repository interfaces through constructor injection; the shared Koin module binds those interfaces to concrete implementations.
What this enables
A screen can express what data it needs without owning the Firestore implementation. That boundary provides a place to substitute a data source or a test double.
The tradeoff
More modules bring more Gradle wiring and dependency decisions. The useful boundary is the responsibility of each feature—not simply the number of modules.
KOTLIN FLOW · EXPLICIT STATE
Derive the cart from the data that changes.
CartViewModel reads the customer stream, extracts unique product IDs with flatMapLatest, and combines the customer and product streams into cart rows. RequestState represents loading, success and error explicitly.
What this enables
The cart presentation follows the latest customer and product data. An empty cart produces an empty product list without starting a product lookup.
The tradeoff
Combining streams means handling partial and failed results. The current mapping omits cart entries whose product is missing; a future iteration could explain unavailable items directly to the shopper.
FROM THE APP
The original experience.
Android screenshots included in the Trendy repository. These are captures of the app, separate from the interactive recreation above.



WHAT I WOULD EXPLORE NEXT
Make the edges
as clear as the happy path.
The next useful iteration would focus on unavailable products, recovery from data errors, and predictable cart behavior when connectivity changes.
Those are proposed next steps, not completed features. The current implementation provides concrete boundaries—repository interfaces, ViewModels and request states—where that work can be developed and tested.
Read the Trendy repository ↗