State + Stage: mô hình, bằng chứng từ learn và thí điểm /speak
Mô hình: 6 State, 20 Stage (SRC-1221)
Chủ dự án 03.10.2026: "deploy 4 State now, upgrade to 6 later". Lượt SRC-1221 là lượt nâng ấy. Tên State và Stage hiển thị bằng tiếng Anh, có số thứ tự.
| State | Stage |
|---|---|
1. Discover (discover) | 1.1 Just arrived · 1.2 Comparing · 1.3 Checking price |
2. Consider (consider) | 2.1 Wants a trial · 2.2 Trial booked · 2.3 Trial done |
3. Start (start) | 3.1 Enrolled · 3.2 Starting point · 3.3 Has a plan |
4. Learning (learning) | 4.1 On plan · 4.2 Practicing · 4.3 Reviewing mistakes · 4.4 Checking progress |
5. Needs attention (attention) | 5.1 Falling behind · 5.2 Stuck · 5.3 Overloaded · 5.4 Thinking of stopping |
6. Ready (ready) | 6.1 Milestone reached · 6.2 Ready for the exam · 6.3 New goal |
Biến thể theo chương trình: NEMO SPEAK không có bài chẩn đoán nên bỏ 3.2 (3.3 Has a plan thành 3.2); NEMO WALK đọc 3.2 là "Quiz passed". Mỗi Stage có năm dòng Need, Main focus, Main action, How you get here, What comes next (STAGE_INFO; IELTS ghi đè Focus và Action bằng IELTS_STAGE_INFO).
Luật chuyển
- Tự động chỉ đi tới. Tín hiệu trên www chỉ sống trong State 1 và 2: mở trang học phí -> 1.3; mở lộ trình, chẩn đoán, chỉnh phiếu điểm, quay lại ngày thứ hai -> 1.2; bấm học thử hoặc đăng ký -> 2.1. Từ 2.2 trở đi chỉ bằng chứng từ learn (hoặc chính người dùng chọn) mới mở được.
- Needs attention là ngoại lệ duy nhất: vào và ra theo bằng chứng. learn cho biết 7 ngày trở lên không học -> 5.1 Falling behind, và lưu chỗ đang đứng (
prev); learn thấy học lại (dưới 7 ngày) -> quay về đúng chỗ ấy, hoặc xa hơn nếu learn cho thấy tiến bộ mới. Chưa từng ghi danh thì không bao giờ bị đưa vào State 5. - Chọn tay luôn được, ở mọi State. Bằng chứng không bao giờ kéo người dùng lùi dưới Stage họ tự chọn; một Stage của State 5 chọn tay không có
prevnên bằng chứng "học lại" không gỡ nó. - Mỗi lần bằng chứng đổi Stage có một dòng nhật ký (
log: thời điểm, lý do, từ, tới; 12 dòng gần nhất). Khung điều khiển ở đáy hiện dòng mới nhất ("Moved by evidence: ..."); thẻ IELTS hiện câu tiếng Việt tương ứng ("Vì learn cho biết bạn đã làm bài chẩn đoán").
| Bằng chứng từ learn | Tới |
|---|---|
SPEAK trialBooked | 2.2 Trial booked |
SPEAK trialDone | 2.3 Trial done |
IELTS enrolled, SPEAK enrolled | 3.1 Enrolled |
IELTS diagnosticDone, WALK quizPassed | 3.2 Starting point (WALK: Quiz passed) |
IELTS hasPlan | 3.3 Has a plan |
IELTS hasPlan và daysInactive < 7 | 4.1 On plan |
IELTS mistakesToReview > 0 | 4.3 Reviewing mistakes |
IELTS daysInactive >= 7 | 5.1 Falling behind (lưu chỗ cũ) |
IELTS milestoneReached | 6.1 Milestone reached |
Lưu trữ và chuyển đổi từ bản 4 State
- Khoá mới
n12.visitor.v2, dạng{ <chương trình>: { state, stage, manual, updated, prev?, log?, ielts? } }. Mọi lần đọc ghi bọctry/catch; dữ liệu hỏng bị bỏ, không tin. - Lần đọc đầu sau khi nâng: chưa có
v2thì đọcn12.visitor.v1và đổi theo bảng dưới (V1_STAGE_MAP), giữ nguyên câu trả lời của learner model IELTS và đổi luôn tên Stage trong nhật ký của nó. Cóv2rồi thìv1bị bỏ qua (không đổi hai lần).
| Cũ (4 State) | Mới |
|---|---|
| Just arrived, Exploring | 1.1 Just arrived |
| Comparing, Wants a plan | 1.2 Comparing |
| Checking price | 1.3 Checking price |
| Wants a trial, Has questions, Signing up | 2.1 Wants a trial |
| Studying | 4.1 On plan |
| Returning | 5.1 Falling behind (chỗ cũ: 4.1) |
"Wants a plan" gộp vào 1.2 vì xem lộ trình là một cách so sánh; lộ trình của chính learner nay là module của 3.3. "Has questions" gộp vào State 2: 2.1 có câu hỏi và nút hỏi qua email, 2.2 có các câu nên hỏi trong buổi thử.
- Bản dựng sẵn (prerender) luôn ở 1.1; trạng thái riêng chỉ áp sau khi React chạy, nên SEO và bản tĩnh không đổi.
Mã: apps/web/src/site/visitorState.ts (thuần, có test), journeySummary.ts (bằng chứng learn, thuần + fetch), VisitorPanel.tsx (store, LearnEvidenceSync, điều khiển ở đáy), speakFocus.ts, SpeakPage.tsx, ieltsModel.ts, ieltsFocus.ts, IeltsVisitor.tsx (dải trang con IELTS). Thẻ Stage đầu trang chủ IELTS (IeltsStageHero) đã gỡ ở SRC-1273, khi cả /ielts lẫn /parents/ielts thành công cụ khám phá.
Bằng chứng từ learn: GET /v1/me/journey-summary (SRC-1221)
Sau khi trang hydrate, www gọi endpoint này MỘT lần mỗi phiên trình duyệt với credentials: "include" (cookie phiên learn, Domain=.nemo12.com). Lỗi gì cũng im lặng: không đổi gì. Kết quả giữ trong sessionStorage (n12.journey.v1) của tab ấy.
{ "data": { "signedIn": true, "programs": {
"ielts": { "enrolled": true, "diagnosticDone": true, "hasPlan": false, "lastActiveAt": "2026-09-20",
"daysInactive": 13, "mistakesToReview": null, "milestoneReached": null, "examDate": "2027-06" },
"speak": { "trialBooked": true, "trialDone": false, "enrolled": false },
"walk": { "quizPassed": null } } } }| Trường | Nguồn | Ghi chú |
|---|---|---|
ielts.enrolled | có dòng learner_ielts_membership (trial hay member) | |
ielts.diagnosticDone | có dòng ielts_diag4_reports | |
ielts.hasPlan | có dòng learner_ielts_plan_cells | |
ielts.lastActiveAt, daysInactive | MAX(day) của learning_events, so với ngày học hôm nay | chỉ ngày, không giờ |
ielts.milestoneReached | ước lượng overall của báo cáo chẩn đoán mới nhất >= mốc thấp nhất của mục tiêu đang chạy | không có mục tiêu hay báo cáo: null |
ielts.examDate | target_date của mục tiêu đang chạy, cắt còn YYYY-MM | |
ielts.mistakesToReview | chưa có nguồn phía server (learn tự tính trên client) | luôn null |
speak.trialBooked, trialDone | speak_trial_signups; xong khi giờ kết thúc của buổi đã qua | |
speak.enrolled | có dòng speak_course_enrollments | |
walk.quizPassed | walk_quiz_attempts.passed = 1 |
Luật quyền riêng tư
- Đây là dữ liệu của CHÍNH người đang đăng nhập, chỉ hiện cho chính họ trên máy họ. Server chỉ đọc learner có
learners.user_id= user của phiên; tài khoản bố mẹ không có learner riêng nhận toànnull, không bao giờ nhận dữ liệu của con hay của người khác. - Chỉ trả có/không, số đếm và ngày thô (
YYYY-MM-DD,YYYY-MM). Không tên, email, id, điểm, câu trả lời hay chữ tự do. Không biết thìnull, không đoán. - Chưa đăng nhập hoặc cookie hỏng: 200
{ signedIn: false }với toànnull, không 401 (trang công khai không được sinh lỗi console). Vì thế route nằm trong danh sách PUBLIC củaauthCoverage.test.ts, có lý do ghi kèm. Cache-Control: private, no-store,Vary: Cookie. CORS chỉ*.nemo12.comvànemo12.com, có credentials (middleware chung của API).- www không gửi kết quả này đi đâu khác, không ghi vào
localStorage; chỉ Stage đã suy ra và dòng lý do được lưu trongn12.visitor.v2của máy ấy.
Test: workers/api/src/modules/journeySummary/routes.test.ts (chưa đăng nhập, dữ liệu của chính mình, không thấy dữ liệu người khác, tài khoản bố mẹ, CORS), apps/web/src/site/journeySummary.test.ts.
/speak: visual hierarchy theo từng Stage
Luật: MỘT khối chính (đứng đầu, chứa nút tô màu DUY NHẤT của trang, nằm trên màn đầu ở 375px), vài khối phụ ngay dưới với tiêu đề nhỏ hơn, phần còn lại gập trong "Xem thêm về NEMO SPEAK". Trên cùng luôn có dòng nhận diện "NEMO SPEAK · Nói tiếng Anh cùng bạn học mỗi tuần, có mentor" để khách biết mình đang ở trang nào; ảnh minh hoạ lớn chuyển xuống phần gập để không đẩy khối chính khỏi màn đầu.
Bảng dưới là bản 4 State (SRC-1214). Bản 6 State nằm trong SPEAK_FOCUS (speakFocus.ts): mỗi Stage một khối chính trong bảy khối sẵn có (hậu quả, nỗi sợ, vòng luyện, nghiên cứu, bảy bậc, yên tâm, sách) và một nút; từ 3.1 trở đi nút dẫn về learn.nemo12.com/speak hoặc email.
| Stage (bản cũ) | Chính (nút) | Phụ | Gập |
|---|---|---|---|
| Mới ghé | Hậu quả khi không luyện nói (carousel) · Đăng ký 2 buổi học thử miễn phí | Vòng luyện, Yên tâm trước khi bắt đầu | còn lại |
| Đang tìm hiểu | Vòng luyện · Học thử | Bảy bậc, Yên tâm | còn lại |
| Đang so sánh | Nghiên cứu đứng sau · Xem học phí | Yên tâm, Vòng luyện | còn lại |
| Xem học phí | Yên tâm trước khi bắt đầu · Xem học phí chi tiết | Bảy bậc | còn lại |
| Muốn xem lộ trình | Bảy bậc · Học thử | Vòng luyện, Yên tâm | còn lại |
| Muốn học thử | Yên tâm trước khi bắt đầu · Học thử | Nỗi sợ | còn lại |
| Còn câu hỏi | Yên tâm trước khi bắt đầu · Hỏi qua email | Nghiên cứu | còn lại |
| Đăng ký | Yên tâm trước khi bắt đầu · Đăng ký trên learn | (không) | còn lại |
| Đang học | Bảy bậc · Mở lịch nói trên learn | Vòng luyện | còn lại |
| Quay lại | Vòng luyện · Quay lại lịch nói | Nỗi sợ | còn lại |
Khu "Yên tâm trước khi bắt đầu"
Một khu gom mọi thứ giảm rủi ro cho learner, chỉ dùng dữ liệu thật, mỗi thẻ gập sẵn với một dòng tóm tắt:
| Thẻ | Nguồn |
|---|---|
| Học thử: NEMO START 2 buổi x 90 phút; 3 lượt thử riêng cho buổi thứ Tư và Chủ nhật trong 09 và 10.2026; đăng ký trước 2 giờ; diễn tiến một buổi 90 phút | apps/web/src/site/tabs/speaking.ts, workers/api/src/modules/speakPair/schedule.ts, apps/learn/src/ielts/speakSessionPlan.ts, speakProgram.ts |
| Ai hướng dẫn bạn: bốn mentor, tên, vai, chuyên môn, tiểu sử, trường cũ (dấu đã xác minh), link hồ sơ | /v1/public/mentors (bảng mentor_profiles), cùng slug với learn SpeakMentors.tsx |
| Bạn cần chuẩn bị gì: tài khoản learn, Zoom và thiết bị có micro, 90 hoặc 120 phút mỗi buổi | tabs/speaking.ts, learn SpeakSchedule.tsx |
| Học phí: NEMO START miễn phí, NEMO SPEAK 1 và 2 mỗi khoá 1.980.000đ | tabs/speaking.ts (khớp learn SpeakPair.tsx) |
| Bằng chứng thật: tin nhắn học viên, NEMO WALK, nghiên cứu gốc | SRC-1169, walkClaims.ts |
| Còn câu hỏi: hello@nemo12.com | programNavData.ts |
Còn thiếu, cần chủ dự án cung cấp: độ tuổi hoặc trình độ tối thiểu, chính sách hoàn tiền hay cam kết, số học viên hoặc số buổi đã chạy, ảnh mentor (hồ sơ hiện chưa có photo_media_id), nhóm Zalo công khai. Lệch cần chốt: tabs/speaking.ts mục Lộ trình ghi "học thử miễn phí 3 buổi", nơi khác ghi "2 buổi học thử".
Hậu quả đặt đầu trang
Ý của chủ dự án: danh sách hậu quả khi nhu cầu không được đáp ứng đứng đầu mỗi trang chương trình, mỗi lần một ý, bấm mở xem số liệu và nguồn. RiskCarousel nay nhận items và title để dùng cho mọi chương trình; /speak dùng speakRisks.ts sẵn có. Danh sách cho IELTS, SAT, AP, GRAMMAR, ESSAY, MATH, AI TEEN làm ở lượt sau, khi hạ tầng này mở ra các trang ấy.
Hậu quả cho sáu chương trình còn lại (SRC-1220)
Chủ dự án 03.10.2026: SAT (/sat, /parents/sat), AP (/ap, /parents/ap), GRAMMAR (/grammar, /parents/grammar), ESSAY (/essay, /parents/essay), MATH (/math) và AI TEEN (/ai-teen) mở thân trang bằng RiskCarousel quiet (khối data-part="program-risks"), ngay dưới hero. Dữ liệu một nguồn ở apps/web/src/site/programRisks.ts, khoá theo ProgramId; trang bố mẹ dùng bản nói về "con". /nemo-walk giữ danh sách của SPEAK; IELTS giữ module Stage 1.1.
- Mỗi chương trình 4 đến 6 ý; mỗi ý một câu claim ngắn, một hai câu chi tiết, và link nguồn.
- Chỉ trích nguồn công khai đã mở ra kiểm (DOI qua Crossref/PubMed, trang trường và College Board, GOV.UK, IELTS, UNESCO, Carnegie, OECD, WEF). Chủ dự án 03.10.2026: nguồn không mở được thì tìm nguồn khác thay; ý nào không tìm được nguồn thì viết lại thành ý có nguồn, nên ý nào cũng có link.
- Nút chính của trang vẫn là nút đặc duy nhất: carousel dùng kiểu
quiet. - Test
programRisks.test.tsgác: đủ sáu chương trình, 4 đến 6 ý, mỗi ý ít nhất một link https, không em dash, ngoặc cong hay dấu ba chấm, bản bố mẹ có chữ "con".
Discover facts đầu trang IELTS (SRC-1233)
Đã gỡ khỏi đầu trang (SRC-1273, 07.10.2026). Khối chuyện năm thẻ không còn trang nào dựng:
/ieltsbỏ nó ở SRC-1247,/parents/ieltsbỏ ở SRC-1273. Bốn thẻ số liệu nay hiện trong bước "Vì sao" của công cụ khám phá trên cả hai trang (lựa chọn "Xét tuyển đại học Việt Nam"), bản bố mẹ dùng câuline.parent. Giao diện chuyện (IeltsFactsStory), thẻ cầu nối và hình minh hoạ từng thẻ đã xoá; dữ liệu và luật nguồn bên dưới vẫn đúng và vẫn gác bằngieltsFacts.test.tsx.
Chủ dự án 04.10.2026: đầu /ielts và /parents/ielts, ngay dưới câu hỏi + claim, có một chuỗi ngắn "Vì sao IELTS quan trọng với lựa chọn đại học", không phải lời chào bán. Bốn thẻ số liệu và một thẻ cầu nối, lướt ngang (snap) trên điện thoại, nút Trước/Tiếp trên máy tính. Dữ liệu ở apps/web/src/site/ieltsFacts.ts, giao diện ở IeltsFactsStory.tsx.
| Thẻ | Số lớn | Nguồn (ngày đăng) |
|---|---|---|
| IELTS là một phần của tuyển sinh | 102 trường (2025, số tổng hợp, không phải số của Bộ); hơn 100 trường (2023) | Tuyensinh247 25.06.2025; VTV 16.07.2023 |
| Ngày càng nhiều thí sinh | NEU: khoảng 11.000 (2023), gần 12.000 (2024), khoảng 22.000 (2025), khoảng 23.000 (2026); ĐH Việt Đức gần 800 (2021), gần 2.600 (2024) | VnExpress 09.07.2023, 08.08.2024, 08.08.2025, 16.07.2026 |
| Không chỉ là môn tiếng Anh | Điểm quy đổi từ chứng chỉ có trọng số tối đa 50% | Đại biểu Nhân dân 24.03.2025 |
| Cần đúng mức band | NEU 2024: sàn 5.5, khoảng 85% thí sinh đạt từ 6.5 | VnExpress 08.08.2024 |
| Cầu nối | Đo điểm xuất phát, biết chỗ cần cải thiện, có lộ trình; nút viền (outline) |
Luật: mỗi số có tên nguồn + ngày DD.MM.YYYY + link, giữ nguyên "gần"/"khoảng" như nguồn; không bao giờ chia số dùng IELTS cho tổng thí sinh cả nước (hai bộ dữ liệu khác nhau). Thẻ cầu nối dùng nút viền vì nút tô màu duy nhất của trang thuộc thẻ Stage. State 1 (Discover) và bản prerender thấy đầy đủ; từ State 2 trở đi khối gập lại thành một dòng details. Test: apps/web/src/site/ieltsFacts.test.tsx.
Một thẻ mỗi lần (SRC-1245, chủ dự án 05.10.2026). Khối không còn lướt ngang ba thẻ cùng lúc: mỗi lần hiện đúng MỘT thẻ, có nút Trước/Tiếp, chấm vị trí kèm "2/5", phím mũi tên và vuốt; không tự chạy. Chuyển thẻ bằng motion (m, tắt khi hệ điều hành bật giảm chuyển động). Cả năm thẻ vẫn nằm trong HTML dựng sẵn (thẻ không hiện mang hidden) để giữ số liệu và nguồn cho SEO. Mỗi thẻ có một hình minh hoạ từ engine bìa sách (heroBannerSvg, khung tile bên cạnh chữ trên máy tính, khung compact phía trên chữ ở 375px), aria-hidden vì chữ vẫn là chữ thật:
| Thẻ | Hình chính | Bảng màu | Vì sao |
|---|---|---|---|
| 102 trường | door (toà nhà trường) | sky | các trường xét IELTS; xanh trời của học đường |
| khoảng 23.000 | chart (cột tăng) | aqua | thí sinh tăng mỗi năm; xanh lục của tăng trưởng |
| tối đa 50% | balance (cân có dấu %), hình mới | lavender | IELTS được cân cùng môn khác, trần 50% |
| 5.5 → 6.5 | stairs (bậc thang có cờ) | sunset | leo từ sàn 5.5 lên 6.5 |
| Cầu nối | bridge (cầu vòm), hình mới | mint | từ số liệu sang bước tiếp theo |
Test kiểm nét viền hình chính đạt 3:1 với cả hai đầu nền (WCAG 1.4.11). Khối được tách khỏi phần trên và dưới bằng đường kẻ border-y border-border và khoảng cách dọc rộng.