Bạn đang cần gì?
Chọn một việc bên dưới. Mỗi việc là một lộ trình ngắn — làm theo thứ tự là được.
Ba lộ trình
Không chắc bắt đầu từ đâu? Chọn việc đầu tiên — nó dạy bạn gọi đúng tên mọi thứ trên màn hình, và dùng được ngay trong tin nhắn tiếp theo bạn gửi cho AI.
- Bấm vào bất kỳ phần nào của webapp mẫu bên dưới
- Panel bên phải hiện tên chuẩn và câu feedback mẫu
- Bấm Copy rồi dán thẳng vào tin nhắn gửi AI
Thêm
Dùng bàn phím: bấm Tab để đi qua từng thành phần, Enter để chọn.
Hoặc chọn nhanh từ danh sách:
Vinamilk — Tết 2027
Offline cut v4 · Delivery 12.09.2026
Shot list
| Shot ▾ | Stage | Assignee | Trạng thái | |
|---|---|---|---|---|
| SH_012 | Comp | NLTP |
Approved | |
| SH_013 | Roto | HV |
In review | |
| SH_014 | Cleanup | MQ |
Retake | |
| SH_015 | — | ? |
Chưa gán |
Ghi chú delivery
Bản render gần đây
Công thức câu feedback chính xác
Vấn đề lớn nhất khi feedback UI là Claude không biết bạn đang nói tới chỗ nào. Dùng công thức 5 phần này thì gần như không bao giờ sửa nhầm.
3 chiều để định vị
| Chiều | Cách nói |
|---|---|
| Khu vực | sidebar / top bar / content area / right panel / footer / modal |
| Thành phần | button, badge, chip, card, table row, input, tab, toast… |
| Trạng thái | default, hover, active, focus, selected, disabled, loading, empty, error |
Nói đủ 3 chiều = Claude sửa đúng dòng code ngay lần đầu. Ví dụ: "table row ở trạng thái hover trong card 'Shot list'".
Từ vựng chỉnh sửa — nói cái này thay vì "nhìn kỳ kỳ"
| Muốn nói | Thuật ngữ |
|---|---|
| padding | khoảng trống bên trong viền của một thành phần |
| margin | khoảng trống bên ngoài, giữa thành phần này với thành phần khác |
| gap / spacing | khoảng cách đều giữa các item trong một nhóm |
| border-radius | độ bo góc |
| contrast | độ tương phản chữ/nền — "chữ xám quá đọc không ra" |
| hierarchy | thứ tự ưu tiên thị giác — "cái quan trọng nhất phải nổi nhất" |
| alignment | căn lề — "3 cột này không thẳng hàng nhau" |
| density | độ dày đặc thông tin — "làm compact hơn / thoáng hơn" |
| affordance | nhìn là biết bấm được — "cái này không giống nút bấm" |
| z-index / layer | lớp chồng lên nhau — "modal bị chìm dưới header" |
| above the fold | phần thấy được mà không cần cuộn |
| viewport | vùng màn hình đang nhìn thấy |
| breakpoint | mốc kích thước màn hình để layout đổi (mobile/tablet/desktop) |
| truncate / ellipsis | chữ dài bị cắt thành "…" |
Mẫu câu copy dùng ngay
Câu cuối cùng quan trọng nhất: luôn khoá phạm vi để tránh Claude "sửa luôn cả nhà".
1. Đọc dấu nhắc lệnh
khoa@macbook ~/Projects/review-app (main) $ ↑ máy của bạn ↑ ĐANG Ở THƯ MỤC NÀY ↑ nhánh git ↑ gõ lệnh sau dấu này
90% rắc rối của người mới là gõ lệnh sai thư mục. Chạy npm run dev ở ngoài thư mục dự án thì báo lỗi khó hiểu.
Không chắc thì gõ pwd xem đang ở đâu và ls xem có file package.json không — có nghĩa là đang đứng đúng chỗ.
2. Bộ lệnh sống còn
3. Ba phím tiết kiệm 80% thời gian gõ
Mũi tên lên ↑
Gọi lại lệnh vừa gõ. Bấm nhiều lần để đi ngược lịch sử. Không ai gõ lại npm run dev bằng tay cả.
Phím Tab
Gõ vài chữ đầu của tên thư mục rồi bấm Tab, nó tự điền nốt. Vừa nhanh vừa không gõ sai chính tả.
Ctrl + C
Dừng thứ đang chạy. Quan trọng nhất trong ba phím. Dùng khi muốn tắt app, hoặc khi lệnh bị treo.
4. Đọc những gì terminal in ra
Terminal in ra bốn loại thứ. Phân biệt được là hết hoảng:
| Bạn thấy | Nghĩa là | Làm gì |
|---|---|---|
| Chữ trắng/xám chạy đều | Nhật ký bình thường, app đang làm việc | Kệ nó |
| warning — chữ vàng | Cảnh báo, app vẫn chạy | Ghi nhận, không cần xử lý ngay. Đừng để tích tụ hàng trăm cái |
| error — chữ đỏ | Lỗi thật, thường app dừng luôn | Copy nguyên văn. Đọc dòng đầu tiên và dòng có tên file của bạn |
| "ready · Local: http://localhost:3000" rồi đứng im | App đang chạy đúng | Đây KHÔNG phải treo. Mở trình duyệt vào địa chỉ đó. Đừng đóng cửa sổ terminal |
npm run dev nghĩa là app đang chạy tốt và đang chờ bạn mở trình duyệt. Cửa sổ này phải để nguyên. Muốn gõ lệnh khác thì mở một cửa sổ terminal thứ hai.5. Dự án của bạn có sẵn lệnh gì
Mở file package.json ở gốc dự án, tìm mục scripts. Đó là danh sách lệnh riêng của dự án, chạy bằng npm run [tên]:
"scripts": {
"dev": "next dev", ← chạy bản phát triển ở máy, tự cập nhật khi sửa code
"build": "next build", ← dựng bản thật, đây là bước hay báo lỗi khi deploy
"start": "next start", ← chạy bản đã dựng
"lint": "next lint" ← soi lỗi cú pháp và code cẩu thả
}
npm run build ở máy trước khi deploy. Bản dựng nghiêm ngặt hơn bản chạy thử, nên lỗi sẽ hiện ra ở máy bạn thay vì hiện ra khi đã đẩy lên hosting.6. An toàn khi dùng terminal
Ba thứ có thể phá máy hoặc mất dữ liệu
rm -rf xoá vĩnh viễn, không có thùng rácGõ sai một dấu cách là xoá nhầm cả thư mục. Trước khi gõ, chạy pwd xác nhận đang đứng đúng chỗ.sudo là chạy với quyền cao nhấtNó bỏ qua mọi lớp bảo vệ của hệ điều hành. Với dự án web bạn gần như không bao giờ cần tới. Thấy hướng dẫn nào bảo dùng sudo cho npm thì nên nghi ngờ.1. Ba môi trường — đừng lẫn lộn
| Môi trường | Tương đương ở post | Ai thấy | Database |
|---|---|---|---|
| Local | Bàn dựng của bạn | Chỉ mình bạn | Database riêng, dữ liệu giả, xoá thoải mái |
| Preview / Staging | Bản gửi duyệt | Bạn + người bạn gửi link | Database staging, dữ liệu giống thật nhưng không phải thật |
| Production | Bản phát sóng | Toàn bộ người dùng | Dữ liệu thật — mất là mất luôn |
2. Chuỗi deploy hiện đại
bạn sửa code ở máy
│
├─ git push đẩy lên GitHub
│ │
│ ├─ hosting tự phát hiện có thay đổi
│ │
│ ├─ BUILD dựng bản thật ← lỗi cú pháp, lỗi kiểu dữ liệu hiện ở đây
│ ├─ TEST chạy kiểm thử ← fail thì DỪNG, không cho lên
│ │
│ ├─ đẩy lên nhánh phụ → URL PREVIEW riêng gửi khách xem trước
│ └─ đẩy lên nhánh main → PRODUCTION người dùng thật thấy ngay
│
└─ hỏng? rollback về bản trước trong khoảng 30 giây
Điểm hay nhất với người làm dịch vụ như bạn: mỗi nhánh được một URL riêng. Muốn cho khách xem thử một hướng giao diện mới thì tạo nhánh, đẩy lên, gửi link — bản chính không hề bị đụng tới. Đúng bằng workflow gửi cut cho khách duyệt.
3. Biến môi trường theo từng môi trường
Đây là nguyên nhân số một của "máy tôi chạy được mà lên mạng thì hỏng":
| Môi trường | Khoá nằm ở đâu | Sai lầm thường gặp |
|---|---|---|
| Local | File .env.local trên máy bạn | Không có gì — nhưng file này không bao giờ được commit |
| Preview | Nhập tay trong bảng điều khiển hosting | Quên nhập, hoặc trỏ nhầm vào database production |
| Production | Nhập tay trong bảng điều khiển hosting | Quên nhập → app chạy nhưng mọi thứ liên quan API đều undefined |
.env không tự đi theo khi deploy — đó chính là mục đích của nó. Mỗi lần thêm một biến mới ở máy, phải nhớ nhập tay vào hosting cho cả preview và production. Đổi biến xong phải deploy lại thì mới có hiệu lực.4. CI/CD — cái máy gác cổng
CI/CD là quy trình tự động chạy mỗi lần bạn đẩy code lên. Với vibe-coder giá trị lớn nhất của nó không phải tự động hoá — mà là chặn bạn deploy một bản hỏng, giống gate QC không cho file sai spec đi qua.
| Bước | Nó kiểm gì | Có bắt buộc không |
|---|---|---|
| Build | Code có dựng được thành bản chạy thật không | Bắt buộc — hosting tự làm sẵn |
| Type check | Kiểu dữ liệu có khớp không | Rất nên — bắt được nhiều lỗi trước khi người dùng gặp |
| Lint | Code có lỗi cú pháp hay cẩu thả không | Nên có |
| Test | Các luồng chính còn chạy đúng không | Nên có khi đã có người dùng thật |
| Kiểm tra thư viện lỗ hổng | Có thư viện nào đang dính lỗ hổng đã công bố không | Nên chạy hàng tháng |
5. Sáu mươi giây đầu khi production hỏng
Thứ tự này quan trọng. Người mới hay làm ngược lại và kéo dài thời gian app chết:
Rollback TRƯỚC, điều tra SAU
Đưa app về bản chạy được ngay lập tức. Hosting có nút hoàn tác về bản deploy trước, mất khoảng 30 giây. Đừng ngồi sửa code trong khi người dùng đang gặp lỗi.
Xác nhận đã hết lỗi
Tự mở app kiểm tra như người dùng thật, không tin vào bảng điều khiển.
Giờ mới đi tìm nguyên nhân
Xem log của hosting quanh thời điểm hỏng, và xem bản deploy vừa rồi đổi những gì. Không còn áp lực nên tìm chính xác hơn.
Sửa trên nhánh riêng, thử ở preview
Sửa xong đẩy lên nhánh phụ, mở URL preview kiểm tra kỹ, rồi mới gộp vào bản chính.
Ghi lại một dòng
Hỏng gì, vì sao, sửa thế nào. Ba tháng sau bạn sẽ cảm ơn chính mình.
6. Ba khái niệm về tên miền
Domain
Địa chỉ người ta gõ vào. Mua theo năm ở nhà đăng ký tên miền. Nhớ bật tự động gia hạn — hết hạn là mất trang.
DNS
Bảng chỉ đường từ tên miền tới server. Đổi xong có thể mất vài giờ mới lan khắp nơi — đừng hoảng khi chưa thấy ngay.
SSL / HTTPS
Mã hoá đường truyền. Vercel/Netlify tự cấp miễn phí. Không có ổ khoá là trình duyệt cảnh báo và người dùng bỏ đi.
7. Biết app hỏng trước khi khách nhắn tin
| Loại | Nó trả lời câu hỏi | Không có thì |
|---|---|---|
| Uptime monitor | App còn sống không? | App chết cả đêm mà sáng hôm sau mới biết |
| Error tracking (Sentry) | Có ai đang gặp lỗi không, lỗi gì, ở màn hình nào | Chỉ biết khi có người chịu khó phàn nàn — phần lớn họ im lặng rời đi |
| Log hosting | Chuyện gì đã xảy ra lúc đó | Không có bằng chứng để tìm nguyên nhân |
| Cảnh báo chi phí | Có gì đang đốt tiền bất thường không | Biết khi nhận hoá đơn |
8. Checklist ngày deploy đầu tiên
1. Lighthouse — chạy một nút ra bốn điểm số
Mở DevTools → tab Lighthouse → Analyze. Chạy ở chế độ ẩn danh để tiện ích trình duyệt không làm sai kết quả. Điểm dưới 50 là đỏ, 50–89 là vàng, từ 90 là xanh.
Performance
Tốc độ tải và phản hồi. Với app nhiều media thì đây thường là điểm thấp nhất, và cũng là điểm đáng sửa nhất.
Accessibility
Dễ sửa nhất trong bốn mục — phần lớn là thêm nhãn và sửa tương phản. Đạt 95 thường chỉ mất một buổi.
Best Practices
Bắt các lỗi cơ bản: dùng HTTPS chưa, ảnh sai tỉ lệ, thư viện có lỗ hổng, lỗi trong console.
SEO
Google có hiểu trang không. Quan trọng nếu bạn muốn người ta tìm thấy; không quan trọng với app nội bộ.
2. Ba chỉ số tốc độ thật sự quan trọng
| Chỉ số | Nghĩa dễ hiểu | Tốt | Kém |
|---|---|---|---|
| LCP | Bao lâu thì thấy được nội dung chính. Như thời gian từ lúc bấm play tới lúc có hình. | ≤ 2.5s | > 4s |
| INP | Bấm xong bao lâu thì có phản hồi. Đây là cảm giác "app này mượt hay ì". | ≤ 200ms | > 500ms |
| CLS | Nội dung có nhảy lung tung khi đang tải không. Như jump cut không mong muốn — người dùng bấm nhầm vì nút vừa nhảy chỗ. | ≤ 0.1 | > 0.25 |
3. Tám nguyên nhân chậm — xếp theo mức độ hay gặp
| Nguyên nhân | Cách sửa |
|---|---|
| Ảnh không nén, kích thước gốc — thủ phạm số một, đặc biệt với người làm media vì quen dùng file gốc | Xuất đúng kích thước hiển thị, dùng định dạng WebP hoặc AVIF, dùng component ảnh có sẵn của framework để nó tự tối ưu |
| Tải hết mọi ảnh ngay từ đầu | Lazy loading — ảnh ngoài màn hình chỉ tải khi cuộn tới |
| Font nặng, tải nhiều biến thể | Chỉ tải độ dày thật sự dùng, dùng font-display: swap để chữ hiện ngay bằng font tạm |
| Thư viện thừa | Xem thư viện nào nặng nhất, bỏ cái chỉ dùng một hàm nhỏ. Đây là lý do phải hỏi mỗi khi AI thêm thư viện |
| Gọi API tuần tự thay vì song song | Nếu ba lời gọi không phụ thuộc nhau thì cho chạy cùng lúc, thời gian bằng cái lâu nhất thay vì tổng ba cái |
| Truy vấn database không có index | Thêm index cho cột hay lọc. Trăm dòng thì không thấy gì, trăm nghìn dòng là treo |
| Lấy về nhiều dữ liệu hơn cần | Chỉ lấy cột cần dùng, phân trang thay vì tải hết một lượt |
| Video tự phát ở đầu trang | Đặt poster tĩnh, chỉ tải video khi người dùng bấm play |
4. Accessibility — tám điểm bạn tự kiểm được
Không cần chuyên gia. Ba cách kiểm nhanh: bấm Tab đi hết trang, chạy Lighthouse, phóng to trình duyệt lên 200%. Ngoài lý do đúng đắn, làm tốt phần này còn giúp SEO và là yêu cầu pháp lý ở nhiều thị trường.
5. Chi phí — biết mình đang trả tiền cho cái gì
| Dịch vụ | Tính tiền theo | Thứ dễ tăng vọt |
|---|---|---|
| Hosting | Lượng dữ liệu truyền đi, thời gian máy chạy, số phút build | Deploy liên tục cả ngày đốt phút build. Ảnh và video nặng đốt băng thông |
| Database | Dung lượng lưu, số kết nối đồng thời, lượng dữ liệu đọc ra | Truy vấn không index chạy trong vòng lặp |
| Lưu trữ file | Số GB lưu và số GB tải xuống | Phí tải xuống là bẫy lớn nhất với app video — lưu thì rẻ, cho người ta xem mới đắt |
| API của mô hình AI | Lượng chữ gửi đi và nhận về | Gửi cả file dài trong mỗi lần gọi. Vòng lặp lỗi gọi liên tục |
| Email, SMS | Số lượng gửi | Gửi lặp do lỗi logic |
1. Design token — LUT cho giao diện
Mỗi lần bạn bảo AI "chỗ này màu xám nhạt hơn tí", nó đặt một mã màu mới ngay tại chỗ đó. Làm 30 lần thì app có 30 sắc xám khác nhau, không cái nào giống cái nào — và muốn đổi tông toàn app thì phải sửa 30 chỗ.
Token là biến dùng chung. Định nghĩa một lần ở đầu, mọi nơi gọi tên biến. Đổi một dòng là đổi cả app — đúng nguyên lý bạn dùng LUT thay vì grade tay từng shot.
var(--accent). Muốn đổi tông: sửa 1 dòng, cả app đổi theo, không sót chỗ nào.Năm nhóm token cần có. Chỉ dùng giá trị trong thang, không chế số lẻ:
Spacing — thang 4px
4 · 8 · 12 · 16 · 24 · 32 · 48 · 64
Mọi padding, margin, gap phải là một trong các số này. Thấy 13px, 17px, 22px là dấu hiệu chắp vá.
Typography — 6 cỡ là đủ
12 · 14 · 16 · 20 · 24 · 32
Nhiều hơn 6 cỡ chữ là mất thứ bậc. Mỗi cỡ kèm một độ dày cố định.
Màu — đặt tên theo VAI TRÒ
--accent · --success · --warning · --danger · --text-muted
Đừng đặt --blue-500. Sau này đổi sang tông xanh lá thì tên biến thành nói dối.
Bo góc — 3 mức
--r-sm 6px · --r-md 10px · --r-full 99px
Trong một app chỉ nên có 2–3 độ bo. Mỗi component một kiểu là nhìn ra ngay.
Độ nổi — 3 tầng
--sh-1 card · --sh-2 dropdown · --sh-3 modal
Bóng đổ thể hiện thứ gì nổi trên thứ gì, không phải để trang trí.
Chuyển động — 2 tốc độ
--fast 120ms · --slow 240ms
Nhanh cho hover, chậm cho panel trượt. Trên 300ms là người dùng thấy ì.
Khai báo một lần ở đầu file CSS gốc:
:root {
/* màu — theo vai trò, không theo tên màu */
--bg: #0d0f13; --surface: #14171d;
--text: #e6e9ef; --text-muted: #9aa4b4;
--accent: #5b8cff; --danger: #ff5d5d;
--success: #3ecf8e; --warning: #f5b642;
/* khoảng cách — thang 4px, cấm số ngoài thang */
--sp-1: 4px; --sp-2: 8px; --sp-3: 12px; --sp-4: 16px;
--sp-5: 24px; --sp-6: 32px; --sp-7: 48px;
/* chữ */
--fs-xs: 12px; --fs-sm: 14px; --fs-md: 16px;
--fs-lg: 20px; --fs-xl: 24px; --fs-2xl: 32px;
/* bo góc và độ nổi */
--r-sm: 6px; --r-md: 10px; --r-full: 99px;
--sh-1: 0 1px 2px rgba(0,0,0,.4);
--sh-2: 0 4px 10px rgba(0,0,0,.5);
}
2. Ma trận 8 trạng thái — dấu hiệu rõ nhất của app pro
App vibe-code hầu như luôn chỉ có một trạng thái: bình thường, dữ liệu đầy đủ, mọi thứ suôn sẻ. Người dùng thật thì bấm khi đang tải, bấm khi không có quyền, mở màn hình chưa có dữ liệu, gõ sai định dạng. Bảng dưới là thứ bạn đưa cho AI để nó không quên. Bấm vào ô để đánh dấu đã làm:
Ô gạch chéo = không áp dụng cho loại component đó.
| Trạng thái | Khi nào xuất hiện | Hay bị quên vì |
|---|---|---|
| Default | Bình thường, không tương tác | — |
| Hover | Rê chuột lên | Không có thì người dùng không biết bấm được |
| Focus | Chọn bằng phím Tab | Bị xoá vì "viền xấu" — đây là lỗi accessibility nghiêm trọng |
| Active | Đang nhấn xuống | Không có thì cảm giác bấm bị "đơ" |
| Disabled | Chưa đủ điều kiện dùng | Làm mờ nhưng không nói LÝ DO bị khoá |
| Loading | Đang chờ server | Không có thì người dùng bấm 5 lần liên tiếp |
| Empty | Chưa có dữ liệu nào | Lúc dev luôn có dữ liệu mẫu nên không ai thấy |
| Error | Thao tác thất bại | Chỉ test đường đi thuận lợi |
3. Ngưỡng tối thiểu không được phá
Vùng bấm ≥ 44×44px
Icon nhìn 20px cũng được, nhưng vùng bấm phải đủ 44px. Đây là lý do nút của bạn "khó bấm trên điện thoại".
Tương phản chữ ≥ 4.5:1
Chữ xám nhạt trên nền tối trông sang nhưng nhiều người không đọc nổi. DevTools có sẵn công cụ đo — hover vào màu trong panel Styles.
Không xoá focus ring
Người không dùng chuột phải Tab để đi. Xoá viền focus là chặn họ hoàn toàn. Muốn đẹp thì thiết kế lại, đừng xoá.
Màu không phải tín hiệu duy nhất
Khoảng 8% nam giới không phân biệt đỏ-xanh lá. Trạng thái phải có thêm chữ hoặc icon, không chỉ đổi màu.
Chữ nhỏ nhất 12px
Dưới 12px là không đọc được trên điện thoại. Trên input, dưới 16px làm iPhone tự phóng to trang khi gõ.
Nút phá huỷ phải xác nhận
Xoá, huỷ, ghi đè — phải hỏi lại hoặc cho hoàn tác. Và đừng đặt cạnh nút thường dùng.
4. Sáu thứ phải giống nhau toàn app
Đây là danh sách để bạn tự soi app mình. Không đều một trong sáu thứ này là nhìn ra ngay dù không biết vì sao:
| Thứ | Kiểm bằng cách |
|---|---|
| Độ bo góc | Chụp màn hình 5 chỗ khác nhau, so bo góc có giống nhau không |
| Thang khoảng cách | Dùng DevTools soi padding vài component — có phải đều thuộc thang 4px không |
| Cỡ chữ | Đếm số cỡ chữ khác nhau trong app. Trên 6 là quá nhiều |
| Kích thước icon | Mọi icon cùng cấp phải cùng cỡ. Lệch 2px là mắt thấy |
| Chiều cao nút và input | Nút và ô nhập đứng cạnh nhau phải cùng chiều cao |
| Tốc độ chuyển động | Mọi hover cùng tốc độ. Chỗ nhanh chỗ chậm là cảm giác rời rạc |
1. Đọc diff — kỹ năng nền
Diff là bảng so sánh trước và sau. Dòng có dấu trừ là bị bỏ đi, dấu cộng là được thêm vào. Xem bằng git diff, hoặc trong Cursor/VS Code, hoặc trên GitHub.
--- a/components/ProjectCard.tsx +++ b/components/ProjectCard.tsx @@ -20,7 +20,12 @@ ← đang xem quanh dòng 20 export function ProjectCard({ project }) { - return <h3>{project.name}</h3> ← DÒNG BỊ BỎ ĐI + if (!project) return null ← DÒNG ĐƯỢC THÊM + return ( + <h3>{project.name ?? 'Chưa đặt tên'}</h3> + ) } (dòng không dấu = không đổi, chỉ để bạn biết ngữ cảnh)
Ba câu hỏi bắt buộc khi nhìn một diff, theo đúng thứ tự:
Nó có đụng thứ tôi không nhờ không?
Nhìn danh sách file ở đầu diff. Tôi nhờ sửa sidebar mà thấy 6 file lạ bị đổi là dấu hiệu cần hỏi lại ngay. Đây là câu hỏi bắt được nhiều tai nạn nhất.
Nó xoá cái gì không?
Dòng đỏ là thứ biến mất. Nếu có dòng đỏ mà bạn không hiểu tại sao phải xoá — hỏi. AI hay "dọn dẹp" mất thứ đang chạy tốt.
Nó thêm thư viện mới không?
Xem file package.json có trong diff không. Mỗi thư viện thêm vào là thêm rủi ro bảo mật, thêm dung lượng, thêm thứ phải cập nhật. Hỏi: có cách nào không cần thư viện này không?
2. Checklist 10 điểm — chạy mỗi lần AI sửa xong
3. Dấu hiệu code đang xuống cấp
Bạn không cần hiểu code vẫn nhận ra được những dấu hiệu này. Thấy là bảo AI dọn ngay, để lâu thì càng khó gỡ:
| Dấu hiệu | Vì sao đáng lo |
|---|---|
| Một hàm dài trên 100 dòng | Làm quá nhiều việc cùng lúc. Sửa một chỗ dễ vỡ chỗ khác. Bảo AI tách nhỏ theo từng việc. |
| Lồng nhau 4–5 tầng, thụt lề sâu như bậc thang | Logic quá rối, gần như chắc chắn có trường hợp chưa xử lý. Nhờ viết lại phẳng hơn. |
Tên biến data, data2, temp, x, handleClick2 | Dấu hiệu code viết vội, không ai đọc lại được — kể cả AI ở phiên sau. |
| Cùng một đoạn xuất hiện 3 lần trở lên | Sửa một chỗ quên hai chỗ kia là nguồn bug kinh điển. Gộp thành một chỗ dùng chung. |
| Số lạ nằm rải rác trong code (86400, 1024, 0.85) | Không ai biết số đó nghĩa gì kể cả bạn ba tuần sau. Phải đặt tên cho nó. |
| Bắt lỗi rồi bỏ trống, không làm gì | Lỗi bị nuốt im lặng — app hỏng mà không ai biết vì sao. Nguy hiểm nhất trong bảng này. |
any rải khắp nơi (TypeScript) | Tắt hết kiểm tra an toàn để cho qua build. Đang giấu lỗi chứ không sửa. |
| Comment dài giải thích một đoạn khó hiểu | Thường là dấu hiệu nên viết lại cho dễ hiểu, thay vì chú thích cho khó hiểu. |
Còn sót console.log, TODO, code bị chú thích để đó | Rác từ các lần thử. Dọn trước khi deploy. |
| File dài trên 500 dòng | Đến lúc tách. Vừa khó tìm, vừa làm AI tốn ngữ cảnh vô ích ở mỗi phiên. |
4. Nợ kỹ thuật — khi nào được nợ, khi nào phải trả
Nợ kỹ thuật là làm nhanh cho xong, biết là chưa chuẩn, tính sửa sau. Không phải lúc nào cũng xấu — vấn đề là nợ có ý thức hay nợ mà không biết mình đang nợ. Cứ ghi vào một file NO-KY-THUAT.md mỗi lần bạn cố tình chọn đường tắt.
1. Bốn khái niệm là đủ dùng
Bảng (table)
Mỗi loại đối tượng một bảng. Đặt tên danh từ số nhiều: users, projects, comments.
Cột (column)
Mỗi thuộc tính một cột, có kiểu cố định: chữ, số, ngày, đúng/sai.
Hàng (row)
Một người dùng cụ thể, một project cụ thể. Bảng có bao nhiêu hàng là có bấy nhiêu bản ghi.
Khoá (key)
id là mã riêng của mỗi hàng. project_id nằm trong bảng khác là sợi dây trỏ ngược về bảng projects.
2. Ba loại quan hệ — nhận biết bằng tiếng Việt
Không cần lý thuyết. Đặt hai câu hỏi bằng tiếng Việt thường là ra ngay loại quan hệ và cách làm:
| Hai câu hỏi | Loại | Cách làm |
|---|---|---|
| Một project có nhiều comment? Có Một comment thuộc nhiều project? Không | Một–nhiều | Đặt cột project_id trong bảng comments. Phổ biến nhất, chiếm khoảng 80% trường hợp. |
| Một user tham gia nhiều project? Có Một project có nhiều user? Có | Nhiều–nhiều | Cần bảng trung gian project_members chứa user_id + project_id + vai trò. Đây là chỗ vibe-code hay làm sai nhất. |
| Một user có một profile? Có Một profile thuộc một user? Có | Một–một | Hiếm khi cần tách. Thường gộp luôn vào một bảng cho đơn giản. |
3. Schema mẫu — app review cut cho khách
Đọc thử để thấy một schema đủ dùng trông ra sao. Chú ý mọi bảng đều có id, created_at, và bảng trung gian ở cuối:
users id uuid khoá chính email text duy nhất full_name text created_at timestamp projects id uuid name text owner_id uuid → users.id một user có nhiều project status text 'offline' | 'online' | 'delivered' deadline date created_at timestamp deleted_at timestamp null = chưa xoá (xoá mềm) videos id uuid project_id uuid → projects.id một project có nhiều bản cut version int v1, v2, v3… storage_path text ĐƯỜNG DẪN file, không phải file duration_ms int created_at timestamp comments id uuid video_id uuid → videos.id author_id uuid → users.id timecode_ms int comment gắn vào giây thứ mấy body text resolved boolean created_at timestamp project_members ← BẢNG TRUNG GIAN cho quan hệ nhiều–nhiều project_id uuid → projects.id user_id uuid → users.id role text 'owner' | 'editor' | 'viewer' khoá chính = (project_id, user_id) — một người chỉ vào một lần
4. Mười quy tắc không cần suy nghĩ, cứ theo
| Quy tắc | Lý do |
|---|---|
| Tên bảng số nhiều, chữ thường, nối bằng gạch dưới | project_members chứ không phải ProjectMember. Nhất quán để không bao giờ phải đoán. |
Mọi bảng có id, created_at, updated_at | Ba cột này về sau luôn cần tới. Thêm sau khi đã có dữ liệu thì phiền. |
| Không lưu thứ tính được | Đừng lưu cột total_comments nếu đếm được. Lưu rồi là có ngày số lưu và số thật lệch nhau. |
| Tiền lưu bằng số nguyên, đơn vị nhỏ nhất | Lưu 150000 (đồng), không lưu 150.0. Số thực làm tròn sai và kế toán sẽ tìm bạn. |
| Thời gian lưu theo UTC, đổi múi giờ lúc hiển thị | Không thì app có khách ở nước ngoài là lệch ngày ngay. |
| Không lưu file trong database | Lưu file lên dịch vụ lưu trữ, database chỉ giữ đường dẫn. Cực kỳ quan trọng với app media. |
| Trạng thái dùng chuỗi có nghĩa, không dùng số | 'approved' đọc là hiểu. status = 3 thì phải đi tra bảng. |
Xoá mềm bằng deleted_at | Người dùng bấm nhầm là chuyện thường. Khôi phục được thì bạn đỡ một đêm mất ngủ. |
| Cột dùng để tìm kiếm thì thêm index | Không có index, 100 dòng vẫn nhanh, 100 nghìn dòng là treo. Thêm cho các cột hay lọc theo. |
| Tạo bảng mới là bật RLS ngay trong cùng một lượt | Để sau là quên. Bảng không có RLS là bảng công khai cho cả internet. |
5. Bốn cạm bẫy vibe-code hay dính
Nhận ra sớm thì sửa dễ
F12 hoặc Ctrl+Shift+I (Windows) · Cmd+Option+I (Mac). Chuột phải vào bất kỳ chỗ nào trên trang → Inspect để mở thẳng vào đúng thành phần đó.5 tab cần biết — ánh xạ sang pipeline post
Elements
Xem cấu trúc HTML thật và CSS đang thực sự áp lên từng thành phần.
- Sửa thử trực tiếp, không lưu
- Xem box model padding/margin
- Biết class nào đang thắng
Console
Nơi mọi lỗi JavaScript hiện ra. Đỏ là lỗi, vàng là cảnh báo.
- Copy nguyên văn lỗi đưa cho AI
- Xem log do code in ra
Network
Mọi lời gọi ra server: gọi cái gì, gửi gì, nhận về gì, mất bao lâu.
- Chẩn đoán "dữ liệu không lên"
- Phát hiện khoá bị lộ
Application
Cookie, token đăng nhập, dữ liệu lưu trong trình duyệt.
- Xoá storage khi lỗi đăng nhập
- Kiểm tra token có tồn tại không
Lighthouse
Chấm điểm tốc độ, accessibility, SEO. Bấm một nút ra báo cáo.
- Chạy trước khi deploy
- Ưu tiên mục điểm thấp nhất
Device toolbar
Xem giao diện trên kích thước điện thoại, tablet.
Ctrl/Cmd+Shift+M- Test breakpoint thật
Siêu năng lực: thử trước, rồi mới nhờ AI sửa
Đây là kỹ thuật giá trị nhất trong cả tab này. Thay vì mô tả mơ hồ rồi chờ AI đoán, bạn tự chỉnh trong DevTools cho tới khi ưng mắt, rồi đưa con số chính xác cho AI. Một vòng là xong thay vì năm vòng.
Bấm biểu tượng mũi tên chọn phần tử
Ctrl/Cmd+Shift+C rồi click vào đúng chỗ muốn sửa trên trang. Panel Elements nhảy tới đúng dòng HTML đó.
Nhìn panel Styles bên phải
Đó là CSS thật đang áp. Thuộc tính bị gạch ngang nghĩa là đã bị luật khác đè lên. Cuộn xuống dưới cùng thấy sơ đồ box model: màu cam là margin, tím là padding.
Sửa thẳng trong DevTools
Click vào giá trị và gõ số mới, hoặc bấm phím mũi tên lên/xuống để tăng giảm từng đơn vị. Trang đổi ngay lập tức. Không có gì được lưu — reload là mất hết, cứ thử thoải mái.
Chốt con số rồi đưa cho AI
Khi ưng mắt, ghi lại giá trị đã thử. Giờ prompt của bạn có bằng chứng: không còn "nhìn chật quá" mà là "padding 8px chưa đủ, tôi thử 14px thì đẹp".
Network — chẩn đoán "dữ liệu không lên"
Mở tab Network, lọc Fetch/XHR, rồi thao tác lại trên trang. Hỏi ba câu theo đúng thứ tự:
Có gọi đi không?
Không thấy dòng nào xuất hiện = lỗi ở frontend, nút chưa gọi hàm. Sửa ở phía giao diện, không phải server.
Gọi đúng địa chỉ không?
Nhìn cột Name và Status. Nếu 404 thì URL sai hoặc route backend chưa tồn tại.
Trả về cái gì?
Click vào dòng đó → tab Payload xem bạn gửi gì đi, tab Response xem server trả gì về. Đây là nơi lỗi thật hiện nguyên hình.
Câu hỏi nào thì mở tab nào
| Bạn đang gặp | Mở tab | Tìm gì |
|---|---|---|
| Màn hình trắng trơn | Console | Dòng đỏ đầu tiên — thường là lỗi làm sập cả trang |
| Bấm nút không phản ứng | Console + Network | Có lỗi đỏ không, có request nào bắn đi không |
| Dữ liệu không hiện / hiện sai | Network | Response trả về gì, có đúng dữ liệu mong đợi không |
| Màu / khoảng cách sai | Elements | Panel Styles — luật nào đang thắng, có bị gạch ngang không |
| Đăng nhập rồi vẫn bị đá ra | Application | Cookie và localStorage — token còn không, hết hạn chưa |
| Trang tải chậm | Network + Lighthouse | File nào nặng nhất, request nào lâu nhất |
| Trên điện thoại bị vỡ layout | Device toolbar | Đổi kích thước tới khi vỡ, ghi lại con số đó |
| Chạy local ổn, lên mạng lỗi | Console + Network | Thường là biến môi trường chưa set trên hosting, hoặc CORS |
1. Lỗi đang nằm ở đâu
App có ba nơi sinh lỗi khác nhau. Mở nhầm chỗ là tìm cả buổi không thấy gì:
Console trình duyệt
Giao diện, nút bấm, hiển thị. Mở bằng F12.
- Màn hình trắng
- Bấm không ăn
- Giao diện vỡ
Terminal đang chạy app
Cửa sổ bạn gõ lệnh chạy app. Lỗi backend và lỗi build hiện ở đây.
- App không khởi động
- Lỗi 500
- Lỗi database
Log của hosting
Trong bảng điều khiển Vercel/Railway. Chạy local ổn mà live hỏng thì xem ở đây.
- Build failed
- Thiếu biến môi trường
2. Giải phẫu một thông báo lỗi
Lỗi trông dài và đáng sợ, nhưng chỉ có hai dòng quan trọng:
TypeError: Cannot read properties of undefined (reading 'name') ← DÒNG 1: LỖI GÌ at ProjectCard (components/ProjectCard.tsx:24:31) ← DÒNG 2: Ở ĐÂU (file của BẠN) at renderWithHooks (node_modules/react-dom/cjs/react-dom.js:16305) ← nhiễu, bỏ qua at mountIndeterminateComponent (node_modules/react-dom/...:20074) ← nhiễu, bỏ qua at beginWork (node_modules/react-dom/cjs/react-dom.js:21587) ← nhiễu, bỏ qua
node_modules đều là ruột thư viện — bỏ qua hết.Cannot read properties of undefined (reading 'name') tại ProjectCard dòng 24" = tại dòng 24, code đang cố lấy .name của một thứ không tồn tại. Thường là dữ liệu chưa tải xong, hoặc gọi sai tên trường.3. Đọc mã HTTP — lỗi của ai
Thấy trong tab Network. Con số đầu tiên cho biết ngay nên đi sửa phía nào:
| Mã | Nghĩa | Lỗi ở đâu | Làm gì |
|---|---|---|---|
| 200 / 201 | Thành công | — | Nếu vẫn sai thì lỗi nằm ở cách hiển thị dữ liệu, không phải ở gọi API |
| 400 | Dữ liệu gửi lên sai | Frontend | Xem tab Payload — thiếu trường hay sai định dạng |
| 401 | Chưa đăng nhập | Xác thực | Token thiếu hoặc hết hạn — kiểm tra Application tab |
| 403 | Đăng nhập rồi nhưng không có quyền | Phân quyền / RLS | Policy database đang chặn. Đây là dấu hiệu RLS đang hoạt động |
| 404 | Không tìm thấy | URL hoặc route | Sai đường dẫn, hoặc route backend chưa được tạo |
| 409 | Xung đột dữ liệu | Database | Thường do trùng giá trị phải là duy nhất, ví dụ email đã tồn tại |
| 422 | Đúng định dạng nhưng không hợp lệ | Frontend | Ví dụ email sai cú pháp, ngày trong quá khứ |
| 429 | Gọi quá nhiều | Rate limit | Bị chặn vì gọi liên tục — hoặc code đang lặp vô hạn |
| 500 | Server sập khi xử lý | Backend | Xem terminal hoặc log hosting — lỗi thật nằm ở đó, không ở trình duyệt |
| 502 / 503 | Server không phản hồi | Hosting | Server chưa khởi động xong, hết tài nguyên, hoặc deploy đang chạy |
4. Bảng tra 22 lỗi hay gặp nhất
| Thông báo | Nghĩa thật + hướng sửa |
|---|
5. Quy trình chẩn đoán 5 bước
Làm theo thứ tự này thay vì dán lỗi rồi cầu nguyện. Hầu hết lỗi được tìm ra ở bước 2:
Tái hiện được không?
Làm lại đúng các bước xem có lỗi lần nữa không. Lỗi ổn định thì dễ sửa. Lỗi lúc có lúc không thường liên quan tới thời điểm dữ liệu về, hoặc trạng thái còn sót lại trong trình duyệt.
Trước đó có chạy không?
Câu hỏi quyền lực nhất. Nếu sáng nay còn chạy thì nguyên nhân nằm trong đúng những thay đổi từ lúc đó tới giờ. Dùng git log xem đã commit gì, hoặc quay về commit trước để xác nhận.
Thu hẹp phạm vi
Bỏ bớt cho tới khi hết lỗi. Tắt tính năng vừa thêm, xoá bớt dữ liệu, thử với tài khoản khác. Chỗ mà bỏ đi thì hết lỗi chính là chỗ chứa nguyên nhân.
Đọc lỗi thật, không đọc triệu chứng
"Màn hình trắng" là triệu chứng. Dòng đỏ trong Console mới là lỗi. Luôn lấy nguyên văn, không diễn giải lại bằng lời của mình.
Sửa nguyên nhân, không vá triệu chứng
Thêm một câu điều kiện để tránh lỗi hiện ra thì lỗi vẫn còn, chỉ là bị giấu đi. Hỏi tiếp: tại sao chỗ đó lại không có dữ liệu?
6. "Máy tôi chạy được mà"
Chạy local ổn nhưng deploy lên là hỏng — bốn nguyên nhân chiếm gần hết:
| Nguyên nhân | Dấu hiệu |
|---|---|
| Chưa khai biến môi trường trên hosting | Lỗi kiểu "undefined" ở chỗ gọi API, hoặc không kết nối được database. File .env của bạn không được đẩy lên — phải nhập tay vào bảng điều khiển hosting. |
| Phân biệt hoa thường trong tên file | Máy Mac/Windows không phân biệt, server Linux thì có. Button.tsx và button.tsx là hai file khác nhau trên server. |
| Phiên bản Node khác nhau | Build fail với lỗi cú pháp lạ. Khai rõ phiên bản Node trong cấu hình dự án. |
| CORS hoặc URL còn trỏ về localhost | Còn địa chỉ localhost:3000 nằm trong code — phải dùng biến môi trường theo từng môi trường. |
Vòng lặp hàng ngày — 4 lệnh là đủ 90%
16 tình huống hoảng loạn — tra là có lệnh
Lệnh nguy hiểm — đọc kỹ trước khi gõ
| Lệnh | Nó làm gì | Hoàn tác được? |
|---|---|---|
| git reset --hard | Xoá sạch mọi thay đổi chưa commit, quay về commit chỉ định | Việc chưa commit thì mất vĩnh viễn. Commit đã tạo thì cứu được bằng reflog |
| git clean -fd | Xoá mọi file chưa từng được Git theo dõi | Không. Git chưa từng biết file đó nên không có bản lưu |
| git push --force | Ghi đè lịch sử trên server bằng bản của máy bạn | Nguy hiểm khi làm nhóm — xoá mất commit của người khác |
| git branch -D | Xoá nhánh kể cả khi chưa gộp | Cứu được bằng reflog trong khoảng 30 ngày |
| git checkout . | Vứt bỏ mọi sửa đổi chưa commit trong thư mục | Không |
--hard, --force, hoặc -D: chạy git status xem đang có gì chưa lưu, và tự hỏi "nếu cái này biến mất thì tôi mất bao nhiêu giờ làm việc". Không chắc thì commit trước đã — commit thừa không hại ai.Quy tắc commit cho người mới
Commit khi nào
Mỗi lần app chạy được, dù chưa hoàn hảo. Đừng đợi đẹp mới lưu.
Đặt tên thế nào
Động từ + cái gì: "thêm màn hình comment", "sửa lỗi upload file lớn". Đừng viết "update", "fix", "abc".
Commit bao lớn
Một commit = một ý. Sửa 5 thứ khác nhau thì chia 5 commit — sau này quay lại từng cái được.
Không bao giờ commit
.env, node_modules, file build, file media nặng, và bất cứ thứ gì chứa khoá.
File .gitignore tối thiểu — đặt ở gốc dự án, tạo trước commit đầu tiên:
# bí mật — quan trọng nhất .env .env.local .env.*.local *.pem # thư viện và file sinh ra tự động node_modules/ .next/ dist/ build/ # rác hệ thống .DS_Store Thumbs.db *.log # media nặng — dùng dịch vụ lưu trữ riêng *.mp4 *.mov *.prproj *.drp
Nhánh — cách thử ý tưởng mà không phá bản đang chạy
main ──●──●──●─────────────────●──▶ luôn chạy được, đây là bản deploy ╲ ╱ thu-nghiem ●──●──●──●────╯ thử tính năng mới ở đây ↑ ↑ tạo nhánh gộp lại khi ổn nếu tệ: xoá nhánh, main không hề hấn gì
Với vibe-code, nhánh có giá trị nhất khi bạn muốn bảo AI thử một hướng lớn: tạo nhánh, cho nó làm thoải mái, hỏng thì xoá cả nhánh — main vẫn nguyên vẹn. Giống duplicate timeline trước khi thử một cấu trúc dựng khác.
1. Trước khi tạo dự án — chốt 6 thứ này
Bảo AI "làm cho tôi cái app quản lý project" là brief một câu cho một phim 3 phút. Chốt 6 thứ dưới đây trước, mọi thứ sau đó nhanh gấp ba:
1 · Một câu
App này giúp AI làm được VIỆC GÌ. Một câu, không hai.
"Cho khách xem cut và comment theo timecode"2 · Danh sách màn hình
Liệt kê 3–7 màn. Nhiều hơn 7 là v1 quá to.
Đăng nhập · Danh sách project · Xem cut · Comment3 · Dữ liệu lưu gì
Mỗi nhóm dữ liệu sẽ thành một bảng trong database.
User · Project · Video · Comment4 · Ai được vào
Công khai hay phải đăng nhập? Có mấy loại người dùng?
Admin · Editor · Khách xem5 · Cắt phạm vi v1
Quan trọng nhất. Ghi rõ cái gì ĐỂ SAU. Không ghi thì AI sẽ làm hết.
V2: thông báo, export, phân tích6 · Stack
Chọn một bộ rồi khoá lại, ghi vào file quy ước.
Next.js + Supabase + Vercel2. Vòng lặp chuẩn của một phiên làm việc
Bắt AI lên kế hoạch, chưa code
Bạn đọc, sửa, duyệt kế hoạch
Cho làm một lát nhỏ duy nhất
Bạn mở app, bấm thử thật
Chạy được thì commit ngay
Lặp lại lát tiếp theo
Bước 5 là bước bị bỏ nhiều nhất và cũng là bước cứu bạn. Commit = lưu version. Có commit thì mọi sai lầm sau đó chỉ tốn 30 giây để quay lại. Không commit thì một lần AI "dọn dẹp giúp" có thể xoá mất hai ngày làm việc.
3. Dùng công cụ nào cho việc gì
Claude Code
Chạy trong terminal, tự đọc và sửa nhiều file, chạy lệnh, cài thư viện, đọc lỗi. Nó nhìn thấy cả dự án chứ không chỉ đoạn bạn dán vào.
Codex / Copilot agent
Cùng nhóm agent chạy trên codebase, khác nhà cung cấp. Chọn một cái làm chủ dự án là đủ.
ChatGPT / Claude (chat)
Không thấy dự án của bạn, chỉ thấy cái bạn dán vào. Bù lại rất tốt để hỏi khái niệm và lấy ý kiến thứ hai.
Cursor / Windsurf
Trình soạn code có AI, thấy từng dòng thay đổi trước khi nhận.
4. Trí nhớ của AI — thứ bạn phải quản lý
AI không nhớ gì giữa hai phiên, và trong một phiên dài nó cũng quên dần phần đầu. Cách xử lý: đưa trí nhớ ra file.
Tạo file quy ước ở gốc dự án — Claude Code đọc CLAUDE.md, Codex đọc AGENTS.md, Cursor đọc .cursorrules. Nội dung gần như nhau, tạo cả ba cũng được:
# DỰ ÁN App review cut cho khách hàng. Khách xem video và comment theo timecode. # STACK — KHÔNG ĐỔI Next.js App Router · TypeScript · Supabase (DB + Auth) · Tailwind · Vercel # NGUYÊN TẮC BẢO MẬT — BẮT BUỘC - Mọi bảng phải bật RLS. Không tạo bảng mới mà không kèm policy. - Không bao giờ đặt khoá bí mật ở frontend. Chỉ dùng NEXT_PUBLIC cho thứ vô hại. - Mọi route backend phải kiểm tra người gọi là ai và có quyền không. - Validate lại toàn bộ input ở phía server. # CÁCH LÀM VIỆC VỚI TÔI - Luôn trình bày kế hoạch trước, chờ tôi duyệt rồi mới code. - Mỗi lần chỉ làm một việc. Không tự ý sửa file ngoài phạm vi tôi nêu. - Tôi không rành backend: giải thích bằng tiếng Việt, không dùng từ chuyên môn mà không giải thích. - Chọn cách đơn giản nhất chạy được. Không thêm thư viện nếu chưa hỏi tôi. - Sau mỗi thay đổi, tóm tắt đã sửa file nào và tại sao. # ĐANG LÀM DỞ (cập nhật cuối phiên: đang làm màn hình comment, chưa xong phần timecode)
5. Mười luật viết prompt code
Bắt lên kế hoạch trước, cấm code
Luật quan trọng nhất. Sửa một đoạn kế hoạch mất 30 giây; sửa 800 dòng code đã sinh ra mất cả buổi.
Một yêu cầu một việc
Gộp ba việc vào một prompt thì lỗi ở việc nào bạn cũng không biết. Chia lát như dựng: một sequence một lần.
Khoá phạm vi rõ ràng
Không khoá thì AI hay "tiện tay dọn luôn" và làm hỏng thứ đang chạy tốt.
Dán lỗi nguyên văn, đừng kể lại
Thông báo lỗi là bằng chứng gốc — như đưa file log thay vì nói "nó bị giật giật".
Mô tả kết quả mong muốn, không chỉ đạo cách làm
Bạn là đạo diễn, không phải người cầm máy. Nói cái muốn thấy; nếu bạn không rành kỹ thuật thì đừng áp cách làm.
Bắt nó nêu giả định trước khi làm
Phần lớn kết quả sai là do AI tự đoán thứ bạn chưa nói. Bắt nó nói ra thì bạn chặn được ngay.
Chặn phức tạp hoá
AI có xu hướng dựng kiến trúc cho công ty nghìn người trong khi bạn chỉ cần một trang. Code càng nhiều thì càng nhiều chỗ hỏng.
Yêu cầu tóm tắt thay đổi sau mỗi lần
Bạn không đọc được hết code, nhưng bạn đọc được tóm tắt. Đây là cách duy nhất để biết nó vừa đụng vào đâu.
Bắt nó tự chạy và tự kiểm
"Xong rồi" của AI thường có nghĩa là "tôi đã viết xong", không phải "tôi đã chạy thử và nó chạy".
Không hiểu thì hỏi lại ngay, đừng bấm tiếp
Mỗi thứ bạn không hiểu mà vẫn nhận là một chỗ sau này không tự sửa nổi. Hỏi lại rẻ hơn nhiều.
6. Khi AI sửa mãi không xong — quy tắc 3 lần
Ai cũng gặp: bảo sửa, nó sửa, vẫn lỗi, sửa tiếp, hỏng thêm chỗ khác. Vòng xoáy này đốt tiền và làm nát code. Quy tắc: thử 3 lần không xong thì dừng, đổi cách — đừng thử lần 4.
Sửa bình thường. Mỗi lần dán nguyên văn lỗi mới.
Không bảo "thử lại" nữa. Đổi chiến thuật.
Bắt nó chẩn đoán thay vì vá.
Rollback về commit sạch, làm lại hướng khác.
7. Kiểm chứng AI không bịa
| Kiểu bịa hay gặp | Cách phát hiện |
|---|---|
| Thư viện không tồn tại | Cài không được, hoặc tên na ná tên thật. Bắt nó đưa link trang chủ. |
| Hàm/tính năng không có thật | Chạy là lỗi ngay. Hỏi "chỗ nào trong tài liệu chính thức nói vậy?" |
| "Đã sửa xong" mà chưa chạy | Bắt chạy thật và dán kết quả ra. Đừng nhận báo cáo suông. |
| Số liệu, giá, giới hạn gói dịch vụ | Những thứ này đổi liên tục — bắt nó tra web trước khi trả lời. |
| Sửa test cho pass thay vì sửa code | Xem nó có vừa đổi file test không. Nếu có, hỏi thẳng. |
| Đồng ý với bạn dù bạn sai | Nếu bạn phản đối mà nó lập tức quay xe hoàn toàn, hỏi lại: "trước đó bạn sai chỗ nào, giải thích cụ thể". |
8. Kiểm thử tối thiểu — đừng bỏ hẳn
Không cần phủ 100%. Vibe-coder chỉ cần đủ để biết thứ đang chạy có bị hỏng khi sửa cái khác không — giống check gate trước khi gửi master, không phải xem lại từng frame.
Mức tối thiểu
Luồng chínhĐăng nhập → tạo → xem → xoá. Chạy được là ổn.
Nên thêm
3 ca lỗiNhập rỗng, nhập sai định dạng, không có quyền.
Khi có người dùng thật
Test tự độngChạy mỗi lần deploy, chặn không cho lên nếu hỏng.
9. Thư viện prompt — copy dùng ngay
App của bạn gồm những mảnh nào
Đối chiếu sang pipeline post cho dễ hình dung:
Frontend
Giao diện chạy trên máy người dùng. Ai cũng xem được toàn bộ code này.
≈ Bản master đã phát — không giấu được gìBackend / API
Code chạy trên server của bạn. Người dùng không nhìn thấy.
≈ Phòng máy, chỉ ekip vàoDatabase
Nơi lưu dữ liệu người dùng vĩnh viễn.
≈ NAS lưu toàn bộ projectAuth
Xác định bạn là ai và được xem cái gì.
≈ Phân quyền truy cập folderEnv / Secrets
Khoá API, mật khẩu DB. Chỉ được nằm ở backend.
≈ Password NAS — không dán lên tườngHosting
Nơi app thực sự chạy 24/7 cho người ngoài truy cập.
≈ Nền tảng phát hành5 lỗi làm sập dự án vibe-code — đọc trước tiên
Stack mặc định an toàn cho vibe-coder
Không phải lựa chọn duy nhất, nhưng là bộ ít gây tai nạn nhất khi bạn không rành backend:
Framework
Next.jsFrontend + backend trong một dự án, đỡ phải nối hai thứ.
Database + Auth
SupabasePostgres + đăng nhập sẵn + RLS. Nhớ BẬT RLS.
Hosting
VercelDeploy bằng git push, tự có preview cho mỗi thay đổi.
Thanh toán
Stripe / PolarKhông bao giờ tự lưu số thẻ. Không bao giờ.
Báo lỗi
SentryBiết app lỗi trước khi người dùng phàn nàn.
Đừng tự dựng mail server.
Đèn đỏ — thấy những dòng này thì dừng lại hỏi
| Claude viết ra thứ này | Nghĩa là |
|---|---|
| Khoá dài dán thẳng trong file .js/.tsx | Secret bị lộ ra frontend → chuyển sang biến môi trường ở server |
| NEXT_PUBLIC_… chứa khoá bí mật | Tiền tố PUBLIC nghĩa là cả thế giới đọc được → sai chỗ |
| service_role / admin key ở phía client | Khoá toàn quyền bị phơi ra → nguy hiểm nhất trong tất cả |
| Câu SQL nối chuỗi bằng dấu + | Rủi ro SQL injection → phải dùng tham số hoá |
| dangerouslySetInnerHTML / innerHTML với dữ liệu người dùng | Rủi ro XSS → phải làm sạch dữ liệu trước |
| cors: origin "*" | Mọi website đều gọi được API của bạn → giới hạn domain |
| DROP TABLE / TRUNCATE trong migration | Xoá sạch dữ liệu → backup trước, chạy trên staging trước |
| Mật khẩu lưu dạng chữ thường đọc được | Không bao giờ được phép → phải hash |
Từ điển backend — hiểu Claude đang nói gì
4 prompt bắt Claude tự kiểm tra
Phần pháp lý ở trên chỉ là thông tin tham khảo, không phải tư vấn pháp lý. Nếu app xử lý dữ liệu cá nhân ở quy mô thật, nên hỏi luật sư về Nghị định 13/2023/NĐ-CP.