Inspiration

I'm a computer engineering student in Ankara, and I have the same problem every student has: the studying isn't hard, starting is. Every Pomodoro app I tried solved the timer and ignored that. A countdown on a white screen doesn't make you want to sit down.

What it does

FlowState puts focus sessions inside a clock tower. You begin, the gears turn, and the room tells you there's nothing beyond it. Underneath the atmosphere it does real work:

  • AI study assistant: Claude or Kimi K2, available mid-session. Explains a difficult idea, sets practice problems, or works through a stuck point.
  • Notes into study units: upload a PDF or photograph a page, get back extracted concepts, a quiz, and a flashcard deck.
  • Focus audio and streaks: noise variants for concentration, a session record and streak calendar for consistency.

How I built it

Flutter and Dart on the client, Riverpod for state. Firebase for auth, Firestore, and Cloud Functions. RevenueCat for monetisation. OneSignal for re-engagement.

Monetisation is deliberately mixed: subscriptions for the AI tiers, plus consumable credits for study-unit generation that never expire. Free users get one generation a day and a second through a rewarded ad, so the paywall converts from experience rather than from a locked door.

The AI calls run server-side in Cloud Functions rather than from the client. That decision cost me a rewrite mid-project, but it keeps the API keys out of the APK and lets me change prompts without shipping a release.

Challenges

Large PDFs froze the app. Parsing ran on the main isolate, so a big lecture PDF produced an ANR. I found it reading logcat on a cable. Moving extraction into a background isolate fixed it — my first real lesson in Flutter's threading model.

Google's testing requirement. As a new personal developer account, I had to run a closed test with 12 testers opted in for 14 continuous days before I could even apply for production access. Recruiting real testers, keeping them engaged, and shipping four iterations across that window was harder than any of the code.

Prompt drift. When I moved generation server-side I left the client path behind a flag. The two prompts silently diverged, and a comment in my own code claimed they were in sync. I only found it by auditing the whole codebase afterward.

What I learned

That shipping is a separate skill from building. The app was functional weeks before it was live, the distance was store assets, billing configuration, privacy policy, data safety, and a testing gauntlet nobody warns you about.

Also that criticism is cheap information.

What's next

Turkish localisation, since YKS and KPSS students are my nearest audience. Error monitoring the app is live with no Crashlytics, which I know is the most consequential gap. And smarter notification timing based on when each user actually studies.

Built With

Share this project:

Updates

Submission history