EdTech / Healthcare Mobile App (iOS & Android)

Gamified Medical Terminology Learning App — Duolingo-Inspired, Published on iOS & Android

Designed and built a cross-platform Flutter app that teaches medical terminology through a gamified, spaced-repetition learning system — complete with structured learning paths, quiz modes, a global leaderboard, and a real-time daily review hub. Live on both the App Store and Google Play.

"Built a full-featured medical learning app from scratch — SM-2 spaced repetition, gamified quizzes, global leaderboard, and dual-store launch"
FlutterDartSupabaseiOSAndroidSpacedRepetitionSM-2GooglePlayAppStoreProviderPostgreSQLRLSGamification
Frontend
Flutter 3.x (Dart)Provider (state management)flutter_animateLottieConfettiGoogle Fonts (Lexend, Noto Sans)
Backend
Supabase (PostgreSQL + Auth + Storage)Row Level Security (RLS)PostgreSQL Triggers & ViewsSharedPreferences (local resume)
Infrastructure
Google Play Store (v1.0.5)Apple App Store (iOS published)Supabase Cloud
2 stores
Simultaneous production launch
Published to both Google Play (v1.0.5, Build 8) and Apple App Store from a single Flutter codebase
511 KB
Full production curriculum SQL
All terms, units, topics, and questions managed server-side in Supabase — zero binary coupling
6 hrs → 9 days+
Spaced repetition interval range
SM-2 algorithm dynamically adjusts review intervals per term based on user accuracy
3
Definition levels per term
Layman, Clinical, and Technical definitions — adapting to any learner's background

Problem Statement

Medical terminology is vast, highly technical, and notoriously hard to retain. Existing tools are either passive (PDFs, flashcards) or lack personalized repetition. The challenge was to build a system that combined structured curriculum delivery, active-recall quizzing, and a real SM-2 spaced repetition algorithm — all wrapped in a polished, Duolingo-style mobile experience, shipped to both platforms simultaneously.

Our Approach

Built MedLingo end-to-end in Flutter with Supabase as the backend. Implemented the SM-2 algorithm fully in Dart with server-side persistence (per-term ease factor and interval tracking in PostgreSQL). Designed a scrollable learning path with prerequisite locking, a flashcard system with three progressive definition levels (Layman → Clinical → Technical), a quiz mode with multiple-choice and drag-and-drop questions, and a daily review hub with a live countdown timer and XP goal tracking. All curriculum content lives in Supabase — zero app update required to add new terms.

SM-2 Spaced Repetition Engine (Custom Dart + PostgreSQL)

Technical Details
Implemented the SM-2 spaced repetition algorithm from scratch in Dart, persisted server-side in Supabase. Each term tracks its own ease_factor (clamped 1.3–3.0), interval_days, and mastery_level (0–5). Correct answers extend the review interval multiplicatively; incorrect answers reset the interval to 6 hours and drop the ease factor. A deliberate two-query pattern handles Supabase's join-filter limitation for topic progress: first fetching term IDs, then filtering progress rows — ensuring correctness without workarounds.
Business Value
Users study smarter, not harder — difficult terms resurface frequently while mastered ones recede, maximising retention per session. The decoupled content architecture means curriculum can be updated or expanded by editing Supabase rows, with no Play Store or App Store submission required.

Challenges We Solved

SM-2 Spaced Repetition — Fully Implemented in Dart + Persisted Server-Side

Spaced repetition requires per-term state (ease factor, interval, mastery level) that must survive app restarts, device switches, and offline use — without any on-device dependency or data loss.

Designed a `user_progress` table in Supabase with columns for `ease_factor`, `interval_days`, `mastery_level`, `last_reviewed_at`, and `next_review_at`. The SM-2 logic runs entirely in Dart (progress_service.dart) after each quiz answer, and immediately upserts the updated state to Supabase. Row Level Security ensures users can only read/write their own records.

Dart (SM-2 algorithm)Supabase PostgreSQLRow Level Security (RLS)progress_service.dart

Two-Step Topic Progress Query Pattern

Supabase's PostgREST join-filter behavior made it impossible to correctly filter user_progress by topic in a single query — resulting in incorrect completion percentages on the learning path.

Implemented a deliberate two-query pattern: first fetch all term IDs for a given topic, then query user_progress filtered by that ID list. This ensures accurate term-level completion data without relying on brittle join filters.

Supabase (PostgREST)topic_service.dartPostgreSQL

Auth Trigger Auto-Provisioning (Zero Race Condition)

On sign-up, client-side profile creation created a race condition — the app could try to read the profile before the INSERT committed, causing crashes on the first session.

Replaced client-side profile creation with a PostgreSQL SECURITY DEFINER function triggered by `auth.users` INSERT. The profile row is always created within the same transaction as the auth user, eliminating the race condition entirely.

Supabase AuthPostgreSQL TriggerSECURITY DEFINER function

Leaderboard via PostgreSQL VIEW with ROW_NUMBER()

Computing real-time global rankings across all users by XP (with streak as tiebreaker) is expensive if done client-side, and Supabase doesn't natively support computed rankings.

Created a PostgreSQL VIEW (`leaderboard`) that uses `ROW_NUMBER() OVER (ORDER BY total_xp DESC, current_streak DESC)` to produce a pre-ranked result set. The Flutter app queries this view directly — rankings are always correct and database-computed.

PostgreSQL VIEWROW_NUMBER() window functionSupabaseleaderboard_service.dart

Project Timeline

1

Discovery

Defined the full feature set: structured learning path with prerequisite locking, three-level flashcard system, quiz mode with multiple question types, SM-2 spaced repetition, daily review hub, leaderboard, achievements, and multi-method auth (Email / Google / Apple). Designed the Supabase schema with RLS policies, indexes on all hot foreign keys, and updated_at triggers on all mutable tables.

2

Build

Built all core screens and services end-to-end: scrollable learning path (learning_path_screen), flashcard viewer with progressive definition levels, Clinic Lesson quiz (multiple-choice + term-building question types), Daily Review with live countdown timer and XP tracking, MedDex searchable glossary, global leaderboard with PostgreSQL VIEW, achievements system, and user profile with avatar upload to Supabase Storage. Implemented local lesson resume via SharedPreferences (last-viewed term index saved on every navigation step). Authored bulk content tooling (generate_onboarding_sql.py, json_to_sql.dart) to import the 511 KB production curriculum.

3

Launch

Published to Google Play (v1.0.5, Build 8) and Apple App Store from a single Flutter codebase using flutter_native_splash and flutter_launcher_icons for native assets. Configured local push notifications (flutter_local_notifications + timezone) for streak reminders. App is live on both stores.

Ready to Build Something Similar?

Let's discuss how we can help transform your business with AI.

Start Your Project