Chuyển đến nội dung
Bùi Hữu Tiến
Tất cả dự án
  • 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
Trang chủ Edly: nền tảng IELTS và SAT/ACT cho lớp học và phòng thi

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. API decision → start → complete / skip; middleware EnforceWarmupRequired đứ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.
Sơ đồ: đề IELTS Listening được chia thành segment có timestamp, được OpenAI bổ sung nội dung theo batch và kiểm tra bằng rule, rồi trở thành bài nghe chép render phía server, tiến độ lưu ở MongoDB hoặc localStorage. Với warm-up, khi bắt đầu thi hệ thống gọi decision API, tới mini-game và complete API idempotent rồi mới vào phòng thi; bỏ qua hoặc fail-open thì vào thẳng phòng thi.
Vuốt ngang để xem toàn bộ sơ đồ

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}.html vớ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 EnforceWarmupRequired chặ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.
  • 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: complete gọ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 cho complete.

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ếu configId, 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.