- EdTech · LMS
- Production
- 3K+ người dùng
Edly
Tự đề xuất và phát triển trọn vẹn tính năng Nghe chép chính tả và Warm-up mini-game, thiết kế luồng giao bài theo module và AI phân tích câu hỏi trên nền tảng LMS với 3.200+ người dùng và 61.000+ câu hỏi.
Xem sản phẩm thực tế (mở trong tab mới)- Vai trò
- Full-stack · lead nhóm 2 developer
- Team
- 3–5 người
- Thời gian
- 03/2026 – 09/2026
- Trạng thái
- Đang vận hành
3.2K+
Người dùng đăng ký
61K+
Câu hỏi trong ngân hàng
2
Tính năng tự đề xuất, làm độc lập
Laravel
Vue 3
TypeScript
Inertia.js
MongoDB
- OpenAI

Bối cảnh
Edly (edly.vn) là nền tảng EdTech / LMS của Protean Studios, phát triển một phần từ nền tảng Prep4u: luyện thi IELTS 4 kỹ năng, Digital SAT và kỳ thi Đánh giá năng lực, kèm khoá học video, lớp học trực tuyến cho giáo viên và mini-game. Người dùng gồm học sinh, giáo viên, phụ huynh, sale, nhân viên nhập liệu và admin.
Codebase lớn và có hai stack frontend song song: Inertia + Vue 3 TypeScript cho các khu vực mới và Livewire cho CMS và trang cũ; dữ liệu nội dung nằm trên MongoDB, dữ liệu giao dịch trên MySQL. Tôi tham gia từ 03/2026 đến 09/2026.
Vấn đề
- Đề IELTS Listening có sẵn chỉ dùng để thi. Học sinh thiếu cách luyện nghe chủ động từng câu, và sản phẩm thiếu một kênh thu hút traffic miễn phí.
- Học sinh vào phòng thi "nguội". Cần một bước khởi động ngắn trước khi thi — nhưng không được làm giảm tỷ lệ bắt đầu thi.
- Giao bài SAT cho lớp học phải tôn trọng phạm vi: admin chia sẻ đề cho giáo viên theo module, giáo viên chỉ giao được những module mình đang sở hữu.
- Ngân hàng 61.000+ câu hỏi cần transcript, độ khó và danh mục — làm tay không xuể.
Vai trò của tôi
- Nghe chép chính tả — 100%, tự đề xuất: ý tưởng → backend/API → cấu trúc dữ liệu MongoDB → UI Vue → lưu tiến độ → AI dịch và sinh từ vựng → SEO/SSR → release.
- Warm-up mini-game — 100%, tự đề xuất: business rules → database → API → tích hợp game frontend → test → tài liệu → release.
- Giao bài theo module: tự phân tích requirement và thiết kế luồng chia sẻ đề và giao bài theo module.
- AI phân tích câu hỏi bằng OpenAI (GPT-5.5) — 100%: sinh transcript, phân loại độ khó và danh mục.
- Tham gia logic phòng thi SAT, Classroom / LMS, một số module IELTS, analytics và CMS; tối ưu API, query và cache ở các luồng mình phụ trách.
- Lead nhóm 2 developer: chia task, review code, thiết kế giải pháp.
Ràng buộc
- Codebase lớn đang vận hành, hai stack frontend, dữ liệu chia giữa MongoDB và MySQL.
- Nghe chép chính tả phải dùng được không cần đăng nhập (để làm kênh SEO) nhưng không được mất tiến độ khi người dùng đăng nhập giữa chừng.
- Trang cần SEO phải render phía server (Inertia SSR).
- AI sinh nội dung hàng loạt: output không ổn định, request dài dễ timeout.
- Warm-up là bước phụ — không được chặn luồng thi chính khi có lỗi, trừ khi nghiệp vụ yêu cầu bắt buộc.
Kiến trúc
- Nghe chép chính tả: mỗi section của đề Listening trở thành một bài luyện. Transcript chia thành segment có timestamp (từ – đến), người nói, bản dịch và từ vựng (từ, nghĩa, IPA); admin chỉnh segment ngay trong trình soạn đề Listening. Một artisan command chạy AI enrichment theo batch. Trang luyện tập render bằng Inertia SSR; tiến độ lưu MongoDB cho người đăng nhập và localStorage cho khách; dữ liệu section được cache và một Observer xoá cache khi đề hoặc câu hỏi thay đổi.
- Warm-up:
WarmupConfig(mỗi đề một cấu hình: chế độ, version, cooldown, block → item) vàWarmupAttempt(trạng thái, kết quả theo block/item, lần trả lời đầu/cuối, số lần thử, thời gian phản hồi) trên MongoDB. APIdecision → start → complete / skip; middlewareEnforceWarmupRequiredđứng trước phòng thi; frontend dùng lớp mapper TypeScript chuyển dữ liệu backend sang engine mini-game có sẵn. - Giao bài theo module: admin chia sẻ đề cho giáo viên theo module → giáo viên giao cho lớp / học sinh trong phạm vi module được sở hữu → hệ thống lọc câu hỏi theo module được giao và đồng bộ module của bài tập.
- AI phân tích câu hỏi: OpenAI (GPT-5.5) sinh transcript, độ khó, danh mục cho câu hỏi trong ngân hàng.
Quyết định kỹ thuật chính
Biến nội dung có sẵn thành sản phẩm mới
- Vấn đề: cần một tính năng luyện nghe mới mà không phải tạo nội dung từ đầu.
- Lựa chọn: tái sử dụng đề IELTS Listening — mỗi section thành một bài nghe chép từng câu, miễn phí, không cần đăng nhập.
- Lý do: chi phí nội dung gần như bằng 0, mỗi bài luyện đồng thời là một trang SEO.
- Trade-off: chất lượng bài luyện phụ thuộc chất lượng transcript gốc → admin chỉnh được segment ngay trong trình soạn đề.
AI enrichment theo batch, có kiểm soát chất lượng bằng rule
- Vấn đề: dịch và sinh từ vựng cho hàng nghìn segment bằng LLM — output không ổn định, request dài dễ timeout.
- Lựa chọn:
- Gọi OpenAI theo batch 10 segment, retry với backoff, chia nhỏ request tránh timeout.
- Kiểm tra bản dịch: tỷ lệ độ dài câu Việt/Anh phải trong khoảng 0,6–3,0; câu không đạt được gọi lại riêng lẻ.
- Tự phát hiện và sửa 2 câu dịch liền kề bị đảo vị trí.
- Lọc từ vựng: chỉ giữ từ thực sự xuất hiện trong transcript.
- Chạy offline bằng
dictation:generate-metadata --dry-runđể xem trước khi ghi.
- Lý do: không tin tuyệt đối output LLM; rule rẻ và nhanh hơn review tay toàn bộ.
- Trade-off: rule chỉ bắt được lỗi hình thức, không bắt được lỗi nghĩa → vẫn để admin chỉnh tay.
Guest-first nhưng không mất tiến độ
- Lựa chọn: khách lưu tiến độ trong localStorage; API trả 200 với dữ liệu rỗng thay vì 401 để không gián đoạn trải nghiệm; có luồng đăng nhập giữa chừng (auth modal + redirect) mà không mất tiến độ. Người đăng nhập lưu từng câu và theo batch trên MongoDB.
- Trade-off: tiến độ của khách mất khi xoá dữ liệu trình duyệt hoặc đổi thiết bị — đổi lại không có rào cản đăng nhập ở kênh SEO.
SEO kỹ thuật cho từng bài luyện
- Lựa chọn: URL slug chuẩn
/nghe-chep-chinh-ta/{slug}.htmlvới redirect 301 từ URL cũ; Inertia SSR với title/description riêng từng section; JSON-LD BreadcrumbList, HowTo, FAQ, ItemList, LearningResource, AudioObject; đưa vào sitemap, sửa lỗi crawlability, tối ưu og:image.
Warm-up: fail-open hay fail-closed là quyết định nghiệp vụ
- Vấn đề: warm-up không được làm hỏng luồng thi, nhưng một số đề cần bắt buộc khởi động.
- Lựa chọn: 3 chế độ với chiến lược lỗi khác nhau:
- Bắt buộc — fail-closed: server trả 403 nếu cố bỏ qua; middleware
EnforceWarmupRequiredchặn truy cập thẳng URL phòng thi. - Khuyến nghị — fail-open: được bỏ qua; nếu API lỗi vẫn cho vào thi.
- Tắt.
- Bắt buộc — fail-closed: server trả 403 nếu cố bỏ qua; middleware
- Lý do: mỗi chế độ là một cam kết khác nhau với người dùng; viết rõ trong business rules trước khi code để cả team thống nhất.
Versioning cấu hình và cooldown chính xác
- Lựa chọn: mỗi đề một cấu hình; version chỉ tăng khi nội dung (block/câu hỏi) thay đổi, sửa metadata không tăng. Cooldown mặc định 24h tính theo
completed_at + cooldown_hours; chỉ lượt hoàn thành cùng version mới được tính; lượt bỏ qua hoặc bỏ dở (bắt đầu quá 30 phút chưa xong) không tính. Compound index{user_id, warmup_config_id, warmup_version, status, completed_at}phục vụ đúng truy vấn cooldown. - Trade-off: thêm độ phức tạp cho dữ liệu attempt, đổi lại khi nội dung warm-up đổi thì học sinh được khởi động lại với nội dung mới.
API complete idempotent, chấm điểm phía server
- Lựa chọn:
completegọi nhiều lần (mạng chập chờn, bấm lại) vẫn cho cùng kết quả, không tạo bản ghi trùng; điểm tính hoàn toàn ở server và chỉ theo lần trả lời đầu tiên — học sinh được thử lại để học nhưng không tính điểm, và không hiển thị đạt/trượt.
Ra mắt theo phase, KPI định nghĩa trước
- Lựa chọn: phase 1 làm demo bằng dữ liệu mock, tái dùng engine mini-game có sẵn; phase 2 nối API thật qua lớp mapper TypeScript, lớp thu thập câu trả lời và fallback chấm điểm local. KPI pilot đặt trước khi ra mắt: tỷ lệ bắt đầu thi giảm không quá 5 điểm %, hoàn thành ≥ 50%, bỏ qua ≤ 40%, bỏ dở ≤ 10%; latency mục tiêu dưới 100ms cho
decision, dưới 300ms chocomplete.
Giao bài theo phạm vi module sở hữu
- Vấn đề: giáo viên chỉ được giao những module SAT mình có quyền; admin cần chia sẻ đề cho giáo viên theo từng module, không bắt buộc cả đề.
- Lựa chọn: quyền giao bài gắn với module giáo viên sở hữu; hệ thống lọc câu hỏi theo module được giao và đồng bộ module của bài tập.
Đánh đổi
- Fail-open vs fail-closed theo từng chế độ warm-up, thay vì một chiến lược cho tất cả.
- Tính điểm lần đầu vs lần tốt nhất: chọn lần đầu để điểm phản ánh trình độ thật, vẫn cho thử lại để học.
- localStorage cho khách: không rào cản, nhưng tiến độ gắn với một trình duyệt.
- QA bằng rule cho bản dịch AI: rẻ, nhanh, không bắt lỗi nghĩa.
- Phạm vi warm-up giai đoạn 1 chỉ IELTS Reading & Listening; roadmap mở rộng sang bài học, SAT, spaced repetition.
Điểm nổi bật khi triển khai
- Trải nghiệm nghe chép: chế độ Dễ / Khó, gợi ý tăng dần (hiện phần đầu đúng, che phần còn lại), chỉnh tốc độ phát, phím tắt toàn cục (Enter để kiểm tra / qua câu), phần shadowing chỉ hiện sau khi xem transcript, text-to-speech bằng Web Speech API (chế độ chậm 0,72×), xử lý độ trễ audio trên mobile.
- Dữ liệu nghe chép: catalog đếm segment bằng MongoDB aggregation và loại phần giới thiệu ("Speaker 0"); modal đánh giá sao và góp ý riêng, lưu vào hệ thống review và báo cho admin; event tracking riêng cho dictation.
- Warm-up: 4 dạng game (ghép cặp, chọn nhanh, điền chỗ trống, nghe và chọn), phản hồi đúng/sai ngay; API
/api/v1/ielts/warmup/{decision,start,complete,skip}có đề xuất rate limit từng endpoint; feature test cho logic quyết định và vòng đời lượt chơi; bộ tài liệu business rules, API contract, database schema, hướng dẫn test và các phase triển khai; xử lý các lỗi tích hợp (thiếuconfigId, CSRF 419, lệch định dạng fill-blank).
Kết quả
- Chạy production trên edly.vn (3.200+ người dùng đăng ký).
- Nghe chép chính tả: luyện miễn phí không cần đăng nhập, mỗi section là một trang SEO có structured data.
- Warm-up ra mắt với business rules, tài liệu và KPI pilot định sẵn.
Bài học
- Biến tài sản có sẵn thành sản phẩm mới thường rẻ và nhanh hơn nhiều so với tạo nội dung mới.
- Với AI sinh nội dung hàng loạt, QA bằng rule và chạy dry-run trước khi ghi là bắt buộc.
- Fail-open hay fail-closed là quyết định nghiệp vụ; viết business rules và KPI trước khi code giúp cả team thống nhất.
- Idempotency và versioning nên có ngay từ thiết kế đầu, nhất là với API chấm điểm.