Files
english/Claude.md
2026-04-12 22:59:46 +07:00

19 KiB
Raw Blame History

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: Phase 2 done — thêm Phase 3 Retention & Monetization, đẩy Speaking AI và Full TOEIC sang Phase 4 & 5


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: 5 phases — MVP → Auth & Progress → Retention & Monetization → 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)

-- 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

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

// 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 có 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 ký để 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 ký

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 ký 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 cá 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 — Xu System & Gamification ← Tiếp theo

Mục tiêu: Tạo thói quen học hàng ngày, giữ chân user bằng Xu economy + gamification Platform: Web only (không Flutter ở phase này) Trigger: Phase 2 có user đăng ký, cần convert sang returning users


Xu Economy — Trung tâm của Phase 3

Học hàng ngày / xem ads → kiếm Xu
           ↓
    Xu → dùng tính năng premium
           ↓
       Hết Xu → xem ads thêm
           (nạp tiền thật → Phase 4)

Kiếm Xu (miễn phí):

Hành động Xu nhận
Đăng ký lần đầu (welcome bonus) 50 Xu
Hoàn thành daily goal 10 Xu
Streak milestone (7 / 30 / 100 ngày) 20 / 50 / 100 Xu
Xem rewarded ads trên web 5 Xu / video (tối đa 5 video/ngày)

Dùng Xu:

Tính năng Chi phí
Streak freeze (bảo vệ 1 ngày) 20 Xu
Thêm 5 lượt AI Writing (GLM-4.7) 30 Xu
1 lượt AI Writing cao cấp (GPT-4o) 15 Xu
Mở thêm bài thi khi hết giới hạn free 10 Xu

⚠️ Chưa có nạp Xu bằng tiền thật ở Phase 3 — chỉ kiếm qua học + ads. Nạp tiền thật (VNPay/MoMo) → Phase 4.


AI Model Tier

Tier Model Free limit Dùng Xu
Free GLM-4 base 3 lần/ngày
Standard GLM-4.7 30 Xu / 5 lượt
Premium GPT-4o / Claude 15 Xu / lượt

Gamification

  • Streak hàng ngày: học ít nhất 1 bài/ngày giữ chuỗi
  • XP points: mỗi bài thi / flashcard / writing check → XP
  • Cấp độ: Beginner → Bronze → Silver → Gold → Master (theo XP tích luỹ)
  • Streak freeze: dùng Xu bảo vệ streak khi bận — hook mạnh nhất
  • Weekly goal: đặt mục tiêu tuần, hoàn thành → badge + thưởng Xu

Leaderboard

  • Bảng xếp hạng tuần theo XP (reset mỗi tuần, không tích luỹ)
  • Hiện top 10 + vị trí của bản thân
  • Chia sẻ kết quả lên Facebook/Zalo — viral loop tự nhiên

Nhắc nhở

  • Browser push notification (web, không cần app)
  • Giờ nhắc do user tự chọn
  • Message cá nhân hoá: "Streak 7 ngày của bạn sắp mất!"

Lộ trình AI cá nhân hoá

  • Phân tích kết quả thi → suggest "Tuần này tập trung Part 5 và 6"
  • Dashboard: "Bạn yếu nhất ở Part 5 — luyện ngay"
  • Đặt ngày thi TOEIC → đếm ngược + lịch ôn gợi ý

Web Ads

  • Google AdSense: banner dưới trang + interstitial sau kết quả bài thi
  • Rewarded video ads: xem để nhận Xu
  • Không ads trong lúc đang làm bài
  • User có đủ Xu / premium → không hiện ads (Phase 4)

DB Schema bổ sung

CREATE TABLE user_gamification (
  user_id      UUID REFERENCES users(id) PRIMARY KEY,
  xp           INT DEFAULT 0,
  level        TEXT DEFAULT 'beginner', -- beginner | bronze | silver | gold | master
  streak       INT DEFAULT 0,
  longest_streak INT DEFAULT 0,
  last_active  DATE,
  xu           INT DEFAULT 50,          -- welcome bonus
  freeze_count INT DEFAULT 0
);

CREATE TABLE xu_transactions (
  id          UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  user_id     UUID REFERENCES users(id),
  type        TEXT,   -- earn_welcome | earn_daily | earn_streak | earn_ads | spend_freeze | spend_writing | spend_test
  amount      INT,    -- dương = nhận, âm = tiêu
  balance     INT,    -- số Xu sau giao dịch (để audit)
  description TEXT,
  created_at  TIMESTAMPTZ DEFAULT now()
);

CREATE TABLE weekly_leaderboard (
  id          UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  user_id     UUID REFERENCES users(id),
  week_start  DATE,
  xp_earned   INT DEFAULT 0,
  rank        INT
);

Tech mới:

  • Google AdSense (banner + rewarded video)
  • Browser Push Notification API
  • Cron job: reset leaderboard mỗi tuần, check streak hàng ngày

Không có ở Phase 3:

  • Nạp tiền thật (VNPay / MoMo) → Phase 4
  • Flutter / mobile app → Phase 4
  • Subscription / Premium plan → Phase 4

Timeline: 56 tuần


PHASE 4 — Speaking AI

Mục tiêu: Tăng differentiation, cover kỹ năng Speaking cho IELTS/TOEIC

Trigger: Phase 3 ổn định, có doanh thu đều

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 có điểm số và 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) + Flutter audio recording

PHASE 5 — Full TOEIC Mock Test

Mục tiêu: Platform luyện TOEIC toàn diện chuẩn ETS

Trigger: Phase 4 xong, cần nội dung premium cao cấp hơn

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 Lý 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 4+
Không xác thực email Phase 2 MVP — giảm friction đăng ký tối đa
Chỉ 3 field đăng ký (tên/email/pass) Friction thấp nhất, đủ để identify user
Guest chỉ xem preview, không làm được Buộc đăng ký để 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, Flutter Phase 3 khi có traction
Coins tên "Xu" Gần gũi user VN hơn "Credits" hay "Points"
Pay-as-you-go thay subscription User VN ít cam kết dài hạn, mua theo nhu cầu dễ convert hơn
AI model tier theo Xu Tạo upsell tự nhiên — user thấy feedback tốt hơn khi dùng model cao hơn
Rewarded ads mobile, banner ads web Phù hợp từng platform — mobile chịu video, web chịu banner
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 Target TOEIC learner hay dùng máy tính
TanStack Query + Zustand Server state tách biệt client state rõ ràng
NestJS Phase 2 Supabase đủ để validate, NestJS khi scale
Speaking AI Phase 4 Cần infra + monetization ổn định trước khi làm realtime audio
Full mock test Phase 5 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, ví dụ sửa tiếng Anh
  • Desktop-first: Design và 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ù dùng Supabase, PostgreSQL schema phải production-ready
  • Coins = "Xu": Dùng nhất quán trong code lẫn UI

Rủi ro đã nhận diện

Rủi ro Mức độ Xử lý
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
AdSense bị block (adblocker) 🟡 TB Rewarded ads mobile bù lại, không phụ thuộc 1 nguồn
VNPay/MoMo integration phức tạp 🟡 TB Dùng payment gateway trung gian (Stripe VN, PayOS)
Audio quality Phase 5 🟡 TB Budget cho studio recording hoặc TTS premium