# Implementation Plan — website-tuvi (Tử Vi Số)

**Strategy:** MVP-first — ship Phase 1 với 5 tool chủ lực + auth + DB, mở rộng dần
**Stack:** Next.js 14 App Router · TypeScript · Tailwind · Postgres · Prisma · NextAuth · OpenAI
**Deploy:** LXC `192.168.40.22` · Docker Compose
**Repo:** local-first, push GitHub private khi có token

---

## 0. Phase Overview

| Phase | Name                     | Deliverable                                         | Time        | Cumulative     |
| ----- | ------------------------ | --------------------------------------------------- | ----------- | -------------- |
| **1** | **MVP Foundation**       | 5 tool + auth + DB + deploy chạy                    | ~10-14 days | Site sống được |
| **2** | **Core Tools Expansion** | +10 tool, AI integration thật, dashboard hoàn chỉnh | ~7-10 days  | 15 tool        |
| **3** | **Full Catalog**         | +10 tool còn lại, blog CMS, SEO polish              | ~7 days     | 25 tool        |
| **4** | **Premium & Polish**     | Subscription, email reminder, A/B test, perf tuning | ~5 days     | Launch-ready   |

Mỗi phase có `git tag` riêng + deploy staging riêng.

---

## 1. Architecture

### 1.1 Stack chi tiết

```
┌─────────────────────────────────────────────────────┐
│ FRONTEND                                            │
│   Next.js 14 App Router (RSC + Server Actions)      │
│   TypeScript strict                                 │
│   Tailwind v4 + shadcn/ui                           │
│   next/font (self-host: Noto Serif Display + BVP)   │
│   Lucide React (icons)                              │
│   Motion (formerly Framer Motion) — subtle anim     │
└─────────────────────────────────────────────────────┘
               │
               ▼
┌─────────────────────────────────────────────────────┐
│ BACKEND (cùng Next.js process)                      │
│   Server Actions cho mutations                      │
│   Route Handlers (/api) cho integrations            │
│   NextAuth.js 5 (Email + Google OAuth)              │
│   Prisma 5 ORM                                      │
│   OpenAI SDK + streaming                            │
│   Rate limit: Upstash Redis hoặc in-memory          │
└─────────────────────────────────────────────────────┘
               │
               ▼
┌─────────────────────────────────────────────────────┐
│ DATA                                                │
│   Postgres 16 (Docker container trên LXC)           │
│   Redis 7 (cache + rate limit + session)            │
│   File: assets static (lá số PDF) → /var/lib/...    │
└─────────────────────────────────────────────────────┘
               │
               ▼
┌─────────────────────────────────────────────────────┐
│ INFRA (LXC 192.168.40.22)                           │
│   Docker Compose: app + postgres + redis + nginx    │
│   Nginx reverse proxy + SSL (Let's Encrypt)         │
│   Backup: pg_dump cron daily → /backups/            │
│   Logs: docker logs + tail rotation                 │
└─────────────────────────────────────────────────────┘
```

### 1.2 Project layout

```
website-tuvi/
├── app/                          # Next.js App Router
│   ├── (marketing)/              # Public site
│   │   ├── page.tsx              # Home
│   │   ├── layout.tsx
│   │   └── blog/
│   ├── (tools)/                  # Tool pages — group routing
│   │   ├── tu-vi/page.tsx        # Tử vi trọn đời
│   │   ├── van-menh/page.tsx     # Vận mệnh AI
│   │   ├── lich-am/page.tsx
│   │   ├── ngay-tot/page.tsx
│   │   ├── hop-tuoi/page.tsx
│   │   └── ... (25 tools)
│   ├── (auth)/
│   │   ├── login/page.tsx
│   │   ├── register/page.tsx
│   │   └── verify/page.tsx
│   ├── (dashboard)/
│   │   ├── me/page.tsx           # Dashboard
│   │   ├── la-so/page.tsx        # My charts
│   │   └── settings/page.tsx
│   ├── api/                      # Route Handlers
│   │   ├── auth/[...nextauth]/route.ts
│   │   ├── ai/chat/route.ts      # AI streaming
│   │   ├── tools/[tool]/route.ts # Generic tool API
│   │   └── webhook/...
│   └── layout.tsx                # Root with theme + GA4 + cookie banner
│
├── components/
│   ├── ui/                       # shadcn/ui generated
│   ├── tools/                    # Tool-specific components
│   │   ├── ChartGrid.tsx         # Lá số 12 cung renderer
│   │   ├── BirthDateForm.tsx     # Reusable form
│   │   └── ResultCard.tsx
│   ├── layout/                   # Header, Footer, BottomNav
│   ├── home/                     # Home sections
│   └── decor/                    # Bagua, ornaments
│
├── lib/
│   ├── astrology/                # Tool logic (PURE TypeScript)
│   │   ├── tu-vi/                # An sao tử vi
│   │   │   ├── stars.ts          # 24 sao + 60+ sao phụ
│   │   │   ├── palaces.ts        # 12 cung
│   │   │   ├── compute.ts        # Main algorithm
│   │   │   └── compute.test.ts
│   │   ├── lunar/                # Âm lịch convert
│   │   ├── tu-tru/               # Bát tự tứ trụ
│   │   ├── kuta/                 # Hợp tuổi 8 tiêu chí
│   │   ├── numerology/
│   │   ├── feng-shui/
│   │   └── ...
│   ├── ai/                       # OpenAI wrapper
│   │   ├── client.ts
│   │   ├── prompts.ts            # Prompts theo tool
│   │   ├── cache.ts              # Redis cache
│   │   └── rate-limit.ts
│   ├── db/                       # Prisma client + queries
│   ├── auth/
│   ├── cookie-consent/
│   └── analytics/                # GA4 events
│
├── prisma/
│   ├── schema.prisma
│   ├── migrations/
│   └── seed.ts                   # Sao + Cung + sample blog
│
├── public/
│   ├── fonts/                    # Self-host
│   ├── og/
│   └── icons/
│
├── docs/design/                  # Already exists
├── design-system/                # Already exists
├── docker/
│   ├── Dockerfile.app
│   ├── docker-compose.yml
│   ├── nginx.conf
│   └── env.example
├── .github/workflows/
│   ├── ci.yml                    # Lint + test + build
│   └── deploy.yml                # SSH deploy on tag
├── tests/
│   ├── e2e/                      # Playwright
│   └── unit/                     # Vitest (cùng *.test.ts)
└── package.json
```

---

## 2. Database Schema

```prisma
// prisma/schema.prisma
generator client { provider = "prisma-client-js" }
datasource db { provider = "postgresql"; url = env("DATABASE_URL") }

model User {
  id            String    @id @default(cuid())
  email         String    @unique
  emailVerified DateTime?
  name          String?
  image         String?
  birthDate     DateTime?      // user's own birth (default chart)
  birthTime     String?        // HH:MM
  gender        Gender?
  isLunar       Boolean   @default(true)
  role          Role      @default(USER)
  plan          Plan      @default(FREE)

  accounts      Account[]      // NextAuth
  sessions      Session[]
  charts        Chart[]
  conversations AIConversation[]
  reminders     Reminder[]
  toolHistory   ToolHistory[]

  createdAt     DateTime  @default(now())
  updatedAt     DateTime  @updatedAt

  @@index([email])
}

enum Gender { MALE FEMALE OTHER }
enum Role { USER ADMIN }
enum Plan { FREE PREMIUM }

model Chart {
  id          String   @id @default(cuid())
  userId      String
  user        User     @relation(fields: [userId], references: [id], onDelete: Cascade)
  label       String              // "Lá số gốc", "Mẹ", "Vợ"
  isDefault   Boolean  @default(false)
  fullName    String
  birthDate   DateTime
  birthTime   String              // HH:MM
  gender      Gender
  isLunar     Boolean  @default(true)

  // Computed cache (regenerate khi thay đổi input)
  computedJson Json?              // Full algorithm output (12 cung, sao...)

  createdAt   DateTime @default(now())
  updatedAt   DateTime @updatedAt

  conversations AIConversation[]
  @@index([userId])
}

model AIConversation {
  id          String   @id @default(cuid())
  userId      String
  user        User     @relation(fields: [userId], references: [id], onDelete: Cascade)
  chartId     String?
  chart       Chart?   @relation(fields: [chartId], references: [id])
  toolKey     String              // "tu-vi", "van-menh", "kinh-dich"...
  title       String              // auto-generated từ first message
  messages    AIMessage[]
  tokensUsed  Int      @default(0)
  costCents   Int      @default(0)
  createdAt   DateTime @default(now())
  updatedAt   DateTime @updatedAt
  @@index([userId, createdAt])
}

model AIMessage {
  id              String   @id @default(cuid())
  conversationId  String
  conversation    AIConversation @relation(fields: [conversationId], references: [id], onDelete: Cascade)
  role            String              // "system" | "user" | "assistant"
  content         String   @db.Text
  createdAt       DateTime @default(now())
  @@index([conversationId])
}

model ToolHistory {
  id          String   @id @default(cuid())
  userId      String
  user        User     @relation(fields: [userId], references: [id], onDelete: Cascade)
  toolKey     String              // "tu-vi", "ngay-tot"...
  inputJson   Json                // Original input
  resultJson  Json                // Computed result snapshot
  createdAt   DateTime @default(now())
  @@index([userId, toolKey, createdAt])
}

model Reminder {
  id          String   @id @default(cuid())
  userId      String
  user        User     @relation(fields: [userId], references: [id], onDelete: Cascade)
  title       String
  reminderDate DateTime
  isLunar     Boolean  @default(false)
  recurrence  String?             // "yearly" | "monthly" | null
  notified    Boolean  @default(false)
  createdAt   DateTime @default(now())
  @@index([userId, reminderDate])
}

model BlogPost {
  id          String   @id @default(cuid())
  slug        String   @unique
  title       String
  excerpt     String   @db.Text
  content     String   @db.Text   // Markdown
  coverImage  String?
  category    String              // "tu-vi" | "phong-thuy"...
  tags        String[]
  publishedAt DateTime?
  authorName  String   @default("Tử Vi Số")
  readMinutes Int      @default(5)
  views       Int      @default(0)

  @@index([slug])
  @@index([publishedAt])
  @@index([category])
}

model Star {        // Reference: 24 sao tử vi (seed)
  id        String  @id
  name      String              // "Tử Vi", "Thiên Phủ"...
  meaning   String  @db.Text
  category  String              // "chinh-tinh" | "phu-tinh"
  goodBad   String              // "tot" | "xau" | "trung-tinh"
  imageUrl  String?
}

model Palace {      // Reference: 12 cung (seed)
  id        String  @id
  name      String              // "Mệnh", "Tài Bạch"...
  meaning   String  @db.Text
  order     Int                 // 0-11
}

// NextAuth tables
model Account {
  id                String   @id @default(cuid())
  userId            String
  type              String
  provider          String
  providerAccountId String
  refresh_token     String?  @db.Text
  access_token      String?  @db.Text
  expires_at        Int?
  token_type        String?
  scope             String?
  id_token          String?  @db.Text
  session_state     String?
  user              User     @relation(fields: [userId], references: [id], onDelete: Cascade)
  @@unique([provider, providerAccountId])
}

model Session {
  id           String   @id @default(cuid())
  sessionToken String   @unique
  userId       String
  expires      DateTime
  user         User     @relation(fields: [userId], references: [id], onDelete: Cascade)
}

model VerificationToken {
  identifier String
  token      String   @unique
  expires    DateTime
  @@unique([identifier, token])
}
```

---

## 3. Route Map (full 25 tools)

| Route                                       | Tool                  | Phase |
| ------------------------------------------- | --------------------- | ----- |
| `/`                                         | Home                  | 1     |
| `/login` `/register` `/verify`              | Auth                  | 1     |
| `/me` `/la-so` `/settings`                  | Dashboard             | 1     |
| `/blog` `/blog/[slug]`                      | Blog                  | 3     |
| `/disclaimer` `/privacy` `/terms` `/cookie` | Legal                 | 1     |
| **Tools group: Tử vi**                      |                       |       |
| `/tu-vi`                                    | **Tử vi trọn đời** ⭐ | **1** |
| `/van-menh`                                 | **Vận mệnh AI** ⭐    | **1** |
| `/tu-tru`                                   | Tứ trụ bát tự         | 2     |
| `/so-mang`                                  | Số mạng 60 hoa giáp   | 2     |
| `/tu-vi-nam`                                | Tử vi năm             | 2     |
| `/tu-vi-ngay`                               | Tử vi ngày            | 2     |
| **Tools group: Phong thủy**                 |                       |       |
| `/phong-thuy-nha`                           | **Phong thủy nhà** ⭐ | **1** |
| `/mau-sac`                                  | Màu sắc phong thủy    | 2     |
| `/so-dien-thoai`                            | Số điện thoại         | 3     |
| `/nam-xay-nha`                              | Năm xây nhà           | 3     |
| **Tools group: Lịch & Ngày**                |                       |       |
| `/lich-am`                                  | **Lịch âm dương** ⭐  | **1** |
| `/ngay-tot`                                 | **Xem ngày tốt** ⭐   | **1** |
| **Tools group: Hợp tuổi & Duyên**           |                       |       |
| `/hop-tuoi`                                 | Hợp tuổi Kuta         | 2     |
| `/hop-tuoi-lam-an`                          | Hợp tuổi làm ăn       | 2     |
| `/duyen-phan`                               | So sánh duyên phận    | 3     |
| `/tuoi-ket-hon`                             | Tuổi kết hôn          | 3     |
| **Tools group: Mystic**                     |                       |       |
| `/than-so-hoc`                              | Thần số học           | 2     |
| `/cung-hoang-dao`                           | Cung hoàng đạo        | 2     |
| `/12-con-giap`                              | 12 con giáp           | 2     |
| `/kinh-dich`                                | Kinh Dịch AI          | 3     |
| `/giai-mong`                                | Giải mộng             | 3     |
| `/ban-tay`                                  | Bàn tay               | 3     |
| **Tools group: Đặt tên**                    |                       |       |
| `/dat-ten-con`                              | Đặt tên con           | 3     |
| `/ten-cong-ty`                              | Tên công ty           | 3     |
| **Library**                                 |                       |       |
| `/sao` `/sao/[id]`                          | 24 sao tử vi          | 3     |
| `/cung` `/cung/[id]`                        | 12 cung tử vi         | 3     |
| `/thu-vien-ai`                              | Prompt library        | 4     |
| **Admin** (Phase 4)                         |                       |       |
| `/admin/blog` `/admin/users`                | Admin CMS             | 4     |

⭐ = Phase 1 MVP

---

## 4. Tool Logic (computational core)

Quan trọng nhất — đây là phần khó vì algorithm tử vi cổ học không có lib npm sẵn cho VN.

### 4.1 Tử vi trọn đời — `lib/astrology/tu-vi/`

**Input:** `{ name, birthDate, birthTime, gender, isLunar }`

**Algorithm steps:**

1. **Convert sang lịch âm** (nếu input là dương): dùng lib `lunar-javascript` hoặc tự code Bộ luật âm lịch VN (Hồ Ngọc Đức)
2. **Tính Can Chi năm/tháng/ngày/giờ** (Tứ trụ)
3. **Xác định cung Mệnh** (theo tháng sinh + giờ sinh — công thức an Mệnh)
4. **An 14 chính tinh** (Tử Vi → vòng Tử Vi, Thiên Phủ → vòng Thiên Phủ)
5. **An sao phụ** (Tả Phù Hữu Bật, Văn Xương Văn Khúc, Lộc Tồn, Kình Đà, ...)
6. **Tính 12 cung** (Mệnh, Phụ Mẫu, Phúc Đức, Điền Trạch, Quan Lộc, Nô Bộc, Thiên Di, Tật Ách, Tài Bạch, Tử Tức, Phu Thê, Huynh Đệ)
7. **Output:** `{ palaces: Palace[], stars: StarPlacement[], summary: { menhChu, mệnh: 'Thạch Lựu Mộc'... } }`

**References (TypeScript port):**

- https://github.com/8loserfruit/tuvi (PHP, port logic)
- https://github.com/dophilong/tuvi-lasoso (JS)
- Sách "Tử vi Đẩu số toàn thư" — public domain

**Phase 1 deliverable:** core algorithm pass ≥10 unit test (đối chiếu với lá số chuẩn từ tracuutuvi.com)

### 4.2 Lịch âm dương — `lib/astrology/lunar/`

**Lib:** `lunar-javascript` (NPM) — có sẵn convert AL ↔ DL chuẩn cho VN
**Functions:** `solarToLunar(date)`, `lunarToSolar(date)`, `getCanChi(date)`, `getNgayTot(date)`

### 4.3 Vận mệnh AI — `lib/ai/`

Khác các tool khác — không có algorithm, mà là **prompt engineering**:

1. User submit câu hỏi + chartId
2. Backend load chart → context
3. Build prompt: `[system: Bạn là chuyên gia tử vi VN ...] [user chart context] [user question]`
4. Stream OpenAI GPT-4o-mini → frontend
5. Save AIConversation + cache key=hash(chart+question) trong Redis

### 4.4 Ngày tốt — `lib/astrology/ngay-tot/`

**Logic:**

- Lục Diệu (Đại An, Lưu Niên, Tốc Hỷ, Xích Khẩu, Tiểu Cát, Không Vong) theo giờ
- Trực ngày (Trừ, Mãn, Bình, Định, Chấp, Phá, Nguy, Thành, Thu, Khai, Bế, Kiến)
- Sao tốt/xấu (Thiên Đức, Thiên Hỷ, Tam Hợp, Lục Hợp / Sát Chủ, Thọ Tử, Trùng Tang)
- Ngày Hoàng Đạo / Hắc Đạo
- Combined score → recommend "Tốt cho khai trương / cưới hỏi / xuất hành"

### 4.5 Phong thủy nhà

**Logic:**

- Mệnh chủ (theo năm sinh) → Đông Tứ Mệnh / Tây Tứ Mệnh
- Tính 8 hướng: Sinh Khí, Diên Niên, Thiên Y, Phục Vị (4 cát) + 4 hung
- Hướng nhà phù hợp = Sinh Khí
- Hướng giường, bếp, bàn thờ riêng

---

## 5. AI Prompts (per-tool library)

```ts
// lib/ai/prompts.ts
export const PROMPTS = {
  "van-menh": {
    system: `Bạn là chuyên gia tử vi đẩu số VN có 30 năm kinh nghiệm.
Trả lời bằng tiếng Việt, giọng văn từ tốn, đáng tin, có dẫn chứng.
Luận giải dựa CHÍNH XÁC trên lá số được cung cấp — không bịa sao, không bịa cung.
Nếu không chắc, nói "theo phái cổ điển..." chứ đừng phán quyết tuyệt đối.
Luôn kết bằng disclaimer: "Đây là tham khảo, người dùng tự quyết định."`,
    contextBuilder: (chart) => `LÁ SỐ:
- Họ tên: ${chart.fullName}
- Ngày sinh AL: ${chart.lunarDate}
- Mệnh: ${chart.menh}
- Cung Mệnh: ${chart.palaces.menh.stars.join(", ")}
- Cung Tài Bạch: ${chart.palaces.taiBach.stars.join(", ")}
... (12 cung)
`,
  },
  "kinh-dich": {
    /* ... */
  },
  "giai-mong": {
    /* ... */
  },
};
```

---

## 6. Detailed Phase 1 — MVP Foundation (10-14 days)

### Sprint 1.1: Infra Setup (2 days)

- [ ] Init Next.js 14 + TS + Tailwind v4 + shadcn/ui
- [ ] Setup ESLint + Prettier + Husky pre-commit
- [ ] Vitest + Playwright config
- [ ] Init Prisma + connect Postgres (LXC `.22`)
- [ ] Docker Compose: app + postgres + redis (local dev)
- [ ] CI/CD: GitHub Actions skeleton (lint + test + build)

### Sprint 1.2: Auth + DB (2 days)

- [ ] NextAuth.js: Email magic link + Google OAuth
- [ ] Prisma migration: User, Account, Session, VerificationToken
- [ ] Auth pages: `/login`, `/register`, `/verify`
- [ ] Dashboard skeleton: `/me`
- [ ] Cookie consent banner

### Sprint 1.3: Layout + Home (2 days)

- [ ] Self-host fonts (Noto Serif Display + BVP) qua `next/font`
- [ ] Tailwind config full token từ MASTER.md
- [ ] Header + Footer + BottomNav components
- [ ] Home page port từ mockup-preview.html sang React component
- [ ] GA4 + Tag Manager
- [ ] SEO base: metadata, sitemap, robots, OG

### Sprint 1.4: Tool 1 — Tử vi trọn đời (3 days) — KEYSTONE

- [ ] `lib/astrology/lunar/` — convert AL/DL (lib `lunar-javascript`)
- [ ] `lib/astrology/tu-vi/` — an sao algorithm + unit tests
- [ ] `BirthDateForm` component (reusable cho mọi tool)
- [ ] `ChartGrid` component — render 12 cung 4×4 SVG
- [ ] `/tu-vi` page: input form + result với chart + luận giải template
- [ ] Server Action: save Chart cho user logged in
- [ ] Test: ≥10 lá số đối chiếu với `tracuutuvi.com` (manual QA)

### Sprint 1.5: Tool 2-3 — Lịch âm + Ngày tốt (1.5 days)

- [ ] `/lich-am` — convert form, hiển thị tháng âm + Can Chi + sao
- [ ] `/ngay-tot` — input event type + ngày, recommend top 5 ngày tốt nhất

### Sprint 1.6: Tool 4 — Vận mệnh AI (2 days)

- [ ] `/van-menh` — chat UI streaming
- [ ] OpenAI integration với context = chart của user
- [ ] Rate limit: 10 calls/day cho FREE, unlimited cho PREMIUM (chưa enforce premium ở MVP)
- [ ] Save AIConversation + AIMessage

### Sprint 1.7: Tool 5 — Phong thủy nhà (1 day)

- [ ] `/phong-thuy-nha` — input mệnh + hướng nhà → output 4 cát + 4 hung
- [ ] Hiển thị bát quái rotated theo hướng

### Sprint 1.8: Polish + Deploy (1.5 days)

- [ ] Disclaimer page + popup khi xem AI lần đầu
- [ ] Privacy + Terms + Cookie policy
- [ ] Production Docker build
- [ ] Deploy lên LXC `.22`: `docker compose up -d`
- [ ] Nginx + Let's Encrypt SSL (giả sử có domain hoặc dùng IP staging)
- [ ] Smoke test E2E (Playwright)
- [ ] Backup script: `pg_dump` cron daily

**Phase 1 Definition of Done:**

- ✅ 5 tool chạy được end-to-end
- ✅ Login + dashboard "Lá số của tôi" hoạt động
- ✅ Site deploy ở `https://192.168.40.22` hoặc domain bạn cấp
- ✅ Lighthouse mobile ≥85 (Performance, Accessibility, SEO)
- ✅ E2E happy path: signup → tử vi → save chart → AI luận giải

---

## 7. Phase 2-4 (outline, detail khi gần phase)

### Phase 2 — Core Tools Expansion (~7-10 days)

- 10 tool: Tứ trụ, Số mạng, Tử vi năm, Tử vi ngày, Màu sắc PT, Hợp tuổi Kuta, Hợp tuổi làm ăn, Thần số học, Cung hoàng đạo, 12 con giáp
- Reminder system + email notification (Resend.com hoặc tự host SMTP)
- Multi-chart support (lưu nhiều lá số cho gia đình)
- Polish dashboard

### Phase 3 — Full Catalog (~7 days)

- 10 tool còn lại: Số ĐT, Năm xây nhà, Duyên phận, Tuổi kết hôn, Kinh Dịch AI, Giải mộng, Bàn tay, Đặt tên con, Tên công ty + Library 24 sao + 12 cung
- Blog CMS với Markdown + admin
- Tool group pages (`/phong-thuy` list)
- SEO polish: schema markup mọi page, sitemap dynamic, OG image generator

### Phase 4 — Premium & Polish (~5 days)

- Stripe integration (subscription Premium $X/tháng — mở khóa AI unlimited + ưu tiên)
- Email reminder daily/weekly
- A/B test framework cơ bản
- Lighthouse all routes ≥90
- Domain + SSL final
- Public launch checklist

---

## 8. Tech decisions & rationale

| Decision                            | Why                                     |
| ----------------------------------- | --------------------------------------- |
| Next.js 14 App Router (RSC default) | SEO + performance + DX, React 19 ready  |
| Tailwind v4 (không v3)              | CSS-first config, faster builds         |
| shadcn/ui                           | Own the code, customizable theo tokens  |
| Postgres + Prisma                   | Stable, type-safe, migration good       |
| Redis cho cache                     | AI luận giải hash → reuse, save cost    |
| OpenAI GPT-4o-mini default          | Tiếng Việt tốt + rẻ ($0.15/1M input)    |
| NextAuth.js v5                      | Mature, support magic link + OAuth      |
| Self-host font (`next/font`)        | LCP tốt, không phụ thuộc Google         |
| Lucide icons                        | Khớp Be Vietnam Pro stroke weight, free |
| Motion (framer-motion)              | Animation declarative, RSC-friendly     |
| Vitest + Playwright                 | Test stack chuẩn                        |
| Docker Compose deploy               | Đơn giản cho LXC 1 node                 |
| GitHub Actions deploy               | Free, đủ dùng                           |

---

## 9. Risks & Mitigations

| Risk                       | Impact           | Mitigation                                                       |
| -------------------------- | ---------------- | ---------------------------------------------------------------- |
| Algorithm tử vi sai        | Cao — phá uy tín | Cross-check ≥10 lá số với 2 site khác, có đơn vị test            |
| AI cost vượt budget        | Trung bình       | Cache aggressive, rate limit, monitor cost daily                 |
| LXC 2GB RAM hết            | Trung bình       | Monitoring, swap, scale 4GB nếu user > 100 concurrent            |
| Postgres backup mất        | Cao              | pg_dump daily + offsite copy (rsync to home server)              |
| Domain chưa có             | Thấp             | Deploy lên IP trước, switch domain sau (1 dòng nginx)            |
| Vietnamese diacritics font | Thấp             | Test corpus có đủ ký tự Việt; dùng Be Vietnam Pro (built for VI) |
| Single-tier auth bypass    | Trung bình       | NextAuth defaults secure; CSRF + cookie httpOnly đã có           |
| GDPR-lite cho VN           | Thấp             | Cookie consent + privacy page, không thu PII không cần           |

---

## 10. Open questions (cần bạn quyết khi gần phase)

1. **Domain & SSL**: khi nào bạn có domain? Mình config trước với IP, switch sau.
2. **Email provider**: Resend.com (free tier 3000/tháng), hoặc SMTP tự host?
3. **GitHub repo**: cần token để push. Token push only (read:repo + write:repo) đủ.
4. **OpenAI API key**: bạn có key chưa? Mình chỉ cần env var, không xử lý billing.
5. **GA4 + GTM ID**: có sẵn chưa hay tạo mới?
6. **Design feedback từ mockup**: có muốn đổi gì trước khi port code không?

---

## 11. First commit plan

Khi bắt đầu Phase 1:

```bash
cd /data/video-pipeline/LXC4103/project/website-tuvi
npx create-next-app@latest . --typescript --tailwind --app --no-src-dir --eslint --import-alias "@/*"
git init && git add . && git commit -m "feat: bootstrap Next.js 14 with Tailwind"
```

Sau đó branching strategy:

- `main` = production
- `dev` = staging
- `feature/<phase>-<task>` = per-task

Mỗi PR phải pass: lint + typecheck + tests + build.

---

## 12. Plan approved — ready to start?

Reply **"start"** → mình bắt đầu Sprint 1.1 (init Next.js + setup Postgres trên LXC `.22`).
Hoặc reply câu hỏi/chỉnh plan này.
