# 🤖 Vibe Coding Workflow Checklist
## Xây dựng AI Chatbot với Next.js + v0.dev + Cursor

> **Mục tiêu:** Hoàn thiện một AI Chatbot production-ready trong một buổi làm việc tập trung  
> **Stack:** Next.js 14 (App Router) · v0.dev · Cursor AI · Vercel AI SDK  
> **Thời gian ước tính:** 3–5 giờ

---

## 📋 Mục lục

1. [Chuẩn bị Prompt & Architecture](#1-chuẩn-bị-prompt--architecture)
2. [Sinh UI với v0.dev](#2-sinh-ui-với-v0dev)
3. [Setup Project với Cursor](#3-setup-project-với-cursor)
4. [Build API Route Streaming](#4-build-api-route-streaming)
5. [Kết nối Frontend](#5-kết-nối-frontend)
6. [Test & Review](#6-test--review)
7. [Deploy & Checklist Cuối](#7-deploy--checklist-cuối)

---

## 1. Chuẩn bị Prompt & Architecture

> **Triết lý:** Garbage in → Garbage out. Prompt tốt tiết kiệm 80% thời gian sửa lỗi.

### 1.1 Xác định scope của chatbot

- [ ] Xác định **use case cụ thể** (customer support / coding assistant / RAG chatbot / general chat)
- [ ] Liệt kê **tính năng bắt buộc** (Must Have) vào một file `SPEC.md`
- [ ] Liệt kê **tính năng nâng cao** (Nice to Have) — để sau sprint 2
- [ ] Chọn **LLM provider**: OpenAI / Anthropic / Gemini / Groq / Ollama (local)
- [ ] Quyết định **kiến trúc lưu trữ** lịch sử chat: in-memory / localStorage / database (Supabase, PlanetScale)

```
💡 TIP: Viết spec theo format này cho Cursor dễ đọc:

## Bot Identity
- Tên: [Tên bot]
- Persona: [Mô tả tính cách]
- Ngôn ngữ mặc định: [VI/EN/đa ngữ]

## Core Features
1. Streaming response
2. Conversation history (N messages)
3. [Feature cụ thể của bạn]

## Constraints
- Không trả lời ngoài chủ đề [X]
- Luôn trả lời bằng [ngôn ngữ]
```

> ⚠️ **Common Mistake #1:** Không viết spec → Cursor generate code không đúng hướng → refactor mất 2x thời gian

---

### 1.2 Chuẩn bị Master Prompt cho Cursor

- [ ] Tạo file `.cursorrules` tại root project với context toàn cục
- [ ] Viết **System Prompt** cho AI chatbot (lưu vào `lib/prompts.ts`)
- [ ] Chuẩn bị **prompt template** cho từng tính năng sẽ generate

```markdown
# Template Cursor Prompt hiệu quả:

"Tôi đang xây [loại chatbot] với Next.js 14 App Router, 
Vercel AI SDK, TypeScript strict mode, và Tailwind CSS.

Context: [mô tả brief từ SPEC.md]

Task: [task cụ thể, 1 task mỗi lần]

Constraints:
- Không dùng 'use client' trừ khi bắt buộc
- Error handling đầy đủ
- TypeScript types, không dùng 'any'
- Comment bằng tiếng Việt cho logic phức tạp"
```

> ⚠️ **Common Mistake #2:** Prompt quá dài và nhiều task → Cursor bị "lost" → code lộn xộn. Mỗi prompt = 1 nhiệm vụ rõ ràng.

---

### 1.3 Chuẩn bị môi trường & API Keys

- [ ] Lấy API key từ provider đã chọn
- [ ] Tạo file `.env.local.example` với tất cả env vars cần thiết
- [ ] Thêm `.env.local` vào `.gitignore` (kiểm tra kỹ!)
- [ ] Chuẩn bị Vercel account nếu plan deploy

```env
# .env.local.example
OPENAI_API_KEY=sk-...
# hoặc
ANTHROPIC_API_KEY=sk-ant-...
GROQ_API_KEY=gsk_...

# Optional
NEXT_PUBLIC_APP_NAME="My AI Chatbot"
NEXT_PUBLIC_MAX_MESSAGES=50
```

> ⚠️ **Common Mistake #3:** Commit `.env.local` lên GitHub → lộ API key → bị charge tiền. Dùng `git secret` hoặc kiểm tra bằng `git diff --cached` trước khi commit.

---

## 2. Sinh UI với v0.dev

> **Triết lý:** v0.dev giỏi nhất ở UI shell. Đừng yêu cầu nó viết business logic.

### 2.1 Craft prompt cho v0.dev

- [ ] Truy cập [v0.dev](https://v0.dev) và đăng nhập
- [ ] Viết prompt UI theo cấu trúc sau:

```
# Prompt mẫu cho v0.dev:

Design a modern AI chatbot interface with:

Layout:
- Full-height chat window (100dvh)
- Left sidebar: conversation history list, new chat button
- Main area: message list + input bar pinned to bottom
- Optional right panel: settings/model selector

Message Bubbles:
- User messages: right-aligned, primary color background
- AI messages: left-aligned, muted background with subtle border
- Support markdown rendering (code blocks with syntax highlight)
- Streaming indicator: animated dots while AI is typing

Input Area:
- Textarea (auto-resize, max 5 rows)
- Send button (disabled when empty or loading)
- Attach file button (icon only)
- Character/token counter

Style:
- Dark mode first, clean minimal aesthetic
- Font: Inter hoặc Geist
- Tailwind CSS + shadcn/ui components
- Responsive: mobile-friendly
```

- [ ] Review kết quả, chọn variant ưng nhất
- [ ] Iterate 1–2 lần với feedback cụ thể ("make the sidebar collapsible", "add avatar to AI messages")

> 💡 **TIP:** Click "Refine" thay vì "Regenerate" khi bạn muốn giữ layout nhưng chỉnh detail. Regenerate sẽ tạo hoàn toàn mới.

---

### 2.2 Export và chuẩn bị code từ v0.dev

- [ ] Click **"Open in v0"** → kiểm tra code tab để xem component structure
- [ ] Ghi chú lại các **shadcn/ui components** được dùng (sẽ cần install)
- [ ] Copy danh sách components: `Button, Input, ScrollArea, Avatar, Badge, Separator...`
- [ ] Click **"Add to Codebase"** nếu đã có project, hoặc copy code thủ công

```
📋 Checklist components thường gặp trong chat UI:
□ ScrollArea (cuộn message list)
□ Avatar (user/bot icon)
□ Button (send, new chat)
□ Textarea (input)
□ Badge (model name, status)
□ Skeleton (loading state)
□ Separator (giữa ngày)
□ Sheet (mobile sidebar)
□ Tooltip (icon buttons)
```

> ⚠️ **Common Mistake #4:** Dùng v0.dev code trực tiếp không review → component có hardcoded data, thiếu prop types, không có error states. Luôn review trước khi paste vào project.

---

### 2.3 Tách component structure

- [ ] Xác định component hierarchy từ code v0.dev:

```
app/
├── page.tsx              # Route chính
└── chat/
    └── page.tsx          # Chat page

components/
├── chat/
│   ├── ChatLayout.tsx    # Wrapper toàn bộ
│   ├── Sidebar.tsx       # Conversation list
│   ├── MessageList.tsx   # Danh sách messages
│   ├── MessageBubble.tsx # Từng message
│   ├── ChatInput.tsx     # Input + send button
│   └── TypingIndicator.tsx # Animated dots
└── ui/                   # shadcn components
```

- [ ] Vẽ sơ đồ data flow: `page → ChatLayout → [Sidebar, MessageList, ChatInput]`
- [ ] Xác định **state nào là global** (conversation list) vs **local** (input value)

> 💡 **TIP:** Paste code v0.dev vào Cursor và hỏi: *"Hãy analyze component này và đề xuất cách tách thành các components nhỏ hơn theo best practice React"*

---

## 3. Setup Project với Cursor

> **Triết lý:** Setup đúng từ đầu, không phải fix sau. Cursor giỏi nhất khi codebase có cấu trúc rõ ràng.

### 3.1 Khởi tạo Next.js project

- [ ] Mở terminal, chạy lệnh tạo project:

```bash
npx create-next-app@latest ai-chatbot \
  --typescript \
  --tailwind \
  --eslint \
  --app \
  --src-dir \
  --import-alias "@/*"
```

- [ ] Vào thư mục project: `cd ai-chatbot`
- [ ] Mở Cursor: `cursor .`
- [ ] Kiểm tra `tsconfig.json` đã có `"strict": true`

> ⚠️ **Common Mistake #5:** Dùng Pages Router thay vì App Router → Vercel AI SDK v3+ tối ưu cho App Router, streaming sẽ phức tạp hơn không cần thiết.

---

### 3.2 Cài đặt dependencies

- [ ] **Core dependencies:**

```bash
# Vercel AI SDK (quan trọng nhất)
npm install ai

# Chọn 1 trong các providers:
npm install @ai-sdk/openai      # OpenAI / compatible
npm install @ai-sdk/anthropic   # Claude
npm install @ai-sdk/google      # Gemini
npm install @ai-sdk/groq        # Groq (fast & free tier)

# UI & Markdown
npm install react-markdown remark-gfm
npm install react-syntax-highlighter
npm install @types/react-syntax-highlighter -D

# State management (nếu cần)
npm install zustand              # Lightweight, recommend
```

- [ ] **shadcn/ui setup:**

```bash
npx shadcn-ui@latest init
# Chọn: Default style, Slate base color, CSS variables: Yes

# Install các components đã note ở bước 2.2
npx shadcn-ui@latest add button input textarea
npx shadcn-ui@latest add scroll-area avatar badge
npx shadcn-ui@latest add separator sheet skeleton tooltip
```

- [ ] Verify installation: `npm run dev` → không có lỗi là ok

> 💡 **TIP:** Dùng Groq với model `llama-3.1-8b-instant` để dev nhanh (free tier, cực nhanh), sau đó switch sang GPT-4o / Claude khi production.

---

### 3.3 Cấu hình Cursor cho project

- [ ] Tạo file `.cursorrules` tại root:

```markdown
# .cursorrules

## Project Context
Đây là AI Chatbot được xây bằng Next.js 14 App Router + Vercel AI SDK + shadcn/ui.

## Tech Stack
- Next.js 14 với App Router (KHÔNG dùng Pages Router)
- Vercel AI SDK v3 (dùng `useChat` hook, `streamText` function)
- TypeScript strict mode (không dùng `any`)
- Tailwind CSS + shadcn/ui (không viết CSS thô)
- Zustand cho state management

## Coding Standards
- Server Components mặc định, thêm 'use client' chỉ khi cần
- Tất cả async operations phải có error handling
- Luôn định nghĩa TypeScript interfaces cho props
- Tên file: PascalCase cho components, camelCase cho utilities
- Không hardcode strings, dùng constants

## File Structure Convention
- components/chat/ — Chat-specific components
- components/ui/ — shadcn components (KHÔNG sửa)  
- lib/ — utilities, helpers, prompts
- types/ — TypeScript type definitions
- app/api/ — API routes (Server-side only)

## Common Patterns
- Dùng `cn()` từ @/lib/utils cho className merging
- Error boundaries cho chat components
- Optimistic UI updates cho messages
```

- [ ] Mở Cursor Settings → Enable **Codebase Indexing** (để Cursor hiểu toàn bộ project)
- [ ] Thêm file `SPEC.md` đã viết ở bước 1 vào project root

> 💡 **TIP:** Dùng `Ctrl+L` (Chat) cho tasks phức tạp cần giải thích. Dùng `Ctrl+K` (Edit) cho sửa nhanh inline. Dùng `Tab` (Autocomplete) cho code flow tự nhiên.

---

### 3.4 Tạo folder structure và type definitions

- [ ] Paste structure sau vào Cursor và yêu cầu tạo:

```
Cursor prompt: "Tạo folder structure sau với các file index.ts rỗng 
và type definitions cơ bản cho một AI chatbot:"
```

- [ ] Tạo `types/chat.ts` với các interfaces cơ bản:

```typescript
// types/chat.ts
export interface Message {
  id: string
  role: 'user' | 'assistant' | 'system'
  content: string
  createdAt: Date
}

export interface Conversation {
  id: string
  title: string
  messages: Message[]
  createdAt: Date
  updatedAt: Date
  model: ModelId
}

export type ModelId = 
  | 'gpt-4o'
  | 'gpt-4o-mini' 
  | 'claude-3-5-sonnet-20241022'
  | 'llama-3.1-8b-instant'

export interface ChatConfig {
  model: ModelId
  temperature: number
  maxTokens: number
  systemPrompt: string
}
```

- [ ] Tạo `lib/prompts.ts` với system prompt:

```typescript
// lib/prompts.ts
export const SYSTEM_PROMPTS = {
  default: `Bạn là trợ lý AI thông minh và thân thiện...`,
  // thêm các persona khác
} as const
```

> ⚠️ **Common Mistake #6:** Không tạo types trước → Cursor generate code không consistent → type errors lan rộng. Types là "hợp đồng" cho cả project.

---

## 4. Build API Route Streaming

> **Triết lý:** API route là trái tim của chatbot. Đúng ở đây = mọi thứ khác đơn giản.

### 4.1 Tạo API route cơ bản

- [ ] Tạo file `app/api/chat/route.ts`
- [ ] Dùng Cursor với prompt sau:

```
Cursor prompt: "Tạo Next.js App Router API route tại app/api/chat/route.ts 
với các yêu cầu sau:
- Dùng Vercel AI SDK streamText
- Provider: [OpenAI/Anthropic/Groq - chọn 1]
- Nhận messages array từ request body
- Include system prompt từ lib/prompts.ts
- Validate input với kiểm tra đơn giản
- Error handling: 400 cho invalid input, 500 cho API errors
- Rate limiting cơ bản (optional)
- TypeScript strict"
```

- [ ] Review code được generate, kiểm tra:

```typescript
// Checklist review API route:
// ✓ Dùng StreamingTextResponse hoặc toDataStreamResponse
// ✓ POST method được export
// ✓ Validate messages không rỗng
// ✓ Model được lấy từ env hoặc request
// ✓ System prompt được append đúng chỗ
// ✓ Catch block trả về proper error response
// ✓ Không có secrets trong code
```

---

### 4.2 Implement streaming với error handling đầy đủ

- [ ] Đảm bảo API route có structure tương tự:

```typescript
// app/api/chat/route.ts — Reference structure
import { streamText } from 'ai'
import { openai } from '@ai-sdk/openai'  // hoặc provider khác
import { SYSTEM_PROMPTS } from '@/lib/prompts'
import { NextRequest } from 'next/server'

export const runtime = 'edge'  // Faster cold starts
export const maxDuration = 30  // Vercel timeout

export async function POST(req: NextRequest) {
  try {
    const { messages, config } = await req.json()

    // Validate
    if (!messages || !Array.isArray(messages) || messages.length === 0) {
      return new Response('Invalid messages', { status: 400 })
    }

    const result = await streamText({
      model: openai('gpt-4o-mini'),
      system: SYSTEM_PROMPTS.default,
      messages,
      maxTokens: 2048,
      temperature: 0.7,
      // onFinish: async ({ text, usage }) => {
      //   // Save to database nếu cần
      // }
    })

    return result.toDataStreamResponse()

  } catch (error) {
    console.error('[API/CHAT]', error)
    return new Response(
      JSON.stringify({ error: 'Internal server error' }), 
      { status: 500, headers: { 'Content-Type': 'application/json' } }
    )
  }
}
```

- [ ] Test API route độc lập với curl hoặc Postman:

```bash
curl -X POST http://localhost:3000/api/chat \
  -H "Content-Type: application/json" \
  -d '{"messages": [{"role": "user", "content": "Xin chào!"}]}'
```

- [ ] Confirm thấy streaming response (text xuất hiện dần từng chunk)

> ⚠️ **Common Mistake #7:** Quên `export const runtime = 'edge'` → Edge runtime response nhanh hơn Node.js runtime cho streaming. Tuy nhiên một số packages không tương thích edge → test kỹ.

---

### 4.3 Thêm middleware và bảo vệ API

- [ ] Tạo basic rate limiting (nếu public):

```
Cursor prompt: "Thêm simple in-memory rate limiting cho API route: 
max 20 requests/minute per IP, trả về 429 với message tiếng Việt 
khi vượt quá. Dùng Map để store, tự clean sau 1 phút."
```

- [ ] Thêm CORS headers nếu cần (thường không cần với Next.js cùng domain)
- [ ] Validate message content length:

```typescript
// Thêm vào validation block
const MAX_MESSAGE_LENGTH = 4000
const MAX_MESSAGES = 50

if (messages.some((m: Message) => m.content.length > MAX_MESSAGE_LENGTH)) {
  return new Response('Message too long', { status: 400 })
}

if (messages.length > MAX_MESSAGES) {
  return new Response('Too many messages', { status: 400 })
}
```

> 💡 **TIP:** Dùng `console.error` có prefix `[API/CHAT]` để filter logs dễ hơn trong Vercel dashboard.

---

## 5. Kết nối Frontend

> **Triết lý:** `useChat` hook của Vercel AI SDK làm 90% công việc. Đừng reinvent the wheel.

### 5.1 Setup useChat hook

- [ ] Tạo `components/chat/ChatContainer.tsx` (client component):

```
Cursor prompt: "Tạo ChatContainer component với:
- 'use client' directive
- useChat hook từ 'ai/react' trỏ đến /api/chat
- Handle: onError hiển thị toast/alert
- Handle: isLoading state
- Auto-scroll to bottom khi có message mới
- Persist messages vào localStorage khi conversation thay đổi
- TypeScript strict, dùng types từ @/types/chat"
```

- [ ] Kiểm tra `useChat` được configure đúng:

```typescript
// Reference: useChat configuration
const {
  messages,
  input,
  handleInputChange,
  handleSubmit,
  isLoading,
  error,
  stop,          // Quan trọng: cho phép user dừng streaming
  reload,        // Retry message cuối
  setMessages,   // Để clear/load conversation
} = useChat({
  api: '/api/chat',
  initialMessages: loadedMessages, // từ localStorage/DB
  onError: (error) => {
    console.error(error)
    // Show toast notification
  },
  onFinish: (message) => {
    // Save conversation sau khi AI xong
    saveConversation(message)
  },
})
```

> ⚠️ **Common Mistake #8:** Không implement `stop()` → User không thể dừng response dài → UX tệ. Luôn có Stop button khi `isLoading = true`.

---

### 5.2 Integrate UI components từ v0.dev

- [ ] Paste code từ v0.dev vào các file tương ứng
- [ ] Connect props từ `useChat` vào UI components:

```
Cursor prompt: "Kết nối useChat hook vào ChatLayout component này [paste component].
Thay thế hardcoded messages bằng messages từ hook.
Input onChange → handleInputChange.
Form submit → handleSubmit.
Thêm disabled state cho button khi isLoading.
Thêm Stop button hiện khi isLoading.
Giữ nguyên styling, chỉ thay logic."
```

- [ ] Kiểm tra từng connection:

```
✓ messages map → MessageBubble components
✓ input value → controlled input
✓ form onSubmit → handleSubmit (không prevent default thêm)
✓ isLoading → loading states (button disabled, typing indicator)
✓ error → error message hiển thị
✓ stop → stop button
```

---

### 5.3 Implement Markdown rendering

- [ ] Tạo `components/chat/MarkdownRenderer.tsx`:

```
Cursor prompt: "Tạo MarkdownRenderer component dùng react-markdown + remark-gfm.
Features:
- Code blocks với syntax highlighting (react-syntax-highlighter, theme: oneDark)
- Copy button cho code blocks
- Inline code styling
- Table styling với Tailwind
- Link mở tab mới (target='_blank')
- Sanitize HTML
Props: { content: string, className?: string }"
```

- [ ] Sử dụng trong `MessageBubble`:

```typescript
// Chỉ render markdown cho AI messages
{message.role === 'assistant' 
  ? <MarkdownRenderer content={message.content} />
  : <p>{message.content}</p>
}
```

> 💡 **TIP:** Thêm `remarkGfm` plugin để support tables, strikethrough, task lists — những thứ AI hay generate.

---

### 5.4 Implement auto-scroll và UX details

- [ ] Auto-scroll to bottom:

```
Cursor prompt: "Thêm auto-scroll behavior cho MessageList:
- Scroll to bottom khi có message mới
- Dùng useRef + useEffect + scrollIntoView
- Chỉ auto-scroll nếu user đang ở gần bottom (threshold: 100px)
- Nếu user đã scroll lên, KHÔNG force scroll (respect user intent)
- Thêm 'Scroll to bottom' button khi user ở trên"
```

- [ ] Thêm keyboard shortcuts:

```typescript
// Trong ChatInput component
const handleKeyDown = (e: React.KeyboardEvent) => {
  if (e.key === 'Enter' && !e.shiftKey) {
    e.preventDefault()
    if (!isLoading && input.trim()) {
      handleSubmit(e as any)
    }
  }
  // Shift+Enter = new line (mặc định)
}
```

- [ ] Thêm character counter và token estimate:

```typescript
// Ước tính token đơn giản: ~4 chars per token
const estimatedTokens = Math.ceil(input.length / 4)
const isNearLimit = estimatedTokens > 800
```

- [ ] Optimistic UI: message user hiện ngay, không đợi server response

> ⚠️ **Common Mistake #9:** Force auto-scroll mọi lúc → User đang đọc message cũ bị bắn xuống dưới → Rất khó chịu. Implement "smart scroll" như trên.

---

### 5.5 Thêm Conversation Management

- [ ] Tạo `store/chatStore.ts` với Zustand:

```
Cursor prompt: "Tạo Zustand store cho conversation management:
State:
- conversations: Conversation[]
- activeConversationId: string | null
Actions:
- createConversation(title?: string): string (returns id)
- deleteConversation(id: string): void
- updateConversationTitle(id: string, title: string): void
- setActiveConversation(id: string): void
Persistence: dùng zustand/middleware persist với localStorage"
```

- [ ] Kết nối sidebar vào store
- [ ] Auto-generate conversation title từ message đầu tiên (dùng AI hoặc truncate)

---

## 6. Test & Review

> **Triết lý:** Test không phải chỉ là "xem có chạy không" mà là "có chạy đúng không".

### 6.1 Manual Testing Checklist

#### Functional Tests
- [ ] Gửi message thông thường → nhận response streaming
- [ ] Message dài (>1000 ký tự) → xử lý đúng
- [ ] Message có code → hiển thị syntax highlight
- [ ] Message có table/list markdown → render đúng
- [ ] Click Stop khi AI đang stream → dừng ngay lập tức
- [ ] Reload conversation → messages vẫn còn
- [ ] Tạo conversation mới → slate trắng
- [ ] Xóa conversation → biến mất khỏi sidebar
- [ ] Switch giữa conversations → messages đúng

#### Edge Cases
- [ ] Gửi message rỗng → button disabled, không gửi được
- [ ] Tắt internet → error message hiển thị
- [ ] API trả về lỗi 500 → error handling đúng
- [ ] Spam click Send → không gửi duplicate
- [ ] Message cực ngắn ("ok", "k") → vẫn hoạt động
- [ ] Emoji trong message → hiển thị đúng 😊
- [ ] Copy code block → clipboard có đúng nội dung

#### UX Tests
- [ ] Typing indicator hiện khi AI đang respond
- [ ] Auto-scroll hoạt động đúng (không jump khi đang đọc)
- [ ] Responsive trên mobile (375px width)
- [ ] Dark/Light mode (nếu implement)
- [ ] Keyboard navigation hoạt động

> 💡 **TIP:** Dùng browser DevTools → Network tab → lọc "chat" để xem streaming response real-time.

---

### 6.2 Code Review với Cursor

- [ ] Mở từng file quan trọng, hỏi Cursor:

```
Cursor prompt cho code review:

"Review file này và cho tôi biết:
1. Security issues (nếu có)
2. Performance problems
3. Missing error handling
4. TypeScript improvements
5. UX issues từ góc nhìn của người dùng

Chỉ liệt kê vấn đề thực sự, không suggest refactor 
những thứ đang hoạt động tốt."
```

- [ ] Review `app/api/chat/route.ts` — focus: security, error handling
- [ ] Review `ChatContainer.tsx` — focus: performance, re-renders
- [ ] Review `MessageList.tsx` — focus: scroll behavior, large lists
- [ ] Review `store/chatStore.ts` — focus: state logic, persistence

---

### 6.3 Performance Check

- [ ] Mở Chrome DevTools → Performance tab
- [ ] Kiểm tra re-renders không cần thiết (React DevTools Profiler)
- [ ] Memo hóa các component nặng:

```
Cursor prompt: "Analyze MessageBubble component này và thêm 
React.memo với custom comparison function để tránh re-render 
không cần thiết khi parent re-renders."
```

- [ ] Kiểm tra bundle size: `npm run build` → xem output sizes
- [ ] Large message lists (>50 messages) → xem xét virtualization

```
Nếu messages > 50: Cursor prompt: "Implement virtual scrolling 
cho MessageList dùng @tanstack/react-virtual để handle 
hàng trăm messages mà không lag"
```

> ⚠️ **Common Mistake #10:** Re-render toàn bộ MessageList mỗi khi có token stream → Lag rõ rệt khi list dài. MessageList phải memo, chỉ MessageBubble mới add animate.

---

### 6.4 Security Review Checklist

- [ ] API keys không có trong client-side code
- [ ] Input được validate phía server (không chỉ client)
- [ ] Không expose internal error details cho client
- [ ] Rate limiting hoạt động (test bằng rapid requests)
- [ ] `.env.local` trong `.gitignore`
- [ ] Không có `console.log(apiKey)` hay log sensitive data
- [ ] Content Security Policy headers (optional nhưng recommended)

```bash
# Quick security check
grep -r "process.env" components/ pages/  
# Không nên thấy SERVER-SIDE env vars trong client components
```

---

### 6.5 Accessibility Check

- [ ] Keyboard navigation: Tab qua tất cả interactive elements
- [ ] Screen reader: alt text cho avatars/icons
- [ ] ARIA labels cho icon buttons (không có text)
- [ ] Color contrast đủ (WCAG AA minimum)
- [ ] Focus ring visible trên interactive elements
- [ ] Error messages được announce cho screen readers

```
Cursor prompt: "Review ChatInput component và thêm 
ARIA attributes phù hợp: aria-label cho buttons, 
aria-live='polite' cho error messages, 
role='status' cho typing indicator"
```

---

## 7. Deploy & Checklist Cuối

### 7.1 Pre-deploy Checklist

- [ ] `npm run build` → **0 errors, 0 warnings**
- [ ] `npm run lint` → clean
- [ ] Tất cả env vars đã được document trong `.env.local.example`
- [ ] Remove tất cả `console.log` debug (giữ `console.error`)
- [ ] Test production build locally: `npm run start`

```bash
# Build check
npm run build
npm run start
# Mở localhost:3000 và test lại một lần nữa
```

---

### 7.2 Deploy lên Vercel

- [ ] Push code lên GitHub (kiểm tra lần cuối không có `.env.local`)
- [ ] Vào [vercel.com](https://vercel.com) → New Project → Import repo
- [ ] Thêm Environment Variables trong Vercel dashboard:

```
OPENAI_API_KEY = [your key]
# Tất cả vars trong .env.local.example
```

- [ ] Deploy → chờ build hoàn tất
- [ ] Test production URL với đầy đủ flows

> 💡 **TIP:** Vercel tự detect Next.js project, không cần config gì thêm. Framework preset = Next.js, Build command và Output directory tự động.

---

### 7.3 Post-deploy Monitoring

- [ ] Vào Vercel → Functions → Xem logs của `/api/chat`
- [ ] Test error scenarios trên production (sai API key, rate limit)
- [ ] Set up Vercel Analytics (miễn phí) để track usage
- [ ] Bookmark URL monitoring: Vercel dashboard → Deployments

---

### 7.4 Final Quality Checklist

```
FUNCTIONALITY          STATUS
─────────────────────────────────
□ Streaming works         ___
□ History persists        ___
□ New chat works          ___
□ Stop button works       ___
□ Error handling          ___
□ Mobile responsive       ___
□ Dark mode               ___

PERFORMANCE            STATUS
─────────────────────────────────
□ First load < 3s         ___
□ No render lag           ___
□ Smooth scrolling        ___
□ Bundle size < 500KB     ___

SECURITY               STATUS
─────────────────────────────────
□ No exposed keys         ___
□ Input validated         ___
□ Rate limiting           ___
□ Error not exposed       ___

CODE QUALITY           STATUS
─────────────────────────────────
□ No TypeScript errors    ___
□ No ESLint warnings      ___
□ Components documented   ___
□ README updated          ___
```

---

## 📚 Quick Reference

### Cursor Prompts hay dùng nhất

```bash
# Debug lỗi
"File này đang có lỗi: [paste error]. 
Giải thích nguyên nhân và fix, đừng thay đổi logic khác."

# Optimize
"Optimize component này cho performance. 
Chỉ thêm memo/callback khi thực sự cần, giải thích why."

# Add feature
"Thêm [feature] vào component này. 
Giữ nguyên code hiện tại, chỉ thêm phần mới. 
TypeScript strict, dùng existing patterns."

# Refactor
"Refactor function này để dễ đọc hơn. 
Logic không thay đổi, chỉ improve clarity."
```

### Shortcuts Cursor quan trọng

| Shortcut | Action |
|----------|--------|
| `Ctrl+L` | Mở Chat (complex tasks) |
| `Ctrl+K` | Inline Edit (quick fixes) |
| `Ctrl+I` | Composer (multi-file edit) |
| `Tab` | Accept autocomplete |
| `Esc` | Reject autocomplete |
| `Ctrl+Shift+L` | Add file to chat context |

### Common Errors & Quick Fixes

| Error | Nguyên nhân | Fix |
|-------|-------------|-----|
| `useChat is not a function` | Import sai | `import { useChat } from 'ai/react'` |
| Streaming không hoạt động | Thiếu `runtime = 'edge'` | Thêm vào route.ts |
| CORS error | API call từ wrong origin | Kiểm tra API URL |
| Hydration error | Server/Client mismatch | Kiểm tra `use client` |
| Messages không persist | localStorage key sai | Log key name |
| Rate limit 429 | Spam requests | Implement debounce |

---

> **🎯 Remember:** Vibe coding không phải là code ẩu — mà là code *nhanh và có chủ đích*. Checklist này là guardrail, không phải prison. Adapt nó theo project của bạn.
> 
> **⚡ Golden Rule:** Mỗi session Cursor = 1 mục tiêu rõ ràng → Review ngay → Commit nhỏ thường xuyên → Không để debt tích lũy.

---

*Cập nhật lần cuối: 2025 · Stack: Next.js 14 · Vercel AI SDK v3 · shadcn/ui*