Inspiration

Last year I entered Shipaton with a YouTube note-taking app. It lost, and looking back it didn't deserve to win. It was a features list, not a product. The one idea worth keeping was underneath the features the whole time: spaced repetition works because it tells you exactly when you're about to forget something. Nothing in that app ever showed you that number. This year the number is the whole interface.

What it does

Phosphor turns a typed topic, a YouTube lecture link, or pasted notes into FSRS-scheduled flashcards. Every card carries a measured retention percentage, and the card's glow on screen is that number: strong memories glow, weak ones dim toward black. A card's forgetting moment is computed in closed form from the FSRS-6 curve (not just its due date, which is rounded and fuzzed by design) and a push notification fires at that instant, carrying the card's own question and all four grading buttons. Grading from the lock screen applies before the app even opens. Outline mode asks you to predict answers before you read, source panels quote the exact transcript line behind every card so nothing is invented, and Library tracks which cards are sliding below a healthy retention threshold in real time.

How we built it

Flutter/Dart on Firebase (Auth, Firestore, Cloud Functions, Storage, Messaging, Crashlytics), RevenueCat for entitlements, and OneSignal for the forgetting-moment push. The FSRS-6 inversion that finds the exact crossing instant is closed-form math, not a search. The shipped fsrs package only exposes retrievability at whole-day resolution, which is too coarse for a push that has to land at a specific hour. A Cloud Function holds the OneSignal send key, computes the instant on every review, and replaces the scheduled push via send_after + external_id. Pricing is a 90-day non-renewing Exam Cycle pass priced below three months of the monthly plan, alongside ordinary monthly/annual subscriptions.

Challenges we ran into

Two are worth naming honestly. First, I nearly withdrew from this contest: an older Android app under the same idea had shipped last year, and I initially read the rules as disqualifying this iOS rebuild. I asked the organizers directly instead of trusting my own reading, and got a binding ruling that a new name, new design, new core functionality and a first release inside the window is eligible. Second, months went by with zero builds ever reaching App Store Connect, and I quietly read that as "the app isn't ready yet." It was one line in the Xcode project: the Release configuration was pinned to a development signing identity, so every export silently could not produce a distributable binary. Deleting that one line was the fix.

Accomplishments that we're proud of

The forgetting-moment push is the feature I'd point a judge at first: it is not a generic reminder, it is the one instant this specific learner's memory of this specific card crosses a retention target, computed rather than guessed. Getting the free tier's cost structure right matters too: free requests route to a cheaper model than paid ones, so the generous free tier is a real cost moat rather than a growth hack that loses money at scale.

What we learned

That a tooling failure and a product failure can look identical from the outside, and that the only way to tell them apart is to actually go looking rather than assume the worse explanation. Also: an untested claim is not a passing one. Screenshots and a store description sound like marketing chores, but building them surfaced a real bug (a database key leaking into a title a user would see) that four months of code review never caught.

What's next for Phosphor

Ship 1.0.7 (or the next build after it) and get the App Preview video attached in App Store Connect. Activate the Lapsed Learner OneSignal journey. Generate a working promo code so judges and reviewers can reach Pro without a purchase. Then the #BuildInPublic posts that are already written and simply not yet posted.

Built With

  • cloud-firestore
  • cloud-functions
  • dart
  • firebase-auth
  • firebase-cloud-messaging
  • firebase-crashlytics
  • firebase-storage
  • flutter
  • flutter-bloc
  • flutter-quill
  • freezed
  • fsrs
  • go-router
  • image-picker
  • injectable
  • intl
  • onesignal
  • pdf
  • receive-sharing-intent
  • revenuecat-(purchases-flutter)
  • share-plus
  • sqflite
  • webview-flutter
  • youtube-explode-dart
  • youtube-player-flutter
Share this project:

Updates

Submission history