Files
english/Claude.md
2026-04-12 18:54:59 +07:00

430 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Claude Project Context — English Learning App (TOEIC Focus)
> File này cung cấp context đầy đủ cho Claude khi làm việc với dự án.
> Cập nhật file này mỗi khi có quyết định kiến trúc mới.
> **Last updated**: Merged all decisions — Phase 1 scaffold done, Phase 24 planned
---
## Tổng quan dự án
**Loại sản phẩm**: Web app học tiếng Anh / luyện thi TOEIC & IELTS cho người dùng Việt Nam
**Target users**: Sinh viên, người đi làm tại Việt Nam cần TOEIC, IELTS, hoặc học tiếng Anh tổng quát
**Focus chính**: TOEIC (mở rộng market), sau đó IELTS
**Giai đoạn hiện tại**: Phase 1 — MVP, validate market
**Roadmap**: 4 phases — MVP → Auth & Progress → Speaking AI → Full TOEIC
---
## Tech Stack
### Frontend
| Layer | Tech | Ghi chú |
|---|---|---|
| Framework | **React** + **Vite** + **TypeScript** | |
| Routing | **TanStack Router** | File-based, type-safe |
| Server state | **TanStack Query** | Fetch, cache, sync API data |
| Client state | **Zustand** | UI state + localStorage persist |
| Styling | **Tailwind CSS** | Desktop-first |
| UI Components | **shadcn/ui** | Dùng khi cần, không bắt buộc |
### Design System (từ Stitch export)
| Token | Value |
|---|---|
| Font | Plus Jakarta Sans + Material Symbols Outlined |
| Primary | #2563EB |
| Success | #16A34A |
| Danger | #DC2626 |
| Background | #F8FAFC |
| Card | #FFFFFF |
| Border radius | 1216px |
| Shadow | soft, subtle |
### Responsive Layout
| Breakpoint | Layout |
|---|---|
| Desktop (1280px) | Sidebar trái cố định (240px) + main content — **LAYOUT CHÍNH** |
| Tablet (768px) | Sidebar thu gọn icon-only |
| Mobile (375px) | Ẩn sidebar, hiện bottom navigation bar |
### Backend
| Phase | Tech | Ghi chú |
|---|---|---|
| Phase 1 | **Supabase** (PostgreSQL + Edge Functions + JS SDK) | Tạm thời, migrate sau |
| Phase 2+ | **NestJS** + **PostgreSQL** native | Khi có traction |
> ⚠️ Supabase chỉ dùng Phase 1. Schema PostgreSQL thiết kế chuẩn ngay từ đầu để migrate không đau.
### AI
| Layer | Tech | Ghi chú |
|---|---|---|
| Provider | **GLM (Z.ai API)** | Rẻ, OpenAI-compatible format |
| Endpoint | `open.bigmodel.cn/api/paas/v4` | |
| Model | GLM-4 / GLM-4.7 | |
| Fallback | OpenAI / Claude API | Swap dễ vì API compatible |
| Gọi từ | Supabase Edge Function (Phase 1) → NestJS service (Phase 2+) | Giấu API key |
### Deploy
| Layer | Tech |
|---|---|
| Frontend | Self-hosted server (có sẵn) |
| Backend | Self-hosted server (có sẵn) |
| Database | Supabase Cloud (Phase 1) → self-hosted PostgreSQL (Phase 2+) |
---
## Database Schema (PostgreSQL)
```sql
-- Câu hỏi TOEIC
CREATE TABLE questions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
part INT NOT NULL, -- 1 đến 7
type TEXT, -- photo | q&a | incomplete_sentence | etc.
content TEXT NOT NULL, -- nội dung câu hỏi / đoạn văn
options JSONB, -- ["A. ...", "B. ...", "C. ...", "D. ..."]
answer TEXT NOT NULL, -- "A"
explanation TEXT, -- giải thích đáp án bằng tiếng Việt
audio_url TEXT, -- Part 14 (listening)
image_url TEXT, -- Part 1 (photos)
created_at TIMESTAMPTZ DEFAULT now()
);
-- Từ vựng TOEIC
CREATE TABLE vocab (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
word TEXT NOT NULL,
phonetic TEXT, -- /wɜːrd/
meaning_vi TEXT NOT NULL, -- nghĩa tiếng Việt
topic TEXT NOT NULL, -- business | office | travel | finance | hr | marketing
example TEXT, -- câu ví dụ tiếng Anh
created_at TIMESTAMPTZ DEFAULT now()
);
-- Phase 2+
CREATE TABLE users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
email TEXT UNIQUE NOT NULL,
name TEXT NOT NULL,
password TEXT NOT NULL, -- hashed
created_at TIMESTAMPTZ DEFAULT now()
);
CREATE TABLE user_progress (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID REFERENCES users(id),
type TEXT, -- test | vocab | writing
reference_id UUID,
data JSONB,
created_at TIMESTAMPTZ DEFAULT now()
);
CREATE TABLE writing_submissions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID REFERENCES users(id),
content TEXT NOT NULL,
feedback JSONB,
created_at TIMESTAMPTZ DEFAULT now()
);
```
---
## TypeScript Interfaces
```typescript
interface Question {
id: string
part: number
type: string
content: string
options: string[]
answer: string
explanation: string
audioUrl?: string
imageUrl?: string
}
interface VocabWord {
id: string
word: string
phonetic: string
meaningVi: string
topic: 'business' | 'office' | 'travel' | 'finance' | 'hr' | 'marketing'
example: string
}
interface TestResult {
testId: string
part: number
score: number
total: number
duration: number
answers: { questionId: string; selected: string; correct: boolean }[]
completedAt: Date
}
interface WritingFeedback {
score: string
grammar: string[]
vocabulary: string[]
structure: string
improvedVersion: string
summary: string
}
// Phase 2+
interface User {
id: string
email: string
name: string
createdAt: Date
}
```
---
## Cấu trúc thư mục
```
src/
├── routes/
│ ├── index.tsx ← Trang chủ (/)
│ ├── toeic/
│ │ ├── index.tsx ← Chọn Part (/toeic)
│ │ ├── part.$partId.tsx ← Config số câu (/toeic/part/$partId)
│ │ ├── session.tsx ← Làm bài (/toeic/session)
│ │ └── result.tsx ← Kết quả + đáp án (/toeic/result)
│ ├── writing.tsx ← AI Writing Checker (/writing)
│ ├── vocab.tsx ← Flashcard (/vocab)
│ └── auth/ ← Phase 2
│ ├── login.tsx ← Đăng nhập (/auth/login)
│ └── register.tsx ← Đăng ký (/auth/register)
├── components/
│ ├── layout/
│ │ ├── Sidebar.tsx ← Desktop sidebar
│ │ └── BottomNav.tsx ← Mobile bottom nav
│ ├── QuestionCard.tsx
│ ├── FlashCard.tsx
│ ├── WritingFeedback.tsx
│ ├── ProgressRing.tsx
│ └── Timer.tsx
├── store/
│ ├── testStore.ts ← Zustand: trạng thái bài thi
│ ├── vocabStore.ts ← Zustand: flashcard progress (persist localStorage)
│ └── authStore.ts ← Zustand: user session (Phase 2)
├── hooks/
│ ├── useQuestions.ts ← TanStack Query
│ ├── useVocab.ts ← TanStack Query
│ └── useWritingCheck.ts ← TanStack Mutation → Edge Function
├── lib/
│ └── supabase.ts ← Supabase client init
└── utils/
└── rateLimiter.ts ← Rate limit 3 lần/ngày/IP (localStorage)
```
---
## Supabase Edge Function — AI Writing Checker
```typescript
// supabase/functions/writing-check/index.ts
import { serve } from "https://deno.land/std/http/server.ts"
serve(async (req) => {
const { content } = await req.json()
const response = await fetch("https://open.bigmodel.cn/api/paas/v4/chat/completions", {
method: "POST",
headers: {
"Authorization": `Bearer ${Deno.env.get("GLM_API_KEY")}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
model: "glm-4",
messages: [
{
role: "system",
content: `You are an expert English writing evaluator for TOEIC/IELTS.
Evaluate the writing and return ONLY valid JSON:
{
"score": "estimated band score",
"grammar": ["error + fix"],
"vocabulary": ["suggestion"],
"structure": "feedback in Vietnamese",
"improved_version": "rewritten version",
"summary": "overall feedback in Vietnamese"
}`
},
{ role: "user", content }
]
})
})
const data = await response.json()
const result = JSON.parse(data.choices[0].message.content)
return new Response(JSON.stringify(result), {
headers: { "Content-Type": "application/json" }
})
})
```
---
## Roadmap — 4 Phases
---
### PHASE 1 — MVP (Hiện tại) 🚧
**Mục tiêu**: Ra sản phẩm web dùng thử không cần login, validate market
**Stack**: React + Vite + TypeScript + TanStack + Zustand + Tailwind + Supabase + GLM
**Tính năng**:
- ✅ Luyện đề TOEIC mini test theo từng Part (Part 17)
- ✅ Chọn số câu: 10 / 20 / full part, có đếm giờ
- ✅ Submit → xem điểm + đáp án + giải thích tiếng Việt
- ✅ Lịch sử kết quả + thống kê điểm yếu theo Part (localStorage)
- ✅ AI Writing Checker (GLM, 3 lần/ngày/IP, không cần login)
- ✅ Flashcard từ vựng TOEIC (6 chủ đề, localStorage progress)
**Không có**:
- ❌ Auth / login
- ❌ Progress sync server
- ❌ Thanh toán
- ❌ Flutter / mobile app
- ❌ Full mock test
**Timeline**: 5 tuần
**Done khi**:
- ≥ 50 câu hỏi mỗi Part (Part 17)
- AI Writing Checker phản hồi < 5 giây
- Không lỗi hiển thị trên Chrome mobile
- 20+ người dùng thật đã dùng thử
- Không critical bug sau 1 tuần beta
---
### PHASE 2 — Auth & Progress
**Mục tiêu**: Giữ chân user, sync progress server-side, hiểu behavior trước khi monetize
**Trigger**: Phase 1 traction 200+ MAU hoặc feedback tích cực
**Stack thay đổi**:
- Migrate Supabase **NestJS + PostgreSQL native**
- Thêm **Redis** cho cache + session
**Guest Access (chưa đăng ký)**:
- Xem preview 1 bài test dạng read-only (thấy câu hỏi, không làm được)
- Không cho submit đáp án, không xem kết quả
- Hiện modal "Đăng để luyện thi" khi cố tương tác
- Flashcard: xem vài card đầu, bị chặn sau đó
- AI Writing: không dùng được, hiện CTA đăng
**Auth — Đăng ký**:
- Form: **Tên + Email + Password** (chỉ 3 field)
- Không xác thực email, không OTP, không confirm
- Đăng xong **redirect home luôn**
**Auth — Đăng nhập**:
- Email + Password
- Redirect về trang trước hoặc home
**Sau khi đăng nhập**:
- Làm bài không giới hạn
- Progress sync server-side: lịch sử thi, từ vựng, writing submissions
- Dashboard nhân: streak, biểu đồ điểm, điểm yếu theo Part
- AI Writing: 10 lần/ngày
**Không có ở Phase 2**:
- Xác thực email
- Quên mật khẩu
- Google / Zalo OAuth
- Flutter / mobile app
- Thanh toán / freemium
- Notification
---
### PHASE 3 — Speaking AI
**Mục tiêu**: Tăng differentiation, cover kỹ năng Speaking cho IELTS/TOEIC
**Trigger**: Phase 2 ổn định, user quay lại đều đặn
**Tính năng**:
- AI Speaking Coach: record giọng AI chấm phát âm + so sánh native speaker
- Luyện IELTS Speaking Part 1/2/3 (mock interview với AI)
- Shadow reading: nghe lặp lại AI so sánh độ chính xác
- Pronunciation scoring điểm số progress chart
**Tech mới**:
- Speech-to-text: Whisper API hoặc Google Speech-to-Text
- Text-to-speech: native audio
- WebRTC / MediaRecorder API (web)
---
### PHASE 4 — Full TOEIC Mock Test
**Mục tiêu**: Platform luyện TOEIC toàn diện chuẩn ETS
**Trigger**: Phase 3 xong, cần nội dung premium
**Tính năng**:
- Full TOEIC test chuẩn ETS: 200 câu, 120 phút
- Audio Listening chuẩn cho Part 14
- Auto-score: tính điểm 10990 theo bảng quy đổi ETS
- Phân tích chi tiết: điểm mạnh/yếu từng Part, so sánh lần trước
- Bộ đề theo năm: ETS 2023, 2024, Actual Test...
- Đếm ngược đến ngày thi + lịch ôn tập gợi ý
---
## Quyết định kiến trúc quan trọng
| Quyết định | do |
|---|---|
| Không auth Phase 1 | Giảm scope, validate market trước |
| Email only Phase 2, không OAuth | Đơn giản nhất để build, OAuth Phase 3+ |
| Không xác thực email Phase 2 | MVP giảm friction đăng tối đa |
| Chỉ 3 field đăng (tên/email/pass) | Friction thấp nhất, đủ để identify user |
| Guest chỉ xem preview, không làm được | Buộc đăng để dùng, giúp thu thập user data |
| Không thanh toán Phase 2 | Hiểu behavior trước khi charge tiền |
| Không Flutter Phase 2 | Web đã responsive, mobile app khi traction ràng |
| Supabase tạm Phase 1 | Ra nhanh hơn 23 tuần, schema chuẩn để migrate sau |
| GLM thay OpenAI/Claude | Rẻ hơn, OpenAI-compatible, swap dễ |
| Desktop-first (không mobile-first) | Target TOEIC learner hay dùng máy tính |
| TanStack Query + Zustand | Server state tách biệt client state ràng |
| localStorage Phase 1 | Đủ cho MVP, không cần backend phức tạp |
| NestJS Phase 2 | Supabase đủ để validate, NestJS khi scale |
| Speaking AI Phase 3 | Cần infra ổn định trước khi làm realtime audio |
| Full mock test Phase 4 | Cần content team + audio, không phải tech problem |
---
## Conventions
- **Ngôn ngữ**: Tiếng Việt cho UI người dùng, English cho code/comments/type names
- **Giải thích đáp án**: Luôn bằng tiếng Việt
- **AI feedback**: Nhận xét tổng thể tiếng Việt, dụ sửa tiếng Anh
- **Desktop-first**: Design test trên 1280px trước, mobile sau
- **YAGNI / KISS**: Không build thứ chưa cần, từng Phase giải quyết từng vấn đề
- **Schema chuẩn ngay từ đầu**: dùng Supabase, PostgreSQL schema phải production-ready
---
## Rủi ro đã nhận diện
| Rủi ro | Mức độ | Xử |
|---|---|---|
| Content đề TOEIC chất lượng thấp (crawl) | 🔴 Cao | Crawl ít + clean kỹ, tự soạn dần thay thế |
| GLM chấm writing không đủ tin cậy | 🟡 TB | Test prompt kỹ, fallback OpenAI nếu cần |
| Latency GLM từ VN cao | 🟡 TB | Benchmark thực tế, cache response nếu cần |
| User mất progress (localStorage Phase 1) | 🟡 TB | Chấp nhận Phase 1, auth Phase 2 giải quyết |
| Bản quyền đề TOEIC crawl | 🟡 TB | Seed nhanh, thay bằng nội dung tự soạn dần |
| Supabase free tier limit | 🟢 Thấp | 500MB đủ Phase 1, migrate trước khi hit limit |
| Audio quality Phase 4 | 🟡 TB | Budget cho studio recording hoặc TTS premium |