Toàn cảnh 6 nền tảng công khai (flyer.vn, flyer.us, exam.flyer.us, teacher.flyer.us, ieltsguru.ai, teado.ai) + shell học Study nhúng trong exam + các tool nội bộ (roadmap, agent, meeting, ketoan…). Tài liệu tham chiếu duy nhất về ai đang chạy trên gì, dữ liệu chảy đi đâu, deploy ra sao, khi có sự cố tìm ai — cho toàn team Product và ai cần một điểm nhìn tổng thể về hệ thống.
Phiên bản
1.0
Ngày
26/08/2026
Owner
Nam (PM) · Tùng (Product)
Scope
Public + internal ecosystem
Nguồn
Quét codebase branch main/dev + read-replica prod DB + PRD nội bộ hiện có
1Ecosystem map — bức tranh 1 phút
FLYER có hai "mặt tiền" chính chia theo địa lý và mục đích:
🇻🇳 Thị trường Việt Nam
flyer.vn — landing sales-driven cho HS/PH VN
exam.flyer.us — ứng dụng học chính (Phòng thi ảo, Cambridge/IELTS)
teacher.flyer.us — GV / trung tâm quản lý
ieltsguru.ai — sản phẩm luyện IELTS chuyên sâu
🌎 Thị trường quốc tế
flyer.us — marketing landing EN + ES (LatAm)
teado.ai — thương hiệu AI-first cho GV LatAm (Colombia, Mexico, Peru…)
teacher.teado.ai — ứng dụng teacher rebrand (chung backend)
📈 Quy mô toàn hệ sinh thái (24/08/2026 · read-replica prod)1,68M hồ sơ HS480k tài khoản26,0M lượt làm bài40.320 trường21.107 giáo viên703 tên miền white-label
Điểm cần nhớ: exam & teacher & ielts & teado chia sẻ cùng backend — cùng database, cùng user table, cùng auth cookie. Bốn frontend nhưng một hệ dữ liệu. Đổi backend là ảnh hưởng cả bốn.
3Chi tiết 6 nền tảng công khai
3.1 flyer.vn — Landing sales cho VN
Marketinghttps://flyer.vnLive
Loại
Chi tiết
Framework
HTML tĩnh 302KB + assets/ (~30MB) — clone LadiPage 100%
Nguồn
/Users/tungtony/Downloads/flyer-vn
Ngôn ngữ
Chỉ tiếng Việt
Nhiệm vụ
Bán chứng chỉ + 3 giá trị FLYER, dẫn khách đăng ký khoá học và cài ứng dụng
Sản phẩm quảng bá
FLYER Test, FLYER PRO, Bingo AI, FLYER LMS, Teado AI, IELTS Guru, Trường Số
Không có (tĩnh); form gửi qua endpoint hard-coded của LadiPage
Deploy
Static host (linh động — CF Pages/Nginx/S3)
Hand-off
Nút login/đăng ký dẫn ra exam.flyer.us hoặc ứng dụng store
3.2 flyer.us — Landing quốc tế (EN + ES)
Marketinghttps://flyer.usLive
Loại
Chi tiết
Framework
Next.js Ứng dụng Router + TypeScript + pnpm
Nguồn
/Users/tungtony/Downloads/flyer.us
Ngôn ngữ
EN mặc định + /es (Spanish rollout cho LatAm)
Route
Ứng dụng Router — /, /es, một vài trang nội dung. Không có /api, không có middleware, không có route auth.
Backend
Static SSG — không tự phục vụ dữ liệu, gọi API bên ngoài từ client nếu cần
Deploy
Vercel (không Dockerfile, không wrangler.toml → zero-config Vercel)
Hand-off
Nút CTA dẫn tới exam.flyer.us / teacher.flyer.us
3.3 exam.flyer.us — Phòng thi ảo (core học viên)
Corehttps://exam.flyer.usLive
Đây là ứng dụng học chính của FLYER trên thị trường VN — nơi HS làm mock test Cambridge/IELTS, luyện tập, thi đua, xếp hạng. Gamification nặng: coin, kim cương, streak, khiên chứng chỉ. Study micro-frontend nhúng trong đây thành study.exam.flyer.us.
Codebase flyer-webs/apps/exam hiện bị block đọc trong session này (macOS TCC trên thư mục Downloads). Chi tiết dưới đây dựa vào WebFetch homepage sản phẩm + memory nội bộ + shell chia sẻ với study.
exam shell (streak/coin/kim cương ở shell, không có trong repo Study)
4Tool nội bộ & landing phụ
Ngoài 6 platform khách hàng, có nhiều tool nội bộ chạy trên Cloudflare Pages / Vercel — mostly một-mình-một-repo, tự deploy bằng wrangler pages deploy hoặc push Git.
Chỉ 11 endpoint: /library + /wisdom-stones/* (Đá Tri Thức). Template cho module mới.
Quy tắc chọn tầng khi phát triển tính năng mới:
Ưu tiên REST v4 cho module mới, cắt tách khỏi legacy (Go rõ ràng, dễ scale ngang).
Nếu module dùng dữ liệu nhiều mảnh liên quan (student + class + attempt) — dùng GraphQL v2 tránh N+1.
Chỉ đụng REST v3 khi phải sửa flow legacy đang chạy (auth, tuition đang phụ thuộc).
Không viết endpoint mới ở GraphQL v1.
Frontend luôn đi qua Next.js rewrites
Trình duyệt không gọi thẳng backend service. Mọi request đi qua /api/* của Next.js rồi Next inject X-Session-Token, gắn cookie same-origin, log request và tránh CORS.
Sidecar imgproxy chạy cạnh — nhận URL ảnh + resize.
Deploy: kubectl rollout restart deploy ... -n production — chưa có GitHub Actions gate.
Domain routing
Ba domain teacher.flyer.us, parent.flyer.us, tools.teado.ai đều trỏ vào cùng pod partner-web; phân biệt bằng host header + rewrite trong next.config.js. Tương tự study.flyer.us và study.exam.flyer.us cùng vào pod study.
assign_tests bẫy is_sample=true — mỗi GV đăng ký được tự sinh 10 bài mẫu; luôn filter is_sample=false khi đo usage. teacher_id 100% NULL — dùng teacher_profile_id.
Checkpoint dùng chung nhiều level — 1 checkPointId xuất hiện ở nhiều duolingo_level; count qua bảng duolingo_level_check_points tránh double.
study vocab A1 mồ côi — 5.890 bài đã build nhưng 99% chưa nối vào path nào; A1 chưa có Study path live.
teacher active KPI — dùng cohort "tháng này vs cùng kỳ tháng trước", KHÔNG cộng dồn all-time (trùng người).
ai_speaking_record_count — là remaining credit, KHÔNG phải usage. Muốn đo usage phải join speaking_question_attempts.
content grammar — audit chính tả từ replica (44 bảng) — pipeline có sẵn, duolingo_parts đã xong 678 lỗi.
7Auth & multi-tenant
Cấu trúc phiên
Cơ chế
Trường hợp dùng
Cookie HTTP-only
Nguồn phiên chính, backend cấp, domain .flyer.us hoặc .flyer.vn để chia sẻ giữa sub-app
X-Session-Token header
Hand-off cross-domain (từ flyer.us landing → exam.flyer.us) qua query ?sessTok= hoặc hash
Anonymous learner
Cookie NEXT_PUBLIC_ANONYMOUS_LEARNER_PROFILE_ID — HS chưa đăng nhập vẫn dùng được Study/Exam, khi nộp bài mới phải login
Cách đăng nhập
OTP SMS — số điện thoại VN → gửi qua vendor SMS
Google OAuth — dùng cho HS/GV có gmail
Facebook OAuth — thị trường VN vẫn dùng nhiều
Email + password — legacy, ít dùng
Google Workspace @flyer.us — cho tool nội bộ (roadmap, meeting, hr, ketoan…)
Multi-tenant hierarchy
User (1 tài khoản)
├── LearnerProfile 1..N (1 phụ huynh nhiều con)
├── TeacherProfile 0..N (GV làm nhiều trường)
│ └── School (trường/trung tâm)
│ └── CustomDomain? (703 trường đã có)
└── Cookie phiên: .flyer.us (chia sẻ sang exam / teacher / study / ielts)
Guard component (teacher.flyer.us)
Trong app/Guard.tsx, mỗi route đổi:
Chưa login & route cần auth → redirect login.
Chưa xong onboarding → chuyển tới bước đang thiếu.
URL có ?schoolId=X khác trường hiện tại → SwitchSchoolMutation.
8AI/ML stack
FLYER không tự train model. Toàn bộ AI đi qua provider LLM ngoài + prompt in-house. Có ít nhất 4 luồng AI khác nhau đang chạy production.
CALL: dùng WebRTC + STT streaming + TTS provider (ElevenLabs).
ElevenLabs key: ~/.claude/secrets/elevenlabs.txt.
4. AI Mentor / Trợ giảng AI
Tab "Trợ Giảng AI" trong teacher.flyer.us — hỏi đáp về bài, phân tích lớp.
Tab "AI Mentor" trong ieltsguru.ai — coaching cá nhân hoá cho HS IELTS.
Provider: Claude Sonnet — context injection từ user profile + last attempts.
Prompt hosting
Prompt engineering nằm trong repo backend (không nhìn thấy được từ frontend). Version control qua Git; PM muốn chỉnh phải PR trực tiếp vào backend repo, không có UI cho việc này.
Be Vietnam Pro (self-hosted 4 weights × 2 latin/vietnamese)
self-hosted /fonts/
Cơ chế "1 audio 1 lần"
Toàn ứng dụng học chỉ có một track chính chạy tại 1 thời điểm — GlobalAudioStore trong hooks/useGlobalAudio.ts giữ single-track control. Nhấn câu mới tự pause câu cũ. Tránh cảnh 2 câu hỏi cùng phát audio khi HS nhấn nhanh.
GV vào teacher.flyer.us/assigned-tests/new
│
▼ chọn check_point + lớp
POST /api/v3/assign_tests { check_point_id, class_id, deadline, target[] }
│
▼ flyer-backend-rust INSERT `assign_tests`, `assign_test_classes`, `assign_test_student`
│ TRIGGER Zalo ZNS + push notification cho HS
│
▼
HS click link Zalo hoặc mở app
│
▼ deep-link: study.flyer.us/vi/{checkPointId}?assignTestCode=XYZ&target[]=...
▼ nếu HS đang mobile browser + có assignTestCode + không phải WebView
└─► OpenInExamApp component tự chuyển sang app native
▼
HS làm bài (§10.1) → user_attempts được gắn với assign_test qua trigger
│
▼
GV mở /report/... hoặc /assigned-tests/[id]
│ query aggregate: bao nhiêu HS đã làm, điểm trung bình, HS chưa nộp
▼
Nếu HS chưa nộp qua deadline → cron gửi nhắc Zalo lại
10.3 Luồng thanh toán / kim cương
HS (VN) mua kim cương / gói PRO
│
▼ chọn phương thức
├─ VNPay ─► redirect merchant → callback POST /v3/vnpay/callback
│ → INSERT `vnpay_payments` (status='SUCCESS')
│ → UPDATE `wallets.balance`
│
├─ Polar ─► redirect polar.sh (dùng cho HS quốc tế)
│
├─ In-app ─► App Store / Google Play → server-to-server verify → `in_app_payments`
│
└─ Chuyển khoản tự động
└─ BankHub / SePay → webhook match số dư → confirm
→ INSERT `tuition_transactions`
→ UPDATE `tuitions.payment_status='PAID'`
Center owner đóng học phí theo tháng cho lớp:
GV tạo `group_invoices` cho lớp → gửi Zalo ZNS phụ huynh
PH click → SePay/BankHub link → tự confirm
Toàn bộ tool nội bộ + flyer.vn clone + landing phụ (~15 project)
wrangler pages deploy . hoặc auto khi push GitHub
Không có, thủ công
Không có CI global. Không có GitHub Actions gate lint/test/typecheck trước merge. Deploy đều chạy thủ công. Có nhắc trong nợ kỹ thuật (§14).
Runtime env injection
K8s apps dùng @beam-australia/react-env — entrypoint chạy react-env --env APP_ENV --prefix PUBLIC trước Next → sinh __ENV.js chứa PUBLIC_* tại thời điểm start pod. 1 image dùng chung dev/staging/prod, chỉ đổi ConfigMap.
Observability
Datadog Browser Logs + RUM — trên tất cả frontend K8s (teacher, exam, ielts, study). trackUser(user) gắn userId + schoolId cho toàn session.
Google Analytics + GTM — marketing sites (flyer.vn/us, teado.ai).
Slack side-car — mỗi lần pod partner-web restart, script slack.mjs post lên Slack. Chạy nối tiếp && nên nếu Slack fail thì pod fail — rủi ro biết.
Sentry: không tìm thấy config, chỉ Datadog.
12Ma trận phụ thuộc giữa các platform
Platform
Nếu sập, ai chết theo?
Postgres primary
Tất cả platform → 500 toàn hệ
Read-replica
Chỉ analytics/dashboard nội bộ (marketing.flyer.vn, cs.flyer.vn, data.flyer.vn) — không ảnh hưởng khách
Lưu ý: Tài liệu này là snapshot 26/08/2026. Data volume, feature adoption và stack có thể đổi. Trước khi hành động dựa trên con số nào, verify lại bằng SQL trên read-replica.