Inspiration

I kept failing at journaling. A blank page at the end of the day is too much work. But I could always answer one question: what did I have on repeat today? Songs are bookmarks for memories. So I built nokki around that idea: one song a day becomes a diary entry.

What it does

  • Log a day in about 30 seconds. Pick the song, tap one of nine pastel moods, and add a line if you want to.
  • A stamp-book calendar. Each entry leaves a hand-drawn stamp, so a whole month fits in one glance.
  • A black cat reads your month back to you. An AI reflection (Gemini) reads only your own entries and writes a gentle look back at your month or year.
  • Night Notes. A page nobody else ever sees.
  • Friends, not followers. There's no public feed and no follower count. You connect by QR code and both sides approve. Every entry is either for friends or just for you.
  • Songs you can hear. iOS uses Apple Music (previews, or full playback for subscribers) and Android uses the iTunes catalog.
  • Avatars, watercolor headers, streaks, stats and achievements. Report, block and account deletion are built in.

How I built it

  • iOS: SwiftUI with an MVVM + UseCase architecture, MusicKit, Sign in with Apple and Google, CoreMotion for the jewel-case gloss, and CoreImage for the share QR code.
  • Android: Kotlin and Jetpack Compose. The avatar library (humation) only existed in Swift, so I ported its renderer to Compose.
  • Firebase runs the backend: Firestore with tested Security Rules, Cloud Functions, Storage and Remote Config. Firebase AI Logic on the Vertex AI backend powers the reflections, and I can switch models without an app update.
  • RevenueCat handles nokki+ on both platforms: one plus entitlement, a default offering with monthly and annual packages, and the Firebase uid as the app user ID so a subscription follows the account across devices. The paywall is custom but reads RevenueCat offerings.

Challenges I ran into

  • Changing what the app was. nokki started as a music SNS with communities, DMs and public accounts. Halfway through, I realised the part I cared about was the private diary. So I removed communities, DMs and one-way follows, and turned five tabs into one diary-like home.
  • App Review couldn't see the social side. My first submission was rejected under Guideline 2.1(a) because friends need mutual approval, so a reviewer with one account saw an empty feed. I built a "guide" account whose friend requests a Cloud Function auto-approves, seeded sample entries, and put its QR code in the review notes.
  • Green tests, broken production. The account-deletion function passed its unit and E2E tests but failed in production because of a missing collection-group index and a wrong query. I made every step independent so the account itself always gets deleted.
  • A crash on notification tap in 1.0.1 came from an async notification delegate that called back off the main thread. The fix shipped in 1.0.2.

What I learned

Something only counts as working once it works where users are. Every one of those bugs showed up only in production or in review. I also learned that removing features can be the biggest design decision. nokki got better every time it got smaller.

What's next

English localization is the obvious next step, since nokki is Japanese-only today. After that: more stamps and header art, and more ways to look back at a year of songs, all while keeping the app small and quiet.

Built With

  • cloud-firestore
  • cloud-functions
  • coremotion
  • firebase
  • firebase-ai-logic
  • firebase-crashlytics
  • firebase-remote-config
  • gemini
  • google-play-billing
  • google-sign-in
  • jetpack-compose
  • kotlin
  • musickit
  • revenuecat
  • sign-in-with-apple
  • storekit
  • swift
  • swiftui
  • vertex-ai
Share this project:

Updates

Submission history