Modern Android,
free-tier first.
Wisp is built with Kotlin, Jetpack Compose, MVVM, Hilt, Room, and Firebase — no premium services, no paid SDKs, no compromises on architecture.
Twelve libraries.
Zero compromises.
Every dependency on this list is mature, free, and well-supported. The whole app builds and runs on the Firebase Spark plan.
MVVM, plus a clean
repository seam.
ViewModels expose state, repositories abstract data sources, and the UI is pure Compose. The Imgur + Firestore split is hidden inside MediaRepo and StoryRepo.
Where everything lives.
Repositories carry the weight.
The repository layer is the seam where the cloud meets the cache. StoryRepo, for example, handles Imgur uploads, writes the story document to Firestore, mirrors it to Room, and exposes a single Flow<List<Story>> to the ViewModel.
UI never touches Firestore directly. ViewModels never touch Room directly. This makes testing trivial — you fake the repository and verify the rest in pure Kotlin.
One wisp, end to end.
Follow a single photo from shutter to a friend's screen.
CameraX captures
UseCase pipeline writes a JPEG to a temp file.
Compress to ~200KB
Quality-aware encoder targets a tight size without crushing the dark areas.
POST to Imgur
Anonymous upload with Client-ID header. Returns a public CDN URL.
Write Firestore doc
{userId, imageUrl, createdAt, expiresAt} — and friends see it instantly.
30%+ coverage,
tracked with Kover.
JUnit unit tests cover repositories and viewmodels. Compose UI tests verify navigation and key flows. Kover generates an HTML report on every CI run.
- Repository tests with fake Firestore + in-memory Room
- ViewModel tests verifying state transitions on each user action
- Compose UI tests exercising navigation and chat-send flow
Free-tier engineering.
Wisp ships entirely on free services. The constraints shaped the architecture.
No Firebase Storage
Storage requires the Blaze (paid) plan. Solution: images go to Imgur, URLs are stored in Firestore documents.
50K reads / day
Firestore Spark plan caps. Solution: Room caches everything, listeners stream incrementally.
No paid analytics
No Crashlytics, Mixpanel, or PostHog. Solution: good logging, manual QA, and Kover for confidence.
Build it yourself.
Wisp is open source. Clone the repo, drop in your Firebase config and Imgur Client-ID, and you're running.