-
-
Garmify turns the clothes you already own into outfits you'll wear. One Compose Multiplatform codebase, live on iOS and Android.
-
Garmify Pro: native Compose paywall driven by a RevenueCat offering. Prices, savings badge and 7-day trial all come from the store.
-
Today: a weather-aware outfit every morning, built only from garments you own. Shuffle for another idea or log what you wore.
-
Wardrobe: background removed on-device (ML Kit / Apple Vision), then AI tags category, color and season. Every tag is editable.
-
Outfits: AI-suggested combinations from your own closet. Save the looks you love and wear them again.
-
Today: unframed iPhone screenshot (1179×2556).
-
Wardrobe: unframed iPhone screenshot (1179×2556).
-
Outfits: unframed iPhone screenshot (1179×2556).
-
Garmify Pro paywall: unframed iPhone screenshot (1179×2556).
-
Garmify app icon (1024×1024).
Inspiration
Most of us stand in front of a full closet and feel like we have nothing to wear. We rotate through the same few pieces while the rest sits forgotten, and then we buy more. I wanted an app that starts from what you already own, not from a shop: photograph your clothes once, and every morning get an outfit that fits today's weather, built only from your own wardrobe.
What it does
Garmify is an AI wardrobe and outfit planner for iOS and Android.
- Your closet, organized: snap a garment and the background is removed on-device. AI tags its category, color and season, and every tag stays editable.
- Today's outfit: a weather-aware look every morning (Open-Meteo forecast), picked only from clothes you own. Shuffle for another idea, and log what you wore.
- Outfits: save the combinations you love and wear them again.
- Weekly Planner (Pro): plan every day of the week against the real forecast, or auto-plan the empty days in one tap.
- Trip Packer (Pro): enter destination, dates and vibe, and get a small capsule of pieces that mix into many outfits, plus a packing checklist.
- Sign in with Apple, Google or email: your closet is backed up and restored on any device.
- Fully localized in English and Turkish.
How it makes money
A freemium subscription powered by RevenueCat on both stores:
- Free: up to 30 garments and 3 outfit shuffles a day, enough to feel the value.
- Garmify Pro: unlimited garments, 15 shuffles a day, and the Weekly Planner and Trip Packer. Monthly or yearly, with a 7-day free trial.
- The paywall is a native Compose Multiplatform screen, driven entirely by the RevenueCat offering. Prices, the yearly "Save X%" badge (computed from the store's price micros) and the trial length are all read from the store, not hard-coded. I can change pricing, run per-country prices or add intro offers without shipping a release.
- One
proentitlement shared across iOS and Android, so a subscriber is Pro on both. - A RevenueCat → Supabase webhook (Edge Function) keeps the server-side entitlement correct. It treats every event as a "this customer changed" signal and re-reads the truth from the RevenueCat API. That avoids the classic bugs where a cancellation is mistaken for lost access, or a billing-issue grace period is ignored.
- A win-back offer is already modeled in the app, ready to ship as the next monetization experiment.
How I built it
One Kotlin codebase, two native apps. Garmify is built with Kotlin Multiplatform + Compose Multiplatform. About 94% of the code lives in commonMain: UI, navigation, ViewModels, domain logic, the Room database, networking, sync and billing. Only thin expect/actual seams are platform-specific:
- Background removal: ML Kit Subject Segmentation on Android and Apple Vision
VNGenerateForegroundInstanceMaskRequeston iOS. Both run on-device, so they're free and private. - Sign-in: native Sign in with Apple and Google on each platform.
- Billing: one shared
RevenueCatBillingGatewayin common code using purchases-kmp, the same implementation on both platforms.
Architecture: Clean Architecture with an MVI presentation layer (state, props, intents), Koin for DI, Kotlin coroutines and Flow throughout.
Local-first data: a Room (KMP) database is the source of truth, so the app works offline. A sync layer mirrors all user tables and garment images to Supabase (Postgres, Auth, Storage).
AI on the server, not in the app: tagging and outfit suggestions run in Supabase Edge Functions, so no AI keys ship in the binary. The model and provider are configuration, not code. I can switch providers (currently Gemini Flash for vision tagging) with a secret change and no app release.
Observability: Firebase Analytics and Crashlytics on both platforms.
Challenges I ran into
- A Kotlin ABI wall on iOS. purchases-kmp was compiled with a newer Kotlin than my project, and Kotlin/Native klibs reject that mismatch (Android JVM klibs don't). Billing was Android-only until I upgraded the whole project to Kotlin 2.3.21. After that I moved the RevenueCat gateway into common code and deleted the platform-specific stubs.
- A "free Pro" hole with two homes. An audit found that a build with no RevenueCat key would unlock Pro on "Subscribe" for free, and the same fallback existed in two layers. Now the mock purchase only runs in debug builds, and a misconfigured release fails loudly instead of silently granting access.
- App Review. My first iOS submission was rejected because sign-in handed off to Safari. I moved OAuth into an in-app
ASWebAuthenticationSessionon both platforms. I also found that a deprecated one-argumentopenURLwas silently killing every outbound link on iOS. - AI providers retire models without notice. One vision model disappeared from under my tagging function mid-development. That's why the endpoint, model and key are now secrets, not constants.
- Shipping two stores at once as a solo developer: subscription setup on Play Console and App Store Connect, three different Apple credentials for RevenueCat, and an iOS release build that needed more than 2 GB of memory just to link.
Accomplishments that I'm proud of
- From an empty repo on July 11 to live on both the App Store and Google Play within the Shipaton window, from one codebase.
- Pricing and trials are fully store-driven, so monetization experiments need no releases.
- Private by default: background removal runs on-device, and the app works offline.
What I learned
- Compose Multiplatform is ready for production: one UI codebase shipped to both stores with a native feel.
- RevenueCat removes a huge amount of platform-specific billing work, but the entitlement model (one entitlement, one project, both stores) needs to be right from day one.
- When you remove a fake-success path, check every layer above it for the same behavior.
What's next for Garmify
- Paywall A/B tests with RevenueCat Experiments (trial length, yearly-first vs monthly-first).
- Smarter outfit suggestions that learn from what you actually wear.
- More languages, and a web-to-app funnel.
Shipaton categories
JetBrains: Ship Kotlin Everywhere. Garmify is a Kotlin Multiplatform + Compose Multiplatform app published on both the App Store and Google Play, with about 94% shared code. Shared UI, domain, data (Room KMP, Ktor, Supabase-kt) and billing (purchases-kmp). Platform code is limited to on-device segmentation and native sign-in.
HAMM Award. Freemium with a clear value ladder, a 7-day trial and a fully store-driven native paywall. The server-side entitlement is kept honest by a RevenueCat webhook.
RevenueCat Design Award. A custom Compose design system and logo, background-removed garment "cut-outs" that make a closet feel like a lookbook, and a paywall designed as part of the app rather than bolted on.
Built With
- android
- apple-vision
- compose-multiplatform
- coroutines
- crashlytics
- deno
- firebase
- gemini
- ios
- jetpack-compose
- koin
- kotlin
- kotlin-multiplatform
- ktor
- ml-kit
- open-meteo
- postgresql
- revenuecat
- room
- sign-in-with-apple
- sqlite
- supabase
- supabase-edge-functions
- typescript
Log in or sign up for Devpost to join the conversation.