Xây một web flashcard Hán Việt đơn giản nhưng đủ xài
Xây một web flashcard Hán Việt đơn giản nhưng “đủ xài”
Dự án flashcard là một web app nhỏ, chạy thuần HTML/CSS/JS, giúp học từ vựng tiếng Trung theo kiểu flashcard. Trong bài viết này mình chia sẻ lại cách mình thiết kế, tổ chức dữ liệu và triển khai tính năng – theo góc nhìn “học mà làm”.
Demo: Flashcard Hán Việt online
Bài toán: Học Hán Việt mà không cần backend
Mục tiêu ban đầu rất rõ:
- Học từ vựng tiếng Trung: Hán tự + Pinyin + Hán Việt + nghĩa tiếng Việt
- Không cần backend, không cần build tool – chỉ cần mở
index.htmllà chạy - Dễ mở rộng chủ đề: thêm một file JSON là có thêm một bộ flashcard
- Ưu tiên trải nghiệm học: phát âm, phân tích từng chữ, giao diện dễ dùng
Từ đó mình chọn kiến trúc:
- Một file
index.htmlchứa UI + logic JavaScript - Nhiều file
.jsonlưu data flashcard theo từng chủ đề - Chạy local server đơn giản (Python/Node) để tránh lỗi CORS khi load JSON
Cấu trúc dữ liệu: Tất cả xoay quanh JSON
Mỗi chủ đề là một file JSON (ví dụ: dinosaurs.json, hospital.json, vegetables.json…). Mỗi file là một mảng các object với format như sau:
{
"hanzi": "恐龙",
"pinyin": "kǒng lóng",
"hanviet": "Khủng long",
"vietnamese": "Khủng long",
"char1": {
"hanzi": "恐",
"pinyin": "kǒng",
"hanviet": "Khủng",
"words": [
{
"hanzi": "恐龙",
"pinyin": "kǒng lóng",
"hanviet": "Khủng long",
"vietnamese": "Khủng long"
}
]
},
"char2": {
"hanzi": "龙",
"pinyin": "lóng",
"hanviet": "Long",
"words": []
}
}
- Trường bắt buộc:
hanzi,pinyin,hanviet,vietnamese
- Trường tuỳ chọn:
char1,char2,char3…: dùng để phân tích từng chữ Hán trong từ ghép- Bên trong
charX.wordslà các từ ghép liên quan đến chữ đó
Cách làm này giúp mình:
- Dễ parse trên client: chỉ cần
fetch+JSON.parse - Tách rõ data và UI: đổi nội dung không đụng tới JavaScript
- Linh hoạt mở rộng: muốn thêm chủ đề chỉ cần thêm file JSON mới
Giao diện & UX: Tối giản nhưng có “đủ đồ chơi”
Toàn bộ UI nằm trong index.html với HTML + Tailwind CSS.
Các phần chính:
- Dropdown chọn chủ đề: app có sẵn hơn 10 chủ đề như:
default.json,dinosaurs.json,hospital.json,kitchen.json,body.json,smartphone.json,planets.json,study_supplies.json,vegetables.json,dishes.json,drinking.json,radicals.json…
- Flashcard chính:
- Hán tự lớn (dễ nhìn)
- Pinyin
- Hán Việt
- Nghĩa tiếng Việt
- Điều hướng:
- Nút next/prev hoặc thanh trượt để chuyển thẻ
- Phân tích từ gốc:
- Hiển thị từng ký tự (
char1,char2…) và các từ ghép liên quan - Hữu ích nếu bạn muốn nhớ từ theo “bộ + nghĩa gốc”
- Hiển thị từng ký tự (
- Responsive:
- Dùng Tailwind để layout co giãn tốt trên cả mobile và desktop
Phát âm: Tận dụng Web Speech API
Để thêm phần “sống” cho flashcard, mình dùng Web Speech API của trình duyệt:
- Khi người dùng bấm icon 🔊, app:
- Tạo
SpeechSynthesisUtterancevới text làhanzihoặcpinyin - Chọn voice tiếng Trung (nếu trình duyệt hỗ trợ)
- Gọi
speechSynthesis.speak()
- Tạo
Một vài lưu ý thực tế:
- Web Speech API phụ thuộc vào trình duyệt:
- Chrome/Edge hoạt động ổn nhất
- Cần kết nối internet để một số giọng đọc hoạt động
- Nếu không có voice tiếng Trung, app vẫn chạy nhưng phát âm không thật sự chuẩn – chấp nhận được với scope dự án cá nhân.
Luồng hoạt động của app
-
Load ban đầu:
- Đọc danh sách file JSON được khai báo trong
index.html(mảngjsonFiles) - Tự động thêm vào dropdown chủ đề
- Đọc danh sách file JSON được khai báo trong
-
Người dùng chọn chủ đề:
- App
fetchfile JSON tương ứng - Parse dữ liệu thành danh sách flashcard trong memory
- App
-
Hiển thị flashcard:
- Render thẻ hiện tại: Hán tự, Pinyin, Hán Việt, nghĩa
- Render phân tích ký tự nếu có
char1/char2…
-
Điều hướng:
- Nút next/prev cập nhật index hiện tại
- Thanh trượt cho phép nhảy nhanh tới thẻ bất kỳ
-
Phát âm:
- Click 🔊 → gọi Web Speech API
Cách chạy dự án
Cách đơn giản nhất:
git clone https://github.com/thanhtoan0306/flashcard.git
cd flashcard
# Mở trực tiếp index.html trong trình duyệt
Tuy nhiên để tránh lỗi CORS khi load JSON, nên chạy qua local server:
Python:
python3 -m http.server 8000
# Truy cập: http://localhost:8000
Hoặc Node.js:
npx http-server
# Truy cập: http://localhost:8080 (tuỳ tool)
Thêm một chủ đề mới chỉ trong vài bước
- Tạo file JSON mới, ví dụ:
animals.json, theo đúng format dữ liệu - Thêm file đó vào mảng
jsonFilestrongindex.html - Reload page:
- Chủ đề mới sẽ tự động xuất hiện trong dropdown
- Không cần sửa thêm JavaScript
Mục tiêu ở đây là: người khác fork repo có thể tự thêm bộ từ vựng của họ mà không phải chạm sâu vào code.
Tech stack & lý do chọn
- HTML + JavaScript ES6+: phù hợp cho một app nhỏ, không cần framework
- Tailwind CSS: style nhanh, tiện thử nghiệm layout
- Web Speech API: thêm phát âm mà không cần backend
- JSON thuần: dễ edit, dễ version control, dễ tái sử dụng
Những gì mình học được từ dự án nhỏ này
- Data-driven UI: chỉ cần cấu trúc JSON hợp lý, UI có thể linh hoạt mà code JS không phình to.
- Bắt đầu từ đơn giản:
- Không vội dùng framework, không vội dựng backend
- Một file HTML duy nhất vẫn có thể giải quyết bài toán rõ ràng
- Cân bằng giữa “đủ đẹp” và “đủ dùng”:
- Tailwind giúp có giao diện sạch, hiện đại mà không tốn quá nhiều thời gian CSS custom
- Tận dụng API có sẵn của trình duyệt:
- Web Speech API là ví dụ điển hình: thêm nhiều giá trị cho trải nghiệm học mà không phải xây thêm service nào khác.
Nếu bạn muốn xem source đầy đủ hoặc fork về tự custom chủ đề riêng, có thể xem tại repo flashcard trên GitHub: https://github.com/thanhtoan0306/flashcard.
