Case study · Tadabbur Shipped

Built for named readers, measured against named outcomes

Two readers defined before the first screen, a curriculum sequenced by word frequency rather than by chapter order, and a set of targets written down before any code existed.

StackFlutter · Dart · Supabase · Riverpod
RoleSole designer and developer, built with Claude Code
Tests17 test files across 55 source files
Commits106
Contents · 11 sections
Overview

A curriculum that starts from what the reader already recites

Tadabbur is a Quranic Arabic learning app. The goal is narrow and stated plainly in its product document: help someone read an unfamiliar page of the Quran and understand its meaning and grammar, through daily practice that takes less time than a single prayer.

It ships as a Progressive Web App built in Flutter, on a Supabase backend — Postgres, Auth, Storage and Edge Functions, with 49 migrations and one edge function serving the review scheduler. The curriculum, the lesson player, an SM-2 spaced-repetition engine and on-device prayer-time calculation are live. The AI tutor and pronunciation scoring are not built.

Problem

Every general-purpose language app teaches the wrong thing first

The people who most want to understand the Quran already recite it. They have the sounds and none of the meaning. A conventional language curriculum starts from greetings and everyday nouns — vocabulary that will not appear in the text they actually read.

The constraint that made this hard: the curriculum had to be sequenced by frequency in the source text, not by pedagogical convention, and it had to be a content set one person could produce and quality-check alone.

Who it is for

Two readers, named before the first screen.

Persona 01Aisha, the new Muslim
What they needScript literacy from zero, and an emotional win inside the first three minutes.
What that ruled outAny onboarding that front-loads grammar theory. High motivation, easily overwhelmed — the path has to give a result before it asks for patience.
Persona 02Omar, the practising professional
What they needA curriculum that starts from what he already recites five times a day — Al-Fatiha and the short surahs — in sessions of five to ten minutes.
What that ruled outGeneric vocabulary lists. He recites fluently from memory and understands none of it; teaching him “hello” and “thank you” would waste the one thing he already has.
These two sit at opposite ends of a script-literacy × comprehension matrix. They were chosen because they are the hardest test of the placement engine — route both correctly and the heritage learner and the academic follow without new engineering, only new content.
My role

Sole designer and developer

Product document, curriculum sequencing, database schema, interface, Flutter architecture, tests, CI and deployment. 106 commits between 4 and 29 August 2026.

Approach

Write the product document first, then build against it

The product requirements document was written before any code: vision, two personas, success metrics with numeric targets, fourteen in-scope items and six explicitly out of scope. Nine further documents cover the schema, API design, Flutter architecture, information architecture, design system and testing strategy.

Key decisions and trade-offs

01

Supabase over Firebase, because the data is relational

The curriculum tree, the many-to-many mapping between words and verses, and the spaced-repetition query patterns are all deeply relational. Firestore would have forced denormalisation that fights that shape at every read.

What it costOffline-first sync is built into Firebase and is not built into Supabase. Choosing Postgres meant designing an outbox-queue pattern by hand and carrying that complexity in every write path.
What it boughtThe schema stays normalised SQL with no translation layer, and the query patterns the product depends on are the ones the database is good at.
02

Ships to the home screen, not to the app stores

Distribution is a website added to the home screen, with per-platform install instructions built into the app itself.

What it costNo store discovery, and on iOS, standalone mode only from Safari.
What it boughtNo review cycle, no $99-a-year developer account, and one release process instead of three. Every push to main builds and publishes; the running build number is visible in Settings and matches the deploy run, so “is my phone on the latest?” is a five-second check rather than a guess.
03

Free, with hard per-user AI cost caps instead of a paywall

The product document rules out monetisation entirely for v1. That is a cost decision as much as an ethical one: with no revenue to offset marginal AI spend, the control has to be usage caps rather than a payment wall.

What it costNo revenue, and a ceiling on how much AI any one person can use.
What it boughtPayment, entitlement and subscription-state engineering left the scope completely — a whole subsystem a solo builder never has to write, test or support.
Scope

In and out

In scope Curriculum path from the alphabet through vocabulary, grammar and short surahs; a lesson player covering vocab cards, reading passages, letter drills, grammar explanations and recall quizzes; an SM-2 review queue; on-device prayer times. Built
Out of scope, for now AI tutor, pronunciation scoring, gamification and push notifications. Specified in the product document, sequenced in the implementation plan, not yet built. Rule-level Tajweed scoring and leaderboards. Deferred by the product document to after the MVP, not yet built. Planned

Success metrics

Targets set before the build, from the product document. Not measured against usage.
MetricTarget
Comprehension mastery Majority of intermediate-course completers
D1 retention Above 40%
D7 retention Above 30%
Habit loop health Tracked, no target
How it ships

Three checks, then the deploy

Every push to main runs flutter analyze, the full test suite, and a set of deployability checks before anything reaches the live site. CI and deploy are separate workflows, both with public status badges on the repository README.

GateWhat it blocks
flutter analyze Static analysis failures reaching a build
Full test suite 17 test files across 55 source files
Deployability checks A build that compiles but cannot actually be served
Deploy to Pages Runs only after all three pass

Updates are never applied mid-session — a deploy cannot reload a user out of a lesson. It waits until they ask, or until the next launch.

What shipped

Learn, Review and Prayer Times, live

  • A Flutter PWA on Supabase — Postgres, Auth, Storage, Edge Functions — with 49 migrations and an edge function serving the review scheduler.
  • Learn, Review and Prayer Times live. Prayer times are computed on the device with no network call.
  • Roughly 4 MB cached on first run so the app works offline, with the rest of the rendering engine fetched in the background.
6 screens · scroll
The Learn screen: the curriculum path with a unit carousel, a one-day streak, and Al-Fatiha marked complete
Learn — the curriculum path
Tadabbur lesson player: a reading passage from Al-Fatiha in full Tashkeel with ayah markers, transliteration and translation
Lesson player — reading passage, full Tashkeel
A vocabulary card in the lesson player: an Arabic word with its meaning, its triliteral root and its morphological pattern
Lesson player — vocabulary card
A letter card in the lesson player: one Arabic letter with its name, a pronunciation hint, and its initial, medial and final forms
Lesson player — letter drill
A recall quiz in the lesson player: an Arabic word in the question stem with four answer options
Lesson player — recall quiz
The prayer times screen: a timeline of the day's prayers in Arabic with a now marker between two of them, calculated on the device
Prayer times — computed on device
What I would do differently

Build the thing the product is named after, first

Tadabbur is described as AI-first, and the AI tutor is one of four features sequenced in the plan and not yet built, with pronunciation scoring, gamification and push notifications. The core — curriculum, lesson player, review scheduler, prayer times — shipped in twenty-six days. The differentiator sat behind it in the plan and is still waiting. If I ran it again I would build the thing that makes the product different first, and let the conventional parts follow, because the conventional parts turned out to be the ones I could finish quickly.

This is how I make decisions at work too

Open to new roles — Toronto, hybrid, remote, or relocating.