Agent-Optimized
v3.0
TECH.MD — Tài liệu Kỹ thuật
& Quy tắc Phát triển
Tài liệu chuẩn dành cho AI Agents & Developers. Toàn bộ quy tắc kiến trúc, UI/UX, bảo mật và quy trình làm việc trong một file duy nhất.
Agent Quick Start
Checklist 4 bước bắt buộc trước khi code
TUYỆT ĐỐI BẮT BUỘC: Không bỏ qua bất kỳ bước nào trong quy trình này. Áp dụng cho mọi phiên làm việc.
1
Phân tích codebase
Đọc
schema.prisma và các types.ts hiện có. Không tạo type mới nếu đã tồn tại.2
Lên kế hoạch trước khi code
Mô tả danh sách file sẽ tạo/sửa. Tuân theo cấu trúc
modules/[feature]/.3
Hỏi kiến trúc với Owner
Xác định xem có nên tách module/package riêng không. Xem Rule #8 — Code Standards.
4
Triển khai từng file nhỏ
Viết code từng file, không vượt 250 dòng / file. Xem Rule #9 — File Size Limit.
Section 1
Hệ thống Lõi — Core Infrastructure
Runtime & Package
Node.js ≥ 22.x (LTS)
pnpm v9.x Workspaces
Turborepo v2.x
Ngôn ngữ
TypeScript v5.x
Strict Mode = true — Không ngoại lệ
Cấu trúc Monorepo
| Thư mục | Chứa gì | Ví dụ |
|---|---|---|
apps/* | Ứng dụng chạy được | web, admin, app |
packages/* | Packages dùng chung | ui, db, api, crypto, config |
Section 2
Frontend & Giao diện
Framework
Next.js v16.2 (App Router)
React 19
Styling
Tailwind CSS v4.2
Native config architecture. Ưu tiên tính năng native.
UI Components
Radix UI (Headless)
shadcn/ui (React 19)
Lucide React
Visualization & UX
recharts
@dnd-kit/core
lenis
Font bắt buộc:
Be Vietnam Pro — load qua next/font/google. Khai báo tại layout.tsx cho toàn bộ dự án.Dark Mode: Dùng custom
ThemeProvider từ components/providers.tsx. KHÔNG dùng next-themes — inject <script> vào React tree, crash hydration iOS Safari/React 19.Section 3
API & Tầng Giao tiếp Dữ liệu
API Layer
tRPC v11
End-to-End Type Safety
End-to-End Type Safety
Real-time
socket.io / tRPC Subscriptions
SSE cho Live Notifications
SSE cho Live Notifications
State Client
Zustand v5
KHÔNG dùng Redux
KHÔNG dùng Redux
Validation
Zod
Schema DB + Form + API
Schema DB + Form + API
Serialization
SuperJSON
Date, Map, Set qua network
Date, Map, Set qua network
Email
Resend
System + Marketing email
System + Marketing email
Section 4
Cơ sở Dữ liệu & Lưu trữ
ORM
Prisma v7.7
Dùng Query Compiler mới để tối ưu hiệu năng
Database
PostgreSQL
Row Level Security (RLS) bắt buộc
Storage
Cloudflare R2
S3 Compatible API. No Egress Fee.
Section 5
Xác thực & Bảo mật
Authentication
Auth.js (NextAuth v5 Core 3)
OAuth: Google, GitHub
Credentials: Argon2 / Bcryptjs
Credentials: Argon2 / Bcryptjs
Authorization
RBAC bắt buộc
Role: Admin / Editor / Viewer
Kiểm soát đến từng action, không chỉ dừng ở Login
Kiểm soát đến từng action, không chỉ dừng ở Login
XSS Protection: Bắt buộc dùng
DOMPurify cho mọi nội dung user-generated được render vào DOM.Section 6
Kiến trúc Multi-Tenant
Chiến lược Database
Single Schema + Row Level Security (RLS). Nhận diện khách thuê qua
tenant_id (UUID) trong mọi bảng nghiệp vụ.| Bảng | Các trường chính |
|---|---|
Tenant | id, name, domain, custom_domain, theme_config (JSON), features (String[]) |
User | id, email, role (OWNER | STAFF), tenant_id |
Order | id, status, amount, metadata (JSON), tenant_id |
Middleware Logic (
src/middleware.ts)// 1. Bóc tách hostname từ HTTP request
// 2. Nhận diện: subdomain hay custom domain?
// 3. Truy xuất tenant_id từ Cache/DB
// 4. Rewrite URL → /[tenantId]/dashboard/... hoặc /[tenantId]/store/...
Section 7
Quy tắc Viết Code dành cho Agent
-
01Type Safety — Tuyệt đối không dùng
anyMọi dữ liệu từ API phải có Schema Zod. Strict Mode = true toàn dự án. -
02Server Components mặc địnhMặc định dùng React Server Components (RSC). Chỉ dùng
'use client'khi thực sự cần tương tác UI. -
03Error Handling chuẩnDùng
error.tsxcủa Next.js + Error Formatting của tRPC để bắt và hiển thị lỗi. -
04Git: Conventional CommitsGhi commit tuân theo chuẩn Conventional Commits: feat, fix, chore, refactor, docs...
-
05Environment Variables — Schema duy nhấtCấm gọi
process.env.ABCrải rác. Bắt buộc dùngenv.ts+@t3-oss/env-nextjsvalidate bằng Zod. Throw Error ngay khi build/start nếu thiếu biến. -
06Rate Limiting & DebounceMọi input Tìm kiếm / Filter / Lookup phải wrap qua Debounce 300–500ms. Ngăn bão request khi gõ phím liên tục.
-
07Sitemap tự động cập nhật (SEO)Mọi route mới tạo ra — kể cả route động — đều phải tự động cập nhật vào
sitemap.ts. Mỗi URL phải có mô tả chuẩn SEO. -
08Hỏi kiến trúc trước khi làm tính năng mớiDừng lại hỏi user: có nên tách module/package/component riêng không? Giữ sạch code, dễ bảo trì.
-
09File Size Limit — Tối đa 250 dòng / fileNếu vượt → tách ngay:
- UI quá dài → extract sub-components vào
components/ - Logic quá dài → extract Custom Hooks vào
hooks/ - API calls quá dài → extract vào
services/hoặcqueries.ts - File cũ vi phạm → đề xuất Refactoring trước khi thêm tính năng mới
- UI quá dài → extract sub-components vào
-
10Routing: SEO vs InternalPublic / SEO: Folder Routing (Clean URL) —
app/products/[slug]/page.tsx. Tuyệt đối không dùng?id=123cho trang cần SEO.
Admin / Dashboard: Query Params (?c=16238&view=history) — SPA-like navigation.
Section 8
Quy tắc Thiết kế & UX/UI
Tuyệt đối không dùng Emoji làm biểu tượng. 100% phải dùng SVG Icons — khuyến nghị
lucide-react.Tuyệt đối không dùng
<select> mặc định của HTML. Xây dựng Custom Select Component bằng Radix UI hoặc State + Framer Motion.Cấm
window.confirm() và alert(). Dùng Inline Confirmation hoặc Custom Modal Overlay.| Quy tắc | Vấn đề | Giải pháp đúng |
|---|---|---|
| Responsive Mobile-First | Thiết kế vỡ trên Mobile | Cấm giá trị kích thước tĩnh cứng nhắc |
| Contrast & Dark Mode | Tương phản thấp, không Accessible | CSS Variables, không hardcode màu |
| Scrollbar Layout Shift | Modal mở/đóng dịch content 15–17px | Bù padding-right = scrollbarWidth khi overflow: hidden |
| Clipboard Fallback | navigator.clipboard bị chặn trong WebView | Fallback <textarea> ẩn + execCommand('copy') |
| Typography Card Title | Font quá bold gây khó đọc | text-xl font-bold text-neutral-700 dark:text-neutral-300 |
| Scrollbar Gutter | Content dịch khi scrollbar xuất/ẩn | scrollbar-gutter: stable trên html, body |
| Data Tables Mobile | Word wrap lộn xộn trên mobile | overflow-x-auto + whitespace-nowrap + min-w-[...] |
| Infinite Scroll | DOM collapse khi hàng trăm records | Strict Pagination (10 items/page) |
Scrollbar Shift Fix (mọi Modal/Drawer)
useEffect(() => {
const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth;
document.body.style.overflow = "hidden";
document.body.style.paddingRight = `${scrollbarWidth}px`;
return () => {
document.body.style.overflow = "auto";
document.body.style.paddingRight = "";
};
}, []);
Header & Navigation Signature
- Header sticky với
backdrop-saturate-150 backdrop-blur-xl bg-background/60 - Avatar fallback: 1 chữ cái nền
bg-blue-600nếu không load được ảnh - Dropdown Avatar dùng
createPortal+getBoundingClientRectđể tránh z-index/overflow issues - Mobile: Horizontal Scrollable Pager thay cho hamburger menu
Section 9
Zero-Trust Backend & Module Isolation
Quy tắc Vàng: Mọi Business Logic phải thực thi tại Server. Frontend chỉ là Presentation Layer.
- CẤM Authorization tại Client (
if (user.role === 'admin') showDeleteButton) - CẤM tính toán giá, tồn kho, điểm thưởng tại Client rồi gửi lên Server
- CẤM dùng ID từ request body mà không verify ownership (IDOR Attack)
- Mọi API/Server Action bắt đầu bằng: Authentication → Authorization → Logic
Feature-based Module Structure
apps/web/modules/
users/
actions.ts ← Server Actions (write/delete/edit)
queries.ts ← Server-side data fetching
schemas.ts ← Zod validation schemas
types.ts ← TypeScript types (module scope)
components/ ← UI chỉ thuộc module này
projects/ ← Tương tự
admin/ ← Tương tự
Mẫu Server Action chuẩn
"use server";
export async function deleteProject(projectId: string) {
// Bước 1: Xác thực danh tính
const session = await auth();
if (!session?.user) throw new Error("Unauthorized");
// Bước 2: Kiểm tra quyền sở hữu (chống IDOR)
const project = await db.project.findFirst({
where: { id: projectId, ownerId: session.user.id },
});
if (!project) throw new Error("Forbidden");
// Bước 3: Thực thi logic nghiệp vụ
await db.project.delete({ where: { id: projectId } });
}
Section 10
Component Patterns & UI Standards
RowActions — Kebab Menu bắt buộc
Mọi bảng có ≥ 2 actions bắt buộc dùng
Built-in: Escape/Click-outside close, flip-up tự động, z-index 9999, iOS ghost-click guard.
RowActions với nút ⋮.Built-in: Escape/Click-outside close, flip-up tự động, z-index 9999, iOS ghost-click guard.
ConfirmDialog bắt buộc khi xóa/sửa
Mọi thao tác Delete/Edit phải qua ConfirmDialog trước khi thực thi.
Variants: danger (đỏ) / warning (vàng) / info (xanh)
Variants: danger (đỏ) / warning (vàng) / info (xanh)
Toast sau mỗi Action
Sau mọi
onConfirm phải gọi toast.success() hoặc toast.warning().<Toaster /> đặt 1 lần trong root layout.EmptyState Component
Khi list trả về
length === 0, bắt buộc render: Icon + Text thân thiện + CTA Button.Loading Skeleton
Cấm
<div>Loading...</div>. Phải dùng Suspense + Skeleton trùng khớp layout gốc kèm shimmer effect.Form Management
Cấm
useState thuần cho form phức tạp. Bắt buộc: react-hook-form + zodResolver. Lỗi inline với viền đỏ.Section 11
iOS Safari — Tất cả Bug đã xác nhận
| Bug | Triệu chứng | Giải pháp đúng | Tránh |
|---|---|---|---|
| Auto-zoom input | Font-size < 16px → Safari zoom trang | font-size: max(16px, 1em) | Không dùng user-scalable=no |
| Ghost Click Modal | Tap row → modal open → tap đầu tiên bị nuốt | isReady guard 350ms + pointer-events:none | Render modal tức thì tại tọa độ tap |
| Double-tap Zoom | Web page phóng to khi chạm đúp | touch-action: manipulation global | Không xử lý → vỡ UI |
| Dev Mode + Cloudflare | Toàn bộ onClick chết trên device thật | pnpm build && pnpm start | pnpm dev qua Cloudflare Tunnel |
| next-themes inject script | Click toàn trang chết trên iOS/React 19 | Custom ThemeProvider không inject script | Dùng next-themes với React 19 |
| SVG absorbing clicks | Tap icon không ăn lệnh của button | pointer-events: none trên SVG | Để mặc định trên SVG |
Viewport Meta chuẩn
export const viewport: Viewport = {
width: "device-width",
initialScale: 1,
// KHÔNG đặt maximumScale/userScalable
// → iOS click bug trên position:fixed!
};
Global CSS bắt buộc
/* globals.css */
input, select, textarea {
font-size: max(16px, 1em);
}
button, a, [role="button"] {
touch-action: manipulation;
}
html, body {
scrollbar-gutter: stable;
}
iOS Ghost Click Guard (350ms)
const [isReady, setIsReady] = useState(false);
useEffect(() => {
const t = setTimeout(() => setIsReady(true), 350);
return () => clearTimeout(t);
}, []);
// Trên modal card — SVG phải có pointer-events: none
<div style={{ pointerEvents: isReady ? 'auto' : 'none' }}>
{/* modal content */}
</div>
Section 12
Loading Skeleton & Priority Queue Loading
Checklist khi thêm Route mới
1
Thêm item vào
menuGroups[] trong Sidebar.tsx2
Tạo thư mục
app/[locale]/[route]/3
Tạo
loading.tsx — KHÔNG được bỏ quaimport { PageSkeleton } from ".../PageSkeleton";Chọn variant: overview / chat / generic
4
Tạo
page.tsx5
Áp dụng Priority Queue 4-tier nếu có API calls
Priority Queue 4-Tier Loading
Tier 1
0ms
Clock, Calendar, dữ liệu tĩnh
Render ngay
Tier 2
100ms
Permission check, auth
Không block UI
Tier 3
~500ms
API call quan trọng nhất
Skeleton hiện
Tier 4
1s+
Geocoding, metadata phụ
Load sau Tier 3
Section 13
Panel / Overlay Positioning (Không Layout Shift)
position: absolute; right: 0 anchor vào parent gần nhất có position != static — không phải cạnh phải màn hình!Layout Tree SAI
outer-wrapper
└── content-column
(position: relative) ← SAI
├── [nội dung trang]
└── Panel
(position: absolute; right: 0)
← anchor vào column!
Layout Tree ĐÚNG
outer-wrapper
(position: relative; width: 100%)
├── content-column
│ ← KHÔNG có position: relative
│ └── [nội dung trang]
└── Panel
(position: absolute; top:0; right:0)
← SIBLING, KHÔNG PHẢI CON
- Panel phải là SIBLING của content column, không phải con
- Content column KHÔNG thay
maxWidthhaymarginkhi panel mở/đóng - Outer wrapper PHẢI có
position: relative - Panel dùng
position: absolute(không phảifixed) trừ backdrop toàn màn hình
Section 14
Mở rộng E-Commerce & Bán hàng
Dynamic Theme Variables
Cấm hardcode màu trong JSX. Quy hoạch về biến CSS:
--primary, --secondary, --accent, --destructive.Cart State Engine
Zustand + persist middleware. Optimistic Update: cộng số lượng ngay trên UI, gửi request ngầm sau. Cấm Context API cho giỏ hàng.
Core Web Vitals
Cấm thẻ
<img> thô. 100% dùng next/image. Hero Banner: priority={true}. List images: loading="lazy" + responsive sizes.Product Variants URL
URL chuẩn SEO:
[locale]/[category]/[product]. Đổi biến thể dùng Search Params + scroll:false — không reload page.Section 15
AI Workspace Compatibility
MCP Architecture
AI Tools thành khối độc lập, linh hoạt cắm/thay thế model (DeepSeek, OpenAI, Gemini). Không lock-in 1 provider.
Vercel AI SDK Streaming
Output stream chunk-by-chunk. Render Markdown + Code Blocks ngay lập tức. Cấm user chờ 10s mới xổ ra toàn bộ text.
Persistence State
Lịch sử hội thoại lưu DB. Multi-session handling. User truy cập nhanh lịch sử qua sidebar.
Section 16
Quy trình Siêu tốc cho Agency / Freelance
1
Template Lõi (Nhân bản)
Thiết lập 1 Next.js + Tailwind chuẩn SEO, Glassmorphism, điểm Lighthouse tuyệt đối. Dùng làm vũ khí hạng nặng.
2
One-File Config
Toàn bộ ngữ liệu tĩnh trong
config.json: Tên, Menu, Hình ảnh, Màu, Tọa độ, Social links.3
Triển khai trong 5 phút
Copy thư mục gốc → sửa
config.json → Build → Bàn giao. Nhân bản không mất sức.Section 17
Mobile Testing qua Cloudflare Tunnel
Bắt buộc: Luôn dùng Production Build khi test qua Cloudflare Tunnel. Dev Mode dùng eval() và WebSocket HMR — iOS Safari block cả hai!
pnpm build # Build tối ưu, loại bỏ eval() và HMR
pnpm start -- --port 5000 # Chạy production server
cloudflared tunnel --url http://localhost:5000 # Sau đó mới tunnel
Phân biệt lỗi code vs lỗi môi trường
- Desktop OK, iPhone qua Cloudflare KHÔNG OK → Chạy
pnpm buildtrước - iPhone qua IP WiFi nội bộ OK → 100% lỗi Dev Mode + Cloudflare
- Cả WiFi nội bộ cũng KHÔNG OK → Mới bắt đầu debug code React
Section 18
UTF-8 Encoding — Quy tắc bắt buộc
MỨC ĐỘ NGHIÊM TRỌNG CAO: Vi phạm gây hỏng toàn bộ ký tự tiếng Việt. Đã xảy ra trên 3 cases thực tế.
CẤM dùng trong PowerShell
Add-Content -Path "file.md" -Value "nội dung"
echo "nội dung" >> file.md
"nội dung" | Out-File file.md
# Mặc định Windows-1252 → hỏng tiếng Việt
ĐÚNG — Ghi tường minh UTF-8
[System.IO.File]::WriteAllText(
"file.md", $content,
[System.Text.Encoding]::UTF8
)
# Hoặc dùng file tool của Agent
.gitattributes bảo vệ toàn dự án
* text=auto eol=lf
*.md text eol=lf
*.ts text eol=lf
*.tsx text eol=lf
*.css text eol=lf
*.json text eol=lf
Section 19
Zero-Cost Database Backup Strategy
Không phụ thuộc 100% vào Vendor. Vercel Cron bị giới hạn bộ nhớ <50MB và timeout — CSDL lớn sẽ crash OOM.
Worker
GitHub Actions — RAM ảo đến 7GB. Cài
pg_dump qua apt-get.Output
Nén
| gzip -9 rồi upload .gz vào Cloudflare R2 qua aws s3 cp.Security
Toàn bộ credentials trong GitHub Actions Secrets. Tách biệt server App và server Backup.
Section 20
Zero-Knowledge Crypto Architecture
Memory-Only Key
Cấm lưu
secretKey xuống localStorage, cookies, IndexDB. Zustand giữ key trên RAM. Đóng tab → key bốc hơi. Miễn nhiễm XSS.Dual-Salt PBKDF2
210,000 vòng lặp băm nát mật khẩu. 2 bộ Salt: auth_verify cho server, pepper+userId cho local. Blind Server + AES-GCM.
AAD Anti-Swap
AES-256-GCM nhúng
additionalData = "${item.id}:${userId}". Tráo Ciphertext sang ID khác → giải mã fail, trả về null.Section 21
Quy trình Khởi tạo Module mới (GitNexus Standard)
Nhận lệnh "Tạo module mới" → TUYỆT ĐỐI KHÔNG CODE NGAY. Bắt buộc qua bước "Project Topology Research".
1
Reusability Check
Query các hàm/component có chung công năng trước. Tìm xem đã có
IconBtn.tsx, relativeTime()... chưa?2
Đọc SKILL.md của module tương tự
Sao chép đúng Design Pattern và Naming Convention của dự án.
3
Impact Analysis
Dùng
gitnexus_impact kiểm tra Blast Radius nếu sửa shared Component/Hook.4
Báo cáo Implementation Plan
Phác thảo kế hoạch → User xác nhận → mới lập trình.