Inspiration
One-to-one tutoring is one of the strongest effects in education research — extra months of progress, large lifts on tests. Almost nobody can afford it. Meanwhile ChatGPT made the old homework-help businesses look like they were selling answers at a markup. Chegg didn’t lose to a better study app. It lost to a free chatbot that would just tell you.
That’s the trap we didn’t want to walk into. Students already have an answer machine in their pocket. What they don’t have is a tutor who remembers last Tuesday, refuses to do the thinking for them, and costs like an app instead of a private teacher.
We started with university students and exam candidates on purpose. They’re paying with real stakes — a GATE rank, a SAT date, a placement interview — and they already know ChatGPT will give them the solution. The product question was: can you build something they still open the next day, after the answer is no longer the point?
What it does
Flocus is a one-to-one AI tutor that guides rather than answers.
In a study session it escalates on purpose: a hint, then a concrete nudge, and only the full worked solution when the student explicitly spends for it. After anything non-trivial it asks them to explain it back in their own words and grades that honestly — partial and off are normal outcomes. Mastery only really moves on a verified teach-back. The model proposes a verdict; the size of the reward is decided in code, and negative signal is never capped.
What a general chatbot structurally cannot do is remember you between sessions. Flocus keeps a durable learner model: per-topic mastery with decay, misconceptions logged in the student’s own words (“drops the sign when distributing a negative”), a booked next appointment, and a periodically re-summarised profile of how they learn.
Around that sit the things that make it a study app rather than a chat window:
- Photograph a problem (handwritten, printed, textbook) — same guided approach, from the actual page
- Three session modes: study, mock interview with a rubric-style close, and spaced-repetition recall
- Prebuilt lessons for GATE CS, CAT, SAT and IELTS, with read-aloud narration, tappable glossary terms, quizzes, and curated video where it exists
- A syllabus-aware plan spread to the student’s real exam date, across 86 university course archetypes and 30 exam tracks
- A streak that counts showing up — a session, a finished lesson, or a cleared recall deck
- Offline: streak, XP, courses, mastery and already-read lessons live on the device; recall works with no connection; only generating something new needs signal
- Nine languages, including Arabic with a real right-to-left layout, not a bolted-on translation
- On-device voice (speech in, speech out) so talking to the tutor doesn’t add a server voice bill
Free tier: daily AI caps, a Home banner, and rewarded ads only when the student hits a real limit (out of hearts, out of today’s lessons) and chooses to watch. We never interrupt a session in progress. Pro is a RevenueCat subscription — weekly, monthly, yearly — with billing copy pulled from the store so we don’t advertise a trial we don’t have.
Live on Google Play: com.flocus.app.
How we built it
Client: React Native + Expo SDK 54, Expo Router, a single design-token file (one orange accent, paper canvas, Instrument Sans / Instrument Serif). Logical style props (marginStart / paddingEnd) so Arabic RTL mirrors automatically; directional icons flip in one place.
Backend: a stateless Express + TypeScript tool-calling orchestrator on Google Cloud Run (Fly.io as live fallback). The client sends the full transcript each turn; the server returns a reply plus tool calls; the client applies them to Firestore. Auth is Clerk. Data is Firestore — no ORM, schema in TypeScript.
AI: provider-agnostic LlmProvider interface; production is Vertex AI Gemini via Application Default Credentials (no API key in the deploy). Free vs paid get different models. Photo turns use the same tiered vision path. Anthropic, OpenAI, Groq stay behind the same interface.
The pedagogy is software, not a prompt. Tools like request_teach_back, grade_teach_back, log_misconception, update_mastery and schedule_next_appointment run in the same turn as the reply. Teach-back deltas (solid / partial / off) are a code table. Unverified positive mastery is capped; struggle isn’t. Recall scheduling is SM-2-lite on those deltas.
Monetization: RevenueCat for subscriptions and entitlements; AdMob served through RevenueCat Ads (Purchases.adTracker) so ad revenue sits next to subscription revenue, broken down by placement. Every LLM call emits a structured log to Cloud Logging → BigQuery (cost, latency, errors, margin per tier) — no prompts or student content ever logged.
Growth plumbing: OneSignal for retention (study-hour and onboarding journeys), Layers for attribution, on-device widgets for the streak.
Challenges we ran into
The model wants to be nice. Left alone, an LLM inflates “you got it” and writes a big mastery bump. We had to take the numbers away from it. The tutor may only emit a verdict enum; code owns the delta. That fight — sycophancy vs honest pedagogy — is the product.
Firestore offline writes don’t fail, they wait. A failed read looked like a new sign-up. The app loaded blank defaults, then saved them back over the real account when the network returned. Mastery, history, misconceptions, goals and XP could disappear. Opening Flocus on a plane could wipe you. Distinguishing “no documents yet” from “couldn’t read” — and refusing to persist empty defaults — was a data-integrity problem dressed up as an offline feature.
Photo questions existed end-to-end with no vision provider. Every image turn returned 503. The UI was honest; the backend wasn’t.
Grounded web search on every tutor turn. Harmless under the old provider; on Vertex it billed ~$0.014 per request, several times the cost of the turn it decorated. It’s now opt-in (“Find resources”) with a per-user daily cap.
Maths without LaTeX. We have no formula renderer. $\\frac{dy}{dx}$ reached students as text and was read aloud as “dollar backslash frac…”. A separate bug collapsed H₂SO₄ and H₂SO₃ to the same glossary key. Prompts now pin plain Unicode; the matcher keeps non-ASCII.
Ads in a study app. We shipped an interstitial on recall-deck completion — monetising the most frequent win and giving nothing back. We ripped it out. Rule now: never monetise a completion, only a limit the student chose to trade 30 seconds for.
Honest billing. We advertised a 14-day trial without checking whether one existed, and compared plans on limits we never enforced. Trial and price copy now come from the store. If it isn’t real, it isn’t on the paywall.
Accomplishments that we're proud of
- Shipped. First public release on Google Play during the Shipaton window, then 1.1.0 — the first release that actually asks for money, and the one that made what we already charged for honest.
- A tutor that can refuse. Hint → nudge → paid solution, plus a teach-back loop the model cannot grade-inflate. That’s the whole bet.
- A learner model that survives the session. Not a chat log. Mastery, misconceptions, the next appointment, a profile of how you learn.
- Reward-only ads, attributed. Ad revenue and subscriptions in one RevenueCat chart, by placement — so we can actually ask whether a free user is worth more watching an ad or hitting the paywall. We chose never to show an ad a student didn’t ask to see.
- Arabic done properly. Full RTL, Noto Sans Arabic, layout that mirrors. Unusual for a first-ship consumer app, and we built it as a first-class locale, not a checkbox.
- Prebuilt, syllabus-grounded lessons for GATE CS, CAT, SAT and IELTS — College Board domains, ielts.org criteria, IIT Madras’s GATE 2027 CS PDF — so the free tier isn’t “generate one and hope.”
- The app still is your account on a bad network. Offline recall, local cache, and a hard stop on the wipe bug.
- Telemetry without surveillance. Cost and latency we can actually operate on; a test that fails if student text leaks into logs.
- A design system with a ceiling. One accent, hairline borders, a custom Journey path, karaoke word-highlighting in lessons — not a generic chat UI with a mascot stuck on top.
What we learned
Don’t let the model hold the ledger. If mastery, hearts, or money depend on a number, that number lives in code. Prompts are for voice and pedagogy; they are not a source of truth.
“Works offline” is a consistency problem. Sync APIs that queue writes will happily publish your empty state. Treat a failed read as unknown, never as empty.
The competitor is free ChatGPT, not another study app. You don’t win on answer quality in a price war with a foundation model. You win on memory, honesty, a plan that matches a real syllabus, and the boring retention layer (streaks, recall, a next appointment).
Interruptive ads in a focus product are a one-star review waiting to happen. Rewarded ads at a limit are a trade the student understands. Interstitials at a completion are a tax on using the app well.
Copy is a contract. If the store has no trial, the app must not say it does. If a quota isn’t enforced, it doesn’t belong on the plan comparison. Students notice, and so do stores.
Curation beats generation for exams. A new syllabus every session is a demo. A GATE CS topic list that matches the official PDF is a product you can advertise without lying.
Ship the unglamorous bugs. Dark-mode chrome, composer under the Android nav bar, an unscrollable paywall, night-time duplicate notifications — those are what make an app feel unfinished to a judge with five minutes.
What's next for Flocus
- iOS. Android is live; App Store review is the remaining door. Same app, same RevenueCat products.
- Deeper beachheads, not more exams. Fill GATE CS / CAT / SAT / IELTS / GAT so every advertised topic has a real lesson and a ranked resource pack (YouTube embed + official reading). Personalisation stays on order, diagnostic skips, language and misconceptions — not on inventing the syllabus at runtime.
- Retrieval, carefully. Today there is no RAG. The ambition is a course that pulls in real papers, videos and notes as untrusted reference, with sanitised context — not concatenated into the system prompt. Firestore vector search first; a dedicated vector DB only if query patterns outgrow it.
- Shared quota state, then async generation. Rate limits and free-tier counters still need to be correct across Cloud Run instances. Once course generation takes minutes, it becomes a job with a push when it’s done — the app already has that notification path.
- India and Egypt pricing that matches willingness to pay, Crashlytics on the client, and an eval loop on the tutor traces we already store.
- Keep the ads philosophy. If we add a placement, it will be another rewarded unlock at a limit — never an interstitial mid-lesson.
The north star doesn’t change: a tutor you can afford, that remembers you, and that makes you do the thinking.
Built With
- gcp
- gemini
- python
- react
- react-native
- revenue-cat

Log in or sign up for Devpost to join the conversation.