# AI Coding Workflow Templates - Next.js & React

> Bộ template prompt chuẩn cho workflow phát triển với Next.js và React.
> Copy từng template, điền thông tin vào các `[placeholder]`, xóa phần hướng dẫn in nghiêng trước khi dùng.

---

## Mục lục

- [Template 1: Khởi động Feature Mới](#template-1-khởi-động-feature-mới)
- [Template 2: Tạo Component React/TypeScript](#template-2-tạo-component-reacttypescript)
- [Template 3: Tạo Custom Hook](#template-3-tạo-custom-hook)
- [Template 4: Review Code - Tìm Bugs](#template-4-review-code---tìm-bugs)
- [Template 5: Refactor & Thêm TypeScript](#template-5-refactor--thêm-typescript)

---

## Template 1: Khởi động Feature Mới

```
# Yêu cầu khởi động feature mới

## 📋 Project Context
- Framework: [Next.js 14 / Next.js 15]
- Package manager: [npm / yarn / pnpm]
- Styling: [Tailwind CSS / CSS Modules / Styled Components]
- State management: [Zustand / Redux / Context API / Jotai]
- Các thư viện quan trọng đang dùng: [ví dụ: React Query, Zod, React Hook Form]
- Cấu trúc folder hiện tại:
  [
    src/
      app/
      components/
      hooks/
      lib/
      types/
  ]

## 🎯 Mục tiêu
Tôi cần xây dựng feature: [Tên feature]

Mô tả chi tiết:
[Mô tả feature cần làm, user có thể làm gì với feature này]

Các màn hình / trang liên quan:
- [Trang 1: mô tả ngắn]
- [Trang 2: mô tả ngắn]

## 📦 Data Format
Dữ liệu đầu vào (từ API hoặc props):
[
  Paste schema / interface / JSON mẫu vào đây
]

Dữ liệu đầu ra cần hiển thị:
[Mô tả những gì cần render ra UI]

## ✅ Yêu cầu Output
Hãy tạo cho tôi:
1. Danh sách các file cần tạo (với đường dẫn đầy đủ)
2. Danh sách các TypeScript interface/type cần định nghĩa
3. Kế hoạch chia component (component tree)
4. Các custom hook cần tạo
5. Outline code cho file chính (chưa cần implement đầy đủ)

Lưu ý:
- Không viết full code ngay, chỉ cần plan và scaffold
- Giữ đúng cấu trúc folder đã có
- [Lưu ý thêm nếu có]
```

### ✏️ Ví dụ điền sẵn — Feature: Giỏ hàng (Shopping Cart)

```
# Yêu cầu khởi động feature mới

## 📋 Project Context
- Framework: Next.js 14
- Package manager: pnpm
- Styling: Tailwind CSS
- State management: Zustand
- Các thư viện quan trọng đang dùng: React Query, Zod, React Hook Form
- Cấu trúc folder hiện tại:
  src/
    app/
    components/
      ui/
    hooks/
    stores/
    lib/
    types/

## 🎯 Mục tiêu
Tôi cần xây dựng feature: Giỏ hàng (Shopping Cart)

Mô tả chi tiết:
Người dùng có thể thêm sản phẩm vào giỏ hàng, thay đổi số lượng,
xóa sản phẩm, và xem tổng tiền. Giỏ hàng được lưu vào localStorage
và sync lên server khi user đã đăng nhập.

Các màn hình / trang liên quan:
- Trang sản phẩm: nút "Thêm vào giỏ"
- Sidebar giỏ hàng: hiện overlay từ phải
- Trang checkout: hiện danh sách sản phẩm đã chọn

## 📦 Data Format
Dữ liệu đầu vào (từ API):
{
  "id": "prod_123",
  "name": "Áo thun basic",
  "price": 250000,
  "image": "https://...",
  "stock": 10,
  "variants": [
    { "id": "var_1", "size": "M", "color": "Trắng" }
  ]
}

Dữ liệu đầu ra cần hiển thị:
- Danh sách sản phẩm trong giỏ (ảnh, tên, size, số lượng, giá)
- Tổng số sản phẩm (badge trên icon giỏ hàng)
- Tổng tiền (có format tiền VNĐ)

## ✅ Yêu cầu Output
Hãy tạo cho tôi:
1. Danh sách các file cần tạo (với đường dẫn đầy đủ)
2. Danh sách các TypeScript interface/type cần định nghĩa
3. Kế hoạch chia component (component tree)
4. Các custom hook cần tạo
5. Outline code cho file chính (chưa cần implement đầy đủ)

Lưu ý:
- Không viết full code ngay, chỉ cần plan và scaffold
- Giữ đúng cấu trúc folder đã có
- Zustand store phải support persist middleware cho localStorage
```

---

## Template 2: Tạo Component React/TypeScript

```
# Yêu cầu tạo Component React/TypeScript

## 🏷️ Tên Component
[ComponentName]

Mục đích: [Mô tả ngắn component này làm gì, dùng ở đâu]

## 🔌 Props Interface
Các props cần có:

| Prop | Type | Required | Default | Mô tả |
|------|------|----------|---------|-------|
| [propName] | [type] | [yes/no] | [default] | [mô tả] |
| [propName] | [type] | [yes/no] | [default] | [mô tả] |

Hoặc paste interface TypeScript nếu đã có:
[
  interface Props {
    // paste vào đây
  }
]

## ⚙️ Behavior (Hành vi)
Trạng thái nội bộ (internal state):
- [State 1: mô tả]
- [State 2: mô tả]

Các sự kiện / interaction:
- Khi [hành động]: thì [kết quả]
- Khi [hành động]: thì [kết quả]

Side effects:
- [Effect 1 nếu có]

## 🚧 Constraints (Ràng buộc)
- [ ] Phải là Client Component / Server Component
- [ ] Phải accessible (ARIA labels, keyboard navigation)
- [ ] Phải responsive: [mobile-first / breakpoints cụ thể]
- [ ] Không dùng thư viện ngoài (ngoài những cái đã có)
- [ ] Phải handle loading state
- [ ] Phải handle error state
- [ ] Phải handle empty state
- [Thêm ràng buộc khác]

## 🎨 Styling
Styling approach: [Tailwind CSS / CSS Modules / inline]

Mô tả giao diện:
[Mô tả hoặc paste Figma spec / mockup text vào đây]

Các class / token quan trọng cần dùng:
- [class/token 1]
- [class/token 2]

Behavior responsive:
- Mobile: [mô tả]
- Tablet: [mô tả]  
- Desktop: [mô tả]
```

### ✏️ Ví dụ điền sẵn — Component: ProductCard

```
# Yêu cầu tạo Component React/TypeScript

## 🏷️ Tên Component
ProductCard

Mục đích: Hiển thị thông tin tóm tắt của một sản phẩm trong trang
danh sách, hỗ trợ thêm vào giỏ hàng nhanh khi hover.

## 🔌 Props Interface
Các props cần có:

| Prop | Type | Required | Default | Mô tả |
|------|------|----------|---------|-------|
| product | Product | yes | — | Object sản phẩm |
| onAddToCart | (id: string) => void | yes | — | Callback thêm giỏ |
| isInCart | boolean | no | false | Đã trong giỏ chưa |
| priority | boolean | no | false | LCP image priority |

Interface TypeScript:
interface Product {
  id: string;
  name: string;
  price: number;
  originalPrice?: number;
  image: string;
  slug: string;
  rating: number;
  reviewCount: number;
  badge?: "new" | "sale" | "hot";
}

## ⚙️ Behavior (Hành vi)
Trạng thái nội bộ:
- isHovered: boolean — hiển thị nút "Thêm vào giỏ"
- isAdding: boolean — loading state khi đang thêm vào giỏ

Các sự kiện / interaction:
- Khi hover vào card: hiện overlay với nút "Thêm vào giỏ"
- Khi click nút "Thêm vào giỏ": set isAdding = true, gọi onAddToCart
- Khi isInCart = true: đổi nút thành "Đã trong giỏ" (disabled)
- Khi click vào ảnh hoặc tên: navigate đến /san-pham/[slug]

Side effects:
- Không có

## 🚧 Constraints (Ràng buộc)
- [x] Phải là Client Component (vì có hover state)
- [x] Phải accessible (aria-label cho nút icon)
- [x] Phải responsive: mobile 2 cột, desktop 4 cột (grid do parent)
- [x] Chỉ dùng Tailwind CSS, không thêm thư viện
- [x] Phải handle loading state (skeleton khi isAdding)
- [x] Dùng Next.js Image cho ảnh sản phẩm

## 🎨 Styling
Styling approach: Tailwind CSS

Mô tả giao diện:
- Card bo góc 12px, shadow nhẹ, background trắng
- Ảnh sản phẩm tỉ lệ 1:1, object-cover
- Badge (new/sale/hot) ở góc trên trái ảnh
- Tên sản phẩm: 2 dòng, text-sm font-medium
- Giá: text-primary font-bold, giá gốc gạch ngang text-gray-400
- Rating: 5 sao nhỏ màu vàng + số review

Behavior responsive:
- Mobile: width 100% trong grid 2 cột
- Desktop: width 100% trong grid 4 cột
```

---

## Template 3: Tạo Custom Hook

```
# Yêu cầu tạo Custom Hook

## 🪝 Tên Hook
use[HookName]

Mục đích: [Mô tả hook này làm gì, giải quyết vấn đề gì]

Sẽ được dùng tại: [Component / page nào sẽ dùng hook này]

## 📥 Input Parameters
| Parameter | Type | Required | Default | Mô tả |
|-----------|------|----------|---------|-------|
| [param] | [type] | [yes/no] | [default] | [mô tả] |

## 🗂️ State cần quản lý
| State | Type | Giá trị ban đầu | Mô tả |
|-------|------|-----------------|-------|
| [stateName] | [type] | [initialValue] | [mô tả] |

## ⚡ Actions (Các hàm export ra)
| Action | Signature | Mô tả |
|--------|-----------|-------|
| [actionName] | ([params]): [returnType] | [mô tả] |

## 📤 Return Value
Hook trả về object với:
{
  // State
  [stateName]: [type],       // [mô tả]
  
  // Derived values  
  [derivedValue]: [type],    // [mô tả]
  
  // Actions
  [actionName]: [signature], // [mô tả]
}

## 🚧 Constraints (Ràng buộc)
- [ ] Phải cleanup effect khi unmount
- [ ] Phải handle race conditions (nếu có async)
- [ ] Phải memoize [function/value] bằng useCallback/useMemo
- [ ] Không gọi API trực tiếp (dùng service layer)
- [ ] Phải có error handling
- [ ] [Ràng buộc khác]

## 📎 Context thêm
Các hook/utility liên quan đang có trong project:
[Ví dụ: useToast, fetcher, apiClient...]

Type/Interface liên quan:
[Paste types liên quan vào đây]
```

### ✏️ Ví dụ điền sẵn — Hook: useCart

```
# Yêu cầu tạo Custom Hook

## 🪝 Tên Hook
useCart

Mục đích: Quản lý toàn bộ logic giỏ hàng — thêm, xóa, cập nhật số
lượng, tính tổng tiền. Sync với Zustand store và persist localStorage.

Sẽ được dùng tại: CartSidebar, ProductCard, CheckoutPage

## 📥 Input Parameters
Không có input parameter (lấy thẳng từ Zustand store)

## 🗂️ State cần quản lý
| State | Type | Giá trị ban đầu | Mô tả |
|-------|------|-----------------|-------|
| items | CartItem[] | [] | Danh sách sản phẩm trong giỏ |
| isOpen | boolean | false | Sidebar giỏ hàng có đang mở không |
| isLoading | boolean | false | Đang sync với server |

## ⚡ Actions
| Action | Signature | Mô tả |
|--------|-----------|-------|
| addItem | (product: Product, quantity: number) => void | Thêm sản phẩm, nếu đã có thì cộng số lượng |
| removeItem | (itemId: string) => void | Xóa 1 sản phẩm khỏi giỏ |
| updateQuantity | (itemId: string, qty: number) => void | Cập nhật số lượng, qty=0 thì xóa |
| clearCart | () => void | Xóa toàn bộ giỏ hàng |
| openCart | () => void | Mở sidebar |
| closeCart | () => void | Đóng sidebar |

## 📤 Return Value
Hook trả về object với:
{
  // State
  items: CartItem[],
  isOpen: boolean,
  isLoading: boolean,
  
  // Derived values
  totalItems: number,     // tổng số lượng sản phẩm
  totalPrice: number,     // tổng tiền chưa format
  isEmpty: boolean,       // giỏ có trống không
  
  // Actions
  addItem: (product: Product, quantity: number) => void,
  removeItem: (itemId: string) => void,
  updateQuantity: (itemId: string, qty: number) => void,
  clearCart: () => void,
  openCart: () => void,
  closeCart: () => void,
}

## 🚧 Constraints
- [x] Phải memoize totalItems, totalPrice bằng useMemo
- [x] Phải memoize tất cả actions bằng useCallback
- [x] updateQuantity với qty <= 0 phải tự động gọi removeItem
- [x] addItem phải check stock trước khi thêm, throw error nếu hết hàng
- [x] Không gọi API trực tiếp trong hook (dùng cartService)

## 📎 Context thêm
Zustand store đã có: useCartStore với persist middleware
Types liên quan:
interface CartItem {
  id: string;
  productId: string;
  name: string;
  price: number;
  quantity: number;
  image: string;
  variantId?: string;
  variantLabel?: string;
}
```

---

## Template 4: Review Code - Tìm Bugs

```
# Yêu cầu Review Code

## 📌 Thông tin code
Ngôn ngữ / Framework: [TypeScript + React / Next.js / ...]
File path: [src/...]
Mục đích của đoạn code: [Mô tả ngắn code này làm gì]

## 💻 Code cần review

[PASTE CODE VÀO ĐÂY]

## 🔍 Yêu cầu review

Hãy **CHỈ PHÂN TÍCH và LIỆT KÊ**, không sửa code.
Trả lời theo đúng các mục sau:

### 1. 🐛 Bugs (Lỗi thực sự)
Liệt kê các lỗi sẽ gây crash hoặc hành vi sai:
- Dòng [số dòng]: [mô tả lỗi] — [giải thích tại sao đây là lỗi]

### 2. 🌊 Edge Cases (Trường hợp biên)
Liệt kê các trường hợp chưa được xử lý:
- [Trường hợp]: [điều gì sẽ xảy ra nếu không handle]

### 3. ⚡ Performance Issues
Liệt kê các vấn đề về hiệu năng:
- Dòng [số dòng]: [vấn đề] — [impact ước tính]

### 4. 🔐 Security Issues (nếu có)
Liệt kê các vấn đề bảo mật:
- [Vấn đề]: [giải thích rủi ro]

### 5. 📊 Tóm tắt mức độ nghiêm trọng
| Mục | Số lượng | Mức độ ưu tiên |
|-----|----------|----------------|
| Bugs | ? | Critical / High / Medium |
| Edge Cases | ? | High / Medium / Low |
| Performance | ? | High / Medium / Low |

## ⛔ Không làm
- Không viết code sửa lỗi
- Không refactor
- Không thêm tính năng mới
- Chỉ phân tích và giải thích
```

### ✏️ Ví dụ điền sẵn — Review hook useProductList

```
# Yêu cầu Review Code

## 📌 Thông tin code
Ngôn ngữ / Framework: TypeScript + React
File path: src/hooks/useProductList.ts
Mục đích của đoạn code: Fetch danh sách sản phẩm với phân trang,
filter theo category và search term

## 💻 Code cần review

import { useState, useEffect } from 'react'
import { fetchProducts } from '@/lib/api'

export function useProductList(category: string) {
  const [products, setProducts] = useState([])
  const [loading, setLoading] = useState(false)
  const [search, setSearch] = useState('')
  const [page, setPage] = useState(1)

  useEffect(() => {
    setLoading(true)
    fetchProducts({ category, search, page })
      .then(data => {
        setProducts(data.items)
        setLoading(false)
      })
  }, [category, search, page])

  const loadMore = () => {
    setPage(page + 1)
  }

  const filteredProducts = products.filter(p => 
    p.name.includes(search)
  )

  return { products: filteredProducts, loading, setSearch, loadMore }
}

## 🔍 Yêu cầu review

Hãy CHỈ PHÂN TÍCH và LIỆT KÊ, không sửa code.
Trả lời theo đúng các mục sau:

### 1. 🐛 Bugs
### 2. 🌊 Edge Cases
### 3. ⚡ Performance Issues
### 4. 🔐 Security Issues (nếu có)
### 5. 📊 Tóm tắt mức độ nghiêm trọng

## ⛔ Không làm
- Không viết code sửa lỗi
- Không refactor
- Chỉ phân tích và giải thích
```

---

## Template 5: Refactor & Thêm TypeScript

```
# Yêu cầu Refactor / Thêm TypeScript

## 🎯 Mục tiêu refactor
Chọn tất cả mục tiêu áp dụng:

- [ ] Thêm TypeScript types/interfaces đầy đủ (từ JS hoặc TS thiếu type)
- [ ] Tách component lớn thành các component nhỏ hơn
- [ ] Tách logic ra custom hook
- [ ] Cải thiện performance (memo, callback, lazy load)
- [ ] Cải thiện readability (đặt tên rõ hơn, tách hàm)
- [ ] Xóa code thừa / dead code
- [ ] Thêm error boundary / error handling
- [ ] Chuẩn hóa theo pattern đang dùng trong project
- [ ] Mục tiêu khác: [mô tả]

## 💻 Code cần refactor

[PASTE CODE VÀO ĐÂY]

## 📎 Context bổ sung
Pattern / convention đang dùng trong project:
[Mô tả hoặc paste ví dụ một file tương tự trong project]

Types đã có sẵn (không cần tạo lại):
[Paste types liên quan]

## 🚧 Constraints — KHÔNG thay đổi những điều sau

### Logic & Behavior
- [ ] Không đổi business logic
- [ ] Không đổi output / return value của function/hook
- [ ] Không đổi tên props public (breaking change)
- [ ] Không đổi API calls (endpoint, method, params)
- [Thêm ràng buộc cụ thể nếu có]

### Technical
- [ ] Không thêm thư viện mới
- [ ] Giữ nguyên file path (không di chuyển file)
- [ ] Không đổi tên export (vì đang được import ở nhiều nơi)
- [ ] Tương thích với [React version / Next.js version]

## ✅ Yêu cầu output
1. Code sau khi refactor (đầy đủ, có thể chạy ngay)
2. Danh sách những gì đã thay đổi (bullet points ngắn gọn)
3. Danh sách những gì KHÔNG thay đổi (để confirm đúng constraints)
4. Ghi chú nếu phát hiện vấn đề khác cần xử lý riêng
```

### ✏️ Ví dụ điền sẵn — Refactor ProductList component từ JS sang TS

```
# Yêu cầu Refactor / Thêm TypeScript

## 🎯 Mục tiêu refactor
- [x] Thêm TypeScript types/interfaces đầy đủ (từ JS sang TS)
- [x] Tách logic fetch ra custom hook
- [x] Cải thiện performance (memo, callback)
- [x] Xóa code thừa / dead code

## 💻 Code cần refactor

// ProductList.jsx — hiện đang là JavaScript thuần
import { useState, useEffect } from 'react'
import axios from 'axios'
import ProductCard from './ProductCard'

export default function ProductList({ category, onSelect }) {
  const [data, setData] = useState(null)
  const [loading, setLoading] = useState(false)
  const [error, setError] = useState(null)
  const [selected, setSelected] = useState([])

  useEffect(() => {
    setLoading(true)
    axios.get('/api/products', { params: { category } })
      .then(res => {
        setData(res.data)
        setLoading(false)
      })
      .catch(err => {
        setError(err)
        setLoading(false)
      })
  }, [category])

  const handleSelect = (product) => {
    const exists = selected.find(p => p.id === product.id)
    if (exists) {
      setSelected(selected.filter(p => p.id !== product.id))
    } else {
      setSelected([...selected, product])
    }
    onSelect(selected) // bug: dùng state cũ
  }

  // hàm này không dùng ở đâu
  const formatPrice = (price) => {
    return price.toLocaleString('vi-VN') + 'đ'
  }

  if (loading) return <div>Loading...</div>
  if (error) return <div>Error!</div>

  return (
    <div className="grid grid-cols-4 gap-4">
      {data && data.map(product => (
        <ProductCard
          key={product.id}
          product={product}
          isSelected={!!selected.find(p => p.id === product.id)}
          onClick={() => handleSelect(product)}
        />
      ))}
    </div>
  )
}

## 📎 Context bổ sung
Pattern đang dùng: Custom hooks để fetch data, đặt trong src/hooks/
Types đã có sẵn:
interface Product {
  id: string;
  name: string;
  price: number;
  image: string;
  category: string;
}

## 🚧 Constraints — KHÔNG thay đổi những điều sau

### Logic & Behavior
- [x] Không đổi business logic của handleSelect (toggle selection)
- [x] Không đổi props: category và onSelect (tên và kiểu)
- [x] Không đổi grid layout (grid-cols-4)
- [x] Không đổi API endpoint /api/products

### Technical
- [x] Không thêm thư viện mới (giữ axios, không đổi sang fetch)
- [x] Giữ nguyên file path src/components/ProductList
- [x] Không đổi tên export default ProductList

## ✅ Yêu cầu output
1. Code sau khi refactor (đầy đủ, có thể chạy ngay)
2. Danh sách những gì đã thay đổi
3. Danh sách những gì KHÔNG thay đổi
4. Ghi chú nếu phát hiện vấn đề khác
```

---

## 📌 Ghi chú sử dụng

### Thứ tự workflow gợi ý

```
Feature mới
    │
    ▼
[Template 1] Khởi động → lên plan, scaffold files
    │
    ▼
[Template 2] Tạo Components → từng component theo plan
    │
    ▼
[Template 3] Tạo Custom Hooks → logic riêng biệt
    │
    ▼
[Template 4] Review Code → tìm bugs trước khi merge
    │
    ▼
[Template 5] Refactor → clean up, thêm types
```

### Tips sử dụng hiệu quả

| Tip | Mô tả |
|-----|-------|
| 🎯 Một prompt, một việc | Đừng gộp nhiều yêu cầu trong một prompt |
| 📋 Luôn có context | Paste types/interfaces liên quan để AI hiểu đúng |
| ⛔ Rõ ràng về constraints | Phần "không làm" giúp tránh AI tự ý thay đổi |
| 🔄 Iterate từng bước | Dùng Template 1 để plan, rồi mới dùng Template 2, 3 |
| 📎 Review trước merge | Template 4 nên chạy với mọi file quan trọng |

---

*Cập nhật templates này theo convention của từng project cụ thể.*