FLYER Β· Product PRD Β· Full-product coverage
πŸ‡»πŸ‡³ TiαΊΏng Việt Β· EN English

🎯 IELTS Guru β€” ieltsguru.ai

IELTS Guru is FLYER's AI-first IELTS preparation product: skill-by-skill mock tests with real exam simulation, AI grading for Speaking and Writing at a fraction of the real exam cost, an AI Mentor for chat and voice practice, and a diamond + subscription monetization model. This PRD documents 100% of the shipped product β€” every route, flow, business rule, data entity and known gap β€” from a direct scan of the flyer/webs-ielts codebase plus fresh production-database numbers.

Version
1.0
Date
24/08/2026
Owner
TΓΉng (Product)
Status
Live in production
πŸ“ˆ Production (24/08/2026)207,767 IELTS attempts all-time28,195 learners all-time11,612 attempts / 30d661 active learners / 30dlive since 22/10/2024
πŸ“š Content1,789 parts3,550 questions4 skillscounts from the production read replica, tables ielts_*
πŸ”— Live product linksieltsguru.ai β†—Listening test β†—Reading test β†—Speaking test β†—Writing test β†—Pricing β†—

1Context, positioning & stack

IELTS Guru targets learners preparing for IELTS who want unlimited realistic practice and instant expert-level feedback without paying for the real exam or a private tutor. Positioning line: "AI Mentor for smart IELTS preparation" β€” the product claims AI Speaking/Writing grading at 1/50 the cost of the real exam. It serves three audiences at once: B2C self-study learners (Vietnam), international B2C learners (USD pricing via Polar), and B2B school tenants through white-label custom domains (including a dedicated ACCA tenant at acca.teado.ai).

Goals. (1) Give IELTS learners unlimited exam-realistic practice per skill. (2) Replace expensive human grading with AI band scoring + actionable feedback. (3) Feed the FLYER ecosystem: shared accounts, teacher assignments, school exams, band-tiered subscriptions.

2Users & user stories

RoleUser storyPriority
Self-study learnerTake a full simulation mock test for one skill under real exam conditions (timer, play-once audio, anti-cheat) and get a band score.P0
Self-study learnerGet AI Writing feedback with the official 4-criteria band breakdown, sentence-level corrections and a sample answer.P0
Self-study learnerGet AI Speaking feedback with transcript, per-word pronunciation (IPA, phonemes) and fluency/grammar/vocab scores.P0
Self-study learnerPractice flexibly: pick specific parts, set my own time limit, redo questions, use dictionary/notes while practicing.P0
LearnerTalk to an AI Mentor β€” free-text chat or voice Topic Talk with learning outcomes β€” to practice English conversationally.P0
LearnerTrack my progress: band trend over time, skill radar, accuracy, study time, target band and days until my exam.P1
LearnerReview mistakes: wrong answers with explanations, mispronounced words I can re-record and re-score, a vocabulary book.P1
School studentEnter a proctored multi-skill school exam session assigned by my school, with violations reported to the teacher.P0 (B2B)
Teacher (via teacher.flyer.us)Assign tests as missions with deadlines, hide answers, review and grade student attempts manually.P1
Anonymous visitorBrowse all test libraries and even take tests with an anonymous profile before being asked to sign up.P1 (funnel)

3Information architecture & routes

Single left-sidebar app shell (no footer). Locales: en (default, unprefixed) and /vi. Auth gating is soft: no middleware or server-side gate β€” anonymous visitors get a dismissible "please sign up" toast everywhere except a small exclude list, and the sidebar intercepts clicks on member-only items to open the sign-in modal.

RoutePurposeAccess
/ β†’ /homeDashboard: greeting, "Personal AI Teacher" free-text box (creates AI chat session), skill cards with mock-test/test counts, Speaking Topics entry, upcoming school-exam popup.Public
/librariesMerged material library. Two rows: Study (FLYER-curated IELTS practice) and Quiz (community/partner practice). Tabs All / FLYER / Community / My school; URL-persisted filters (search, skill, band, type, sort).Public
/ielts/{skill} Γ—4Mock-test list per skill (listening, reading, writing, speaking) with topic/type/sort/part filters and infinite scroll.Public
/ielts/{skill}/[id] Γ—4Test detail + player in one route: preview β†’ mode choice β†’ (sound/mic check) β†’ do exam. SSR for SEO meta.Public β†’ gated to start
/ielts/{skill}/result/[id] Γ—4Score screen after submit; polls every 3s while AI grading is pending.Login
/ielts/{skill}/report/[id] Γ—4Detailed report: answer keys + explanations (L/R), criteria feedback V2 (W), transcript + pronunciation (S). Speaking report is deliberately public/shareable.Login (S: public)
/practice/[id] + result/reviewQuiz engine: 13 question types incl. drag-drop, matching, flashcards, interactive video, audio response, AI-evaluated open-ended.Public β†’ login
/test-results/[id]Replay a Listening/Reading attempt in the original exam UI, read-only.Login
/real-time-conversation{,/chat,/chat/[id],/topic,/topic/[id]}AI Mentor hub: streaming text chat and voice Topic Talk with a lip-synced avatar.Login
/missionTeacher-assigned homework: in-progress and completed lists, deadlines, late-submit rules.Login
/mistakes (+ ?currentTabMistakes=notes)Mistake-word pronunciation drill + Vocabulary book (two tabs in one route).Login
/historyAll attempts table (desktop) / cards (mobile) with filters; rows deep-link to the right result/report page.Login
/learning-profileAnalytics dashboard: 6 stat cards, average-band line chart, skill radar chart, target-band modal.Login
/packages Β· /diamonds-previewSubscription pricing Β· diamond top-up.Public
/login /signup /recover /logout /join-class /join-placementest /active-accountAuth pages, class-code join, ACCA placement lead form, activation-code redemption.Mixed
/profiles /create-profile /settings/profiles /settings/themeLearner-profile switcher (up to 20 per account), profile form, appearance (8 accent colors + dark) and language settings.Login
/api/*ping (health), cookies, link-preview, bug-report (β†’ Google Apps Script), imgproxy, polar-link-payment, student-chat/[id] + student-call/[id] (edge SSE proxies), Apple/Android well-known files.β€”

Sidebar nav (desktop sidebar = mobile drawer): Mock tests β†’ /, Study β†’ /libraries, Missions, Mistakes, Vocabulary book, Learning profile, History; bottom block: Teacher role (opens teacher.flyer.us), Notifications popup, diamond counter β†’ /diamonds-preview, avatar popup (Upgrade β†’ /packages, Change interface, Active code, Switch profile, Edit profile, Log out).

4Content model & inventory

All content lives in the universal CheckPoint container shared across FLYER products, with per-skill IELTS part edges. Rendered question formats (MCQ, T/F/NG, matching, headings, form completion…) are all composed from just 3 detail primitives, driven by <blank id> placeholders inside contentHtml:

CheckPoint (test) ── time Β· maxGrade Β· diamond (AI cost) Β· isPremium Β· ieltsBand Β· topics
 β”œβ”€ IeltsListeningPart { audio, audioSubtitle (tapescript), expiredTime, questions[] }
 β”œβ”€ IeltsReadingPart   { contentHtml (passage), expiredTime, questions[] }
 β”œβ”€ IeltsWritingPart   { contentHtml, images[], sampleAnswerHtml, learnFromSampleHtml }
 β”œβ”€ IeltsSpeakingPart  { info{introductionText,audio}, questions[]{ timeToThink, timeToSpeak,
 β”‚                       sampleAnswerHtml, sampleAnswerAudio } }
 └─ Question β†’ details[] { detailType: GAP_FILL | SELECT | OPTION,
                           options[{label,text,correctAnswer}], explainHtml/En }

Production content & usage inventory (read replica, 24/08/2026)

SkillPartsQuestionsPart attemptsQuestion attempts
Listening48885796,011165,128
Reading4611,25860,770150,434
Speaking3421,36137,917149,311
Writing4987438,5854,122
Total1,7893,550233,283468,995

Writing has few "questions" because most writing tasks are part-level essay prompts, not question-level items. In-test notes saved by learners: 3,564 rows (ielts_notes).

5Mock test & practice flows

Two modes on every test

Practice modeSimulation mode (mock test)
PartsLearner picks any subset (Speaking: exactly one part)All parts, fixed order
TimerLearner picks 15/30/45/60 minΞ£ part times, auto-submit at 0
AudioFree seek/pause/replayPlays once, no transport controls; Speaking prompts have a replay budget of 2
Question textVisible per content settingSpeaking: hidden except Part 2
ToolsDictionary, translate, highlight, notesDictionary/translate disabled; copy/paste blocked
Anti-cheatβ€”Forced fullscreen; tab-switch/fullscreen-exit counted as violations, warning modal, extension popups hidden; violationCount submitted with the attempt

Per-skill session flow

  1. Listening / Reading: Preview (mode cards + diamond cost + AI-vs-teacher scoring choice) β†’ sound check (Listening only) β†’ exam screen with react-hook-form state, 1-second countdown, question palette per part, Howler audio player (Listening) or resizable passage/questions splitter (Reading) β†’ every answer autosaves via submitPartAttempt β†’ Submit or timeout β†’ endAttempt(violationCount) β†’ result page.
  2. Writing: Preview with scoring-method radio (Teacher β€” only if canRequestTeacher β€” vs FLYER AI) β†’ split view: prompt + images left, essay textarea right with live word count (soft warning at 500 words, hard cap with toast) β†’ autosave on blur β†’ submit β†’ result polls while AI grades.
  3. Speaking: Preview (single-part practice or full simulation) β†’ speaker check + mic check (local-only recording) β†’ per part: typewriter intro β†’ per question: prompt audio β†’ think countdown (timeToThink) β†’ recording auto-starts, ring fills over timeToSpeak, auto-stop β†’ upload (RecordRTC mono 16 kHz β†’ /record β†’ recordId) β†’ submit per question (+ optional note in simulation) β†’ part timer can force-submit in-flight answers β†’ end attempt β†’ result.
  4. School exam sessions (B2B, feature flag student_school_exam): a blocking popup lists the exam's per-skill sessions with status pills; "Enter exam" opens the test with ?examId&sessionId&examMode=1 β€” Practice mode is hidden, the attempt is linked to the session via REST (link-attempt), and violations are additionally reported live to POST /v3/learner/exams/cheats.
Band scoring. Computed server-side. Full test β†’ band 0–9 displayed as X.X/9.0 (report side rounds to nearest half band); partial/practice β†’ raw correct/total instead of a band; Speaking prefers teacherGrade over AI grade when both exist. There is no combined 4-skill sitting inside the app β€” multi-skill mock exams are orchestrated as school exam sessions.

6AI grading β€” Writing & Speaking

Writing

Speaking

7AI Mentor (Bingo)

8Progress, reports & study tools

ToolBehavior
Result screenBand or raw score with confetti; four states: scored / waiting-AI (Rive loader, 3s poll) / waiting-teacher / no scoring requested (offers "Redo with FLYER AI"). L/R auto-opens an inline answer review; hidden entirely when the assigning teacher set isHiddenAnswer.
L/R detailed reportScore side: correct/total, time spent, half-band score, two-column answer-key grid (learner vs correct, joined by "or"). Detail side: per-part audio + toggleable tapescript (Listening), read-only questions with βœ…/❌, explanation accordions (EN/VI).
HistoryCursor-paginated table with debounced search and skill/type/status filters; each row deep-links to the correct result/report route in a new tab with ?url_back. Badges for challenge codes and placement tests.
Learning profilePeriod selector (today β†’ all time); 6 stat cards (completed tests, study time, accuracy, target band, exam date, days-to-exam); average-band line chart; 4-skill radar chart with "needs improvement" label; target modal validates .0/.5 band steps and entry < target.
Mistakes drillMispronounced words with model TTS vs the learner's own recording; re-record and re-score (per-phoneme IPA feedback) under a re-scoring quota; CEFR-level and status filters.
Vocabulary bookNotes grouped by check point, editable definitions, TTS, created from the in-test highlight tooltip (Note / Highlight / Dictionary on any selected text in passages).

9Accounts, auth & multi-tenant

10Monetization & premium gates

Subscription plans (FLYER IELTS PRO)

PlanVN price (VND)VN listUS priceCheckout
3 months790,0001,000,000$49VN β†’ hosted checkout on exam.flyer.us (VNPay); US β†’ Polar checkout (hardcoded product IDs); default selection = 6-month
6 months ⭐1,550,0002,400,000$89
12 months2,320,0003,900,000$149

Diamond top-up (AI-grading currency)

PackDiamondsPrice (VND)
Trial2525,000
Basic5050,000
Pro Learner ⭐12599,000 (was 125,000)

Wallet = diamond (purchased) + freeIeltsDiamond (rewarded), shown with a breakdown popover. Third monetization channel: activation codes redeemed at /active-account (grants plan days + diamonds, with redemption history).

Four independent gates

  1. Subscription entitlement β€” locked check points (isPremium / viewerCanAccess) redirect logged-in non-subscribers to /packages.
  2. Band-range entitlement β€” the subscription tier carries bandFrom–bandTo; the band filter and visible catalogue are scoped to that window (legacy packages = all bands 0–10).
  3. Diamonds per attempt β€” AI grading for Speaking/Writing charges the check point's diamond price; enforcement is server-side (NOT_ENOUGH_DIAMOND).
  4. Teacher review β€” the "Request scoring from teacher" option appears only when the learner's profile has canRequestTeacher.

Attribution: UTM cookies (24h TTL), referral_code (member-get-member, capture only β€” no referral UI), ?ref source domain into signup. Analytics: GTM + GA4, Firebase Analytics, Meta Pixel; Sentry for errors. iOS smart-app banner + universal links to com.flyer.ielts.

11Data, API & infrastructure

API surface

Key entities

CheckPoint (universal content container, ~80 fields) β†’ per-skill parts β†’ questions β†’ 3-primitive details; UserAttempt (~55 fields β€” one attempt entity for every FLYER product, with per-skill part attempts, band/score fields, AI + teacher grading, violation count, gamification earnings); User (wallet, subscriptions + band entitlements) β†’ up to 20 LearnerProfile (target band, exam date, streak, AI speaking quota, school/class, custom domains). Production tables: 22 ielts_* tables on the read replica (parts/questions/attempts per skill + notes).

Infrastructure

12Edge cases & error handling

SituationHandling
Not enough diamonds at startBackend returns NOT_ENOUGH_DIAMOND; modal routes to upgrade (currently /packages β€” see gap #5).
Attempt errors generallyA 16-code taxonomy over two error channels, each mapped to toast-vs-modal, i18n key, and an action (login / result / diamond / back / restart / retry); intrusiveness depends on phase β€” start blocks, submit mostly toasts, end always offers an exit.
Timer reaches 0Auto-submit; Speaking additionally stops the recorder, force-submits the in-flight answer with a 20 s safety net.
Leaving fullscreen / switching tabs in simulationViolation counter + warning modal + title flash; ESC swallowed and fullscreen re-entered; count rides on end-attempt and (in school exams) live cheat reports.
Logged in elsewhereLive subscription event β†’ blocking "logged out from X" toast with re-login.
Abandoned speaking questionAn upload-generation guard drops late audio uploads belonging to a question the learner already left.
AI grading slow/failed3 s polling; Speaking gives up gracefully after 2 minutes; Writing keeps a skeleton until feedback arrives.
Teacher hid answersisHiddenAnswer suppresses all answer review and redirects the review route home.
Anonymous user on member pagesSidebar intercepts with sign-in modal; direct URLs render empty shells (queries skipped) rather than redirecting.
imgproxy down307 fallback to the built-in Next image optimizer, no broken images.

13Known gaps & technical debt

Found during the full-codebase scan β€” each is either a product decision to make or a fix to schedule.

#FindingType
1No placement test, onboarding questionnaire or generated study plan. "Personalized roadmap" exists only in the SEO description; placementLevel, onboardingInfo and the STUDENT_ONBOARDING flag are data-model-only. Target band is captured but never drives recommendations.Product gap
2Vietnamese is force-disabled at runtime: both branches of the IP check call setLanguage("en"), overriding even manual choice on next load.Bug
3Anonymous pricing is wrong for international visitors: isFlyerUs returns false for all logged-out users, so US visitors see VND prices and the VN checkout.Bug
4No Polar path for diamonds β€” international users can buy a subscription but cannot top up diamonds (AI grading currency) at all.Product gap
5NOT_ENOUGH_DIAMOND routes to /packages (subscriptions) instead of /diamonds-preview (diamonds).UX
6No delete-account flow (orphan error string only) β€” App Store 5.1.1(v) compliance risk given the linked iOS app.Compliance
7DetailedFeedbackSpeaking (Writing-V2-style band-descriptor Speaking feedback) exists in the schema but is not consumed by the web client.Roadmap
8"Free talk / Call Bingo" mode is translated and partly implemented but not wired into the conversation mode chooser; /v3/learner/journey/continue generated but never called.Roadmap
9Brand/domain split: canonical URLs, robots.txt, sitemap and Polar success URL all point at ielts.flyer.us; per-page SEO titles still say "FLYER IELTS Virtual Testing Platform". A migration to ieltsguru.ai touches ~7 known files.Brand
10Sitemap is 12 hardcoded static URLs β€” no dynamic test detail pages, no /packages; dynamic generation is commented out.SEO
11Committed secrets: live Polar tokens, Firebase config, Redis password and other keys sit in the committed .env* files β€” rotate and move to a secret store.Security
12Premium redirect only fires for logged-in users β€” the subscription paywall is bypassable by logging out (anonymous attempts allowed by design).Decision
13Dead routes still referenced (challenge screens, /verify-account, /update-profile, /checkout…), a disabled phone field wired to console.log, half-wired daily reward, settings tabs (general/notifications/privacy) translated but unbuilt, retired GAMIFICATION theme = large unreachable code tree.Debt
14Learner feedback goes to a Google Sheet via Apps Script (bug-report widget), not into the product database; Zalo is the support channel.Ops

14Acceptance criteria & future

Acceptance criteria (verified against production, 24/08/2026)

  1. All four skills offer both Practice and Simulation modes with the mode differences in Β§5; simulation enforces fullscreen anti-cheat and submits violationCount.
  2. AI Writing report returns the 4-criteria band breakdown with bilingual sub-criteria feedback and sentence-level corrections; AI Speaking report returns transcript + per-word pronunciation with IPA/phonemes; both poll at 3 s.
  3. Diamond charging is enforced server-side including free quota; wallet = purchased + rewarded diamonds.
  4. Band-tier subscriptions scope the visible catalogue via bandFrom–bandTo entitlements.
  5. School exam sessions hide Practice mode, link attempts to sessions, and report cheats live.
  6. Anonymous visitors can browse and attempt tests on an anonymous profile; one account supports up to 20 learner profiles with single-session enforcement.
  7. Production numbers on this page reproduce from the read replica (ielts_* tables; usage = user_attempts.type_attempt='IELTS').

Recommended next (from the gaps)


← PRD catalogue Β· Source: direct scan of flyer/webs-ielts branch dev (24/08/2026) + FLYER production read replica Β· Internal β€” FLYER only.