Back to Blog

From idea to App Store in weeks: how I built Snappit with KMPShip

A real-world case study of building a cross-platform video journaling app for Android and iOS using Kotlin Multiplatform and KMPShip. See exactly what's possible when you ship faster.

Posted by

From idea to App Store in weeks: how I built Snappit with KMPShip

The best way to prove something works is to use it yourself

When I built KMPShip, I had a clear goal: help developers ship Android and iOS apps faster from a single codebase. But how do you prove a boilerplate actually works in production?
You build something real with it.
That's exactly what I did with Snappit - a daily video journaling app that helps people capture 5 seconds of their life every day and automatically compiles those moments into beautiful montages.
This isn't a demo app. It's not a proof of concept. Snappit is a real product, live on both the App Store and Google Play, with real users, real subscriptions, and real revenue.
And it was built entirely using KMPShip.

What is Snappit?

Snappit solves a simple problem: we forget most of our lives.
Think about it. What did you do three Tuesdays ago? What about six months ago? Most of us can't remember. Our memories fade, and the moments that made up our days disappear.
Traditional solutions don't work:
  • Journaling takes too much time and discipline
  • Photo albums require curation and organization
  • Video content creation is overwhelming and performative
Snappit takes a different approach: just 5 seconds a day.
No pressure for perfection. No editing. No audience. Just a quick capture of your day that gets automatically compiled into:
  • Weekly montages (~35 seconds)
  • Monthly compilations (~2.5 minutes)
  • Yearly recaps (~30 minutes)
The result? A personal documentary of your life, created with almost zero effort.

Snappit at a glance

  • 5-second daily videos - Quick, pressure-free recording
  • Automatic montages - Weekly, monthly, and yearly compilations
  • Streak tracking - Stay motivated with gamification
  • 27 collectible badges - Rewards for consistent recording
  • 100% private - All videos stored locally on device
  • Cross-platform - Same experience on Android and iOS

Why I chose to build Snappit with KMPShip

As the creator of KMPShip, I could have built Snappit with any technology. Native Android and iOS. Flutter. React Native. But I chose Kotlin Multiplatform for the same reasons I recommend it to others:

1. One codebase, two platforms, native performance

Snappit processes video. It records from the camera. It generates montages. These aren't simple API calls - they're performance-intensive operations that need to feel native.
With KMP, I write the business logic once and get truly native performance on both platforms. The camera integration uses CameraX on Android and AVFoundation on iOS. The result feels native because it is native.

2. Real code sharing that actually works

When people ask "how much code can you actually share with KMP?", I point them to Snappit. Here's the reality:
LayerCode Sharing
Business logic100% shared
ViewModels100% shared
Navigation100% shared
Database100% shared
Networking100% shared
UI (Compose)95%+ shared
Platform featuresPlatform-specific implementations behind shared interfaces
The only platform-specific code is where it needs to be: camera recording, file system access, and platform APIs. Everything else is shared.

3. KMPShip gave me a massive head start

Instead of spending weeks setting up:
  • Project structure and build configuration
  • Dependency injection with Koin
  • Navigation with Voyager
  • HTTP client with Ktor
  • Database with Room
  • Push notifications
  • In-app subscriptions with RevenueCat
  • Analytics integration
  • CI/CD pipelines
I started with all of this already configured and working. KMPShip's Scale tier gave me the foundation. I just added the Snappit-specific features.

The KMPShip features powering Snappit

Let me show you exactly which KMPShip features Snappit uses in production.

Clean architecture that scales

Snappit follows the Full Clean Architecture pattern from KMPShip's Scale tier. The codebase is organized into clear layers:
snappit/
├── shared/
│   ├── core/          # DI, design system, analytics
│   ├── data/          # Repositories, Room DB, data sources
│   ├── domain/        # Entities, use cases, interfaces
│   ├── presentation/  # ViewModels, Compose UI, screens
│   └── gamification/  # Badge and rewards system
├── androidApp/        # Android-specific code
└── iosApp/            # iOS-specific code
This separation isn't academic. It made adding features fast and refactoring safe. When I added the gamification system, I created a new module without touching existing code. When I rewrote the montage generation logic, the UI didn't change.

Dependency injection with Koin

Every screen in Snappit uses dependency injection. ViewModels get their dependencies automatically. Services are injected where needed. Testing is straightforward because everything is mockable.
kotlin
// From Snappit's MainScreen val viewModel = koinViewModel<MainViewModel>() val alarmeeService: MobileAlarmeeService = koinInject()
KMPShip's Koin setup handles the cross-platform complexity. Android and iOS get platform-specific implementations injected through the same interface.

Navigation with Voyager

Snappit has multiple navigation patterns:
  • Tab-based navigation for the main app (Home, Record, Timeline, Settings)
  • Stack navigation for flows like onboarding and paywall
  • Modal navigation for video playback and settings sheets
All of this works identically on both platforms because the navigation logic is shared:
kotlin
// Tab navigation in Snappit TabNavigator( tab = HomeTab, tabDisposable = { TabDisposable(it, tabs) } ) { tabNavigator -> Scaffold( bottomBar = { NavigationBar { tabs.forEach { tab -> NavigationBarItem( selected = tabNavigator.current == tab, onClick = { tabNavigator.current = tab }, icon = { Icon(tab.options.icon) }, label = { Text(tab.options.title) } ) } } } ) { paddingValues -> CurrentTab() } }

Room database for offline-first architecture

Every video clip in Snappit is stored in a local Room database. Montages, streaks, badges, user progress - all persisted locally. The app works completely offline.
Snappit's database schema includes 8 tables:
  • RoomClipModel - Video clips with metadata
  • RoomMontageModel - Generated montages
  • RoomStreakCacheModel - Streak calculations
  • RoomBadgeModel - Unlocked badges
  • RoomMemoryCardModel - Memory cards
  • RoomUserProgressModel - User progress tracking
  • RoomPointsTransactionModel - Reward points
  • RoomCosmeticModel - User customizations
KMPShip's Room setup handles all the cross-platform configuration. I just defined my entities and DAOs.

RevenueCat for subscriptions

Snappit offers a freemium model with Snappit Pro subscriptions. The payment integration uses RevenueCat, exactly as configured in KMPShip's Scale tier:
kotlin
// From Snappit's RevenueCatDataSource suspend fun purchaseProduct(productId: String): Result<Unit> suspend fun isUserSubscribed(): Boolean fun isUserSubscribedAsFlow(): Flow<Boolean>
The same code handles:
  • Weekly subscriptions ($2.99)
  • Yearly subscriptions ($24.99)
  • Free trials (7 days)
  • Purchase restoration
On Android, it uses Google Play Billing. On iOS, it uses StoreKit. But my code doesn't care - RevenueCat abstracts it all.

Push notifications with Alarmee

Snappit sends daily reminders to help users maintain their recording streak. The notification system uses the Alarmee library, configured through KMPShip:
kotlin
// Daily reminder scheduling in Snappit alarmeeService.local.schedule( alarmee = Alarmee( uuid = RECORD_CLIP_REMINDER_ALARM_ID, notificationTitle = title, notificationBody = body, scheduledDateTime = clipReminderAlarm, repeatInterval = RepeatInterval.Daily, androidNotificationConfiguration = AndroidNotificationConfiguration( channelId = DAILY_RECORD_CLIP_NOTIFICATION_CHANNEL_ID ), iosNotificationConfiguration = IosNotificationConfiguration(), ) )
One API. Two platforms. Notifications just work.

Analytics for data-driven decisions

Understanding user behavior is critical. Snappit integrates multiple analytics providers:
  • Mixpanel for event tracking
  • AppsFlyer for attribution
  • Firebase Analytics for general analytics
  • Sentry for crash reporting
All through a unified analytics interface:
kotlin
// Event tracking in Snappit analyticsTracker.trackEvent(AnalyticsEvent.SnappitRecorded) analyticsTracker.trackEvent(AnalyticsEvent.MontageGenerated(type = montageType)) analyticsTracker.trackEvent(AnalyticsEvent.BadgeUnlocked(badgeId = badge.id))

Firebase authentication

Users can sign in to sync their preferences and subscription status. The authentication flow uses Firebase Auth, integrated through KMPShip's authentication setup:
kotlin
// Auth state management in Snappit val isUserAuthenticated = IsUserAuthenticatedUseCase() val setAuthProvider = SetUserAuthProviderUseCase()

Beyond KMPShip: Snappit-specific features

While KMPShip provided the foundation, Snappit has features that go beyond the boilerplate.

Video recording and processing

The core feature - recording 5-second clips - required platform-specific implementations:
  • Android: CameraX with Camera2 for video capture
  • iOS: AVFoundation with AVCaptureSession
But the recording logic, state management, and UI are shared. The platform-specific code is wrapped behind a common interface.

Montage generation

Snappit automatically compiles daily clips into montages. This involves:
  • Reading video files from storage
  • Concatenating videos in chronological order
  • Adding date overlays to each clip
  • Generating thumbnails for previews
  • Saving the final montage

Gamification system

To encourage consistent recording, Snappit includes a full gamification system:
  • 27 collectible badges across 4 categories
  • Streak tracking with current and longest streak
  • Reward points for various actions
This entire system lives in a separate module, demonstrating how KMPShip's modular architecture enables feature isolation.

The results: what shipping with KMPShip looks like

Development timeline

Using KMPShip's Scale tier as the foundation, I went from idea to App Store submission in weeks, not months. The time savings were real:
FeatureWithout KMPShipWith KMPShip
Project setup2-3 daysAlready done
Navigation3-5 daysAlready done
Database setup2-3 daysAlready done
Subscriptions1-2 weeksAlready done
Push notifications3-5 daysAlready done
CI/CD pipeline1-2 weeksAlready done
Total saved4-6 weeks-
Those weeks went into building actual features: video recording, montage generation, and the gamification system.

Code sharing metrics

Real numbers from Snappit's codebase:
  • 95%+ code shared between Android and iOS
  • 8 shared database tables with identical schemas
  • 27 shared ViewModels powering the app
  • 1 codebase to maintain instead of 2

App quality

Both the Android and iOS versions feel native because they are native. The camera opens instantly. Recording is smooth. Montages play back seamlessly. Users don't know (or care) that it's a cross-platform app.
The App Store listing shows the quality: rated 4.8 stars by users who appreciate the simple, polished experience.

Lessons learned building Snappit

1. Start with Scale tier if you're building a real product

I used KMPShip's Scale tier because Snappit needed authentication, payments, and a local database from day one. If I'd started with MVP tier, I would have upgraded anyway.
If you know you're building a revenue-generating app, start with Scale. The time you save on infrastructure goes into building features.

2. The architecture matters more than you think

Snappit has grown significantly since launch. New features like the gamification system, memory cards, and cosmetics were easy to add because the architecture supported it.
Clean architecture isn't overhead. It's an investment that pays off the moment you need to change something.

3. Platform-specific code is fine when needed

KMP doesn't mean zero platform-specific code. Snappit's camera implementation is entirely platform-specific. That's the right choice for performance-critical features.
The goal is sharing what makes sense to share: business logic, ViewModels, navigation, and UI. Let the platform do what it does best.

4. RevenueCat is worth every penny

Handling in-app purchases manually is a nightmare. RevenueCat abstracts the complexity of Google Play Billing and StoreKit. The integration in KMPShip just works.
For subscription apps, this alone saves weeks of development time.

Try Snappit yourself

The best way to see what's possible with KMPShip is to use an app built with it.
Download Snappit and start capturing your life, 5 seconds at a time:
Notice how native it feels. The smooth animations. The responsive UI. The fast camera. That's Kotlin Multiplatform in production.

Build your own app with KMPShip

Snappit proves that KMPShip isn't just a boilerplate - it's a production-ready foundation for real apps.
Whether you're building:
  • A video app like Snappit
  • A social app with feeds and notifications
  • A subscription-based service
  • A productivity tool
  • An e-commerce experience
KMPShip gives you the same foundation I used. The same architecture. The same integrations. The same time savings.
Start building today:

Frequently asked questions

How long did it take to build Snappit?

From first commit to App Store submission: a few weeks. The video recording and montage generation took the most time. Everything else - navigation, database, payments, notifications - was already done by KMPShip.

Is Snappit's code available?

Snappit is a commercial product, so the source code isn't public. However, KMPShip customers get access to a codebase that follows the same patterns and architecture.

What tier of KMPShip would I need for an app like Snappit?

Scale tier. Snappit uses authentication, payments, local database, analytics, and remote config - all features in the Scale tier.

Can I build a video app with KMPShip?

Yes, but you'll need to implement platform-specific video recording and processing. KMPShip provides the architecture and infrastructure. The media handling is custom.

Does KMPShip include video processing libraries?

Not directly. Snappit uses custom video processing (KlipKit) built specifically for its needs. KMPShip focuses on app infrastructure, not specialized media processing.

Continue your KMPShip journey

Ready to build your own app?