Sử dụng checklist xuất mã nguồn do AI tạo này để bàn giao dự án an toàn: biến môi trường, bí mật, cài đặt cục bộ, khởi tạo DB, CI và một README chạy rõ ràng.

Hầu hết dự án xuất bị hỏng vì một lý do đơn giản: chúng chạy ổn bên trong nền tảng gốc, nơi mọi mặc định, bí mật, trạng thái cơ sở dữ liệu và bước build đã có sẵn. Khi mã rời khỏi bong bóng đó, người tiếp theo phải đoán những gì đã được giả định.
Một bàn giao sạch nghĩa là dự án có thể được clone, cấu hình và khởi động bởi người không phải người xây dựng, trên một máy mới tinh, mà không cần trao đổi dài dòng. Nó không đòi hỏi mã hoàn hảo. Nó đòi hỏi những điều cơ bản được làm rõ và có thể lặp lại.
Các xuất bị vỡ vì cùng một nhóm vấn đề lặp đi lặp lại: cấu hình ẩn, cách xử lý bí mật mơ hồ, bước thiết lập cục bộ không rõ ràng, bất ngờ với database, và CI chỉ hoạt động trong một môi trường duy nhất.
Đó là lý do vì sao một checklist xuất mã nguồn do AI tạo chủ yếu nói về tài liệu và khả năng tái tạo, không phải sao chép file. Nếu bạn xây dựng app trên một nền tảng vibe-coding như Koder.ai rồi xuất source, đội tiếp theo vẫn cần một bản đồ: phải thiết lập gì, chạy gì và “hoạt động” trông như thế nào.
Checklist này tập trung vào những điều thiết yếu khi bàn giao: biến môi trường, bí mật, thiết lập phát triển cục bộ, khởi tạo cơ sở dữ liệu, cấu hình CI, và một README “cách chạy” thực tế. Nó không bao gồm quyết định sản phẩm, hoàn thiện UX hay thiết kế lại kiến trúc.
Quyền sở hữu cũng phải rõ ràng. Người xây dựng có trách nhiệm làm rõ các giả định (tài liệu, script, mặc định an toàn). Người nhận chịu trách nhiệm điều chỉnh dự án cho môi trường của họ (trình quản lý bí mật, hosting, quy tắc CI nghiêm hơn). Khi hai bên biết phần việc của mình, bàn giao trở nên thủ tục hơn.
Một bàn giao sạch bắt đầu bằng một thỏa thuận đơn giản: khi nào thì coi là "xong" khi mã rời nền tảng. Nếu không có điều này, các đội sẽ tranh cãi sau về script thiếu, phụ thuộc bất ngờ, hoặc phiên bản nào là thực.
Chọn một thời điểm ổn định duy nhất và xem nó như nguồn chân lý. Xuất giữa chừng là cách khiến repo thành thứ gần như chạy được.
Một điểm xuất tốt thường là một trong các lựa chọn sau:
Thêm một câu giải thích tại sao đây là điểm xuất phù hợp. Ví dụ: “Tất cả luồng chính đều qua và schema cơ sở dữ liệu đã cố định cho mốc này.”
Viết một bản kiểm kê ngắn về những gì người nhận nên mong đợi. Hãy cụ thể về những gì có trong gói và những gì cố tình không gồm.
Bao gồm những thứ cơ bản: mã nguồn (apps, services, package dùng chung), mẫu config (ví dụ file env), script (build, dev, test, migrations, seed), và ghi chú triển khai. Chỉ kèm dữ liệu mẫu nếu nó đã được làm sạch và an toàn.
Rồi đóng băng phiên bản để “chạy trên máy tôi” không thành chuẩn mới. Ghi lại phiên bản runtime và toolchain (Node, Go, Flutter, package manager), cùng phiên bản cơ sở dữ liệu (phiên bản chính PostgreSQL quan trọng).
Cuối cùng, liệt kê các điều kiện tiên quyết phải hoàn thành trước khi chạy thứ gì đó. Giữ ngắn và cụ thể: tài khoản cần có, công cụ cần cài, cổng phải trống, và bất kỳ bước thiết lập một lần nào.
Hầu hết các xuất "chạy được trên nền tảng" bị hỏng vì các thiết lập chính chưa bao giờ được ghi lại. Biến môi trường là thủ phạm thông thường: chúng sống ngoài repo, nên thành viên mới clone project không biết giá trị mong đợi.
Xử lý việc này như bắt buộc cho một xuất sạch: mỗi biến phải có thể tìm ra, được giải thích và dễ thiết lập mà không phải đoán mò.
Tạo một nguồn chân lý duy nhất trong README bàn giao: danh sách tên biến, chúng điều khiển gì, và giá trị lấy từ đâu. Giữ lời giải thích đơn giản, và ghi rõ điều gì liên quan đến bảo mật.
Một định dạng đơn giản cho mỗi biến:
Cùng với tài liệu đó, kèm một file .env.example trong repo. Nó nên bao gồm mọi biến có thể cần, với giá trị placeholder an toàn để app có thể khởi động với vài chỉnh sửa tối thiểu.
# Required
APP_ENV=development
PORT=3000
DATABASE_URL=postgres://user:password@localhost:5432/app_dev
# Optional
LOG_LEVEL=info
CORS_ORIGINS=http://localhost:5173
# Environment specific
PUBLIC_BASE_URL=http://localhost:3000
Một vài chi tiết ngăn phần lớn nhầm lẫn:
Làm rõ “bắt buộc vs tùy chọn”. Nếu thiếu một biến khiến crash, hãy nói rõ. Nếu nó bật tính năng (gửi email, thanh toán, lưu file), nêu tên tính năng và mô tả điều gì xảy ra khi không có.
Ghi ra điều gì thay đổi giữa các môi trường. DATABASE_URL và PUBLIC_BASE_URL thường khác nhau giữa dev, staging và production, trong khi LOG_LEVEL có thể giống nhau. Nếu bạn dùng Koder.ai để xuất và triển khai, kiểm tra lại các mặc định nền tảng (ports, base URLs, allowed origins) đã được phản ánh trong tài liệu để hành vi nhất quán khi ra ngoài nền tảng.
Cuối cùng, nói rõ cách load env vars cục bộ. Nếu project mong đợi file .env, ghi nơi đặt nó và app có đọc tự động hay cần lệnh/công cụ nào.
Bí mật là các giá trị có thể gây hại nếu lộ: API keys, mật khẩu database, token auth, OAuth client secret, private keys, webhook signing secrets, v.v.
Với một xuất, giữ cho đơn giản: repo chỉ chứa placeholder, không bao giờ giá trị bí mật thật. Nếu bí mật cần để khởi động, đưa nó vào .env.example với tên rõ ràng và giải thích cách tạo bí mật thật.
Một mô hình thực tế là tách ba thứ: file mẫu, file cục bộ, và kho bí mật cho CI/triển khai. Mã nguồn xuất nên gồm file mẫu, ignore file cục bộ, và tài liệu cách CI/hosting nhận bí mật.
Chọn một cách cho mỗi môi trường và giữ nhất quán.
.env (được gitignored) được app load, hoặc trình quản lý bí mật cục bộ của độiVí dụ: repo có PAYMENTS_API_KEY=replace_me. Người nhận tạo key của riêng họ trên dashboard nhà cung cấp và đặt nó trong .env cục bộ và trong CI. Mã không đổi.
Bàn giao là thời điểm tốt để xoay vòng bí mật, đặc biệt nếu chúng từng được dùng trong phiên chia sẻ nền tảng.
.env cục bộ.Nếu bạn xuất từ Koder.ai, coi bản xuất như một môi trường mới và tạo bí mật mới cho đội nhận.
Một bàn giao thành công khi dev mới clone repo, chạy vài lệnh và thấy app hoạt động không phải đoán mò. Hướng tới tiền đề: điều kiện tiên quyết rõ ràng, thứ tự lệnh rõ ràng, và một khối “cách chạy” ngắn khớp với thực tế.
Đặt những thứ này ở đầu README để không ai phải suy diễn từ lỗi:
Nếu dự án được xây trên Koder.ai, giữ thiết lập cục bộ khớp với thứ bạn xuất (cấu trúc thư mục, lệnh start giống nhau). Đừng giả định “Postgres đã chạy” trừ khi bạn nói rõ.
Ghi chính xác các lệnh theo thứ tự mà đồng đội mới nên chạy. Giữ để copy-paste:
# 1) Install dependencies
cd web
npm ci
cd ../server
go mod download
# 2) Create your env file
cp .env.example .env
# 3) Start dependencies (if needed)
# e.g., start Postgres locally or via docker compose
# 4) Run the app
cd server
go run ./cmd/api
cd ../web
npm run dev
Thêm đoạn test và build tối thiểu ngay bên dưới:
# Tests
cd server && go test ./...
cd web && npm test
# Build
cd web && npm run build
cd server && go build ./...
Hầu hết lỗi “không chạy được” thuộc vài nhóm:
Phiên bản sai (Node/Go). Triệu chứng: lỗi dependency hoặc biên dịch. Sửa: cài phiên bản đã ghim và chạy lại cài đặt.
Thiếu giá trị env. Triệu chứng: config “undefined”, lỗi auth, lỗi 500. Sửa: so sánh .env với .env.example và điền giá trị bắt buộc.
Database không kết nối. Triệu chứng: connection refused, “database does not exist.” Sửa: khởi động Postgres, kiểm tra host/port/user, và chạy chính xác các bước init DB như ghi.
Khi một project được xuất từ nền tảng, database thường là thứ đầu tiên hỏng trên máy mới. Mục tiêu đơn giản: đồng đội có thể đi từ “tôi clone repo” tới “app chạy với dữ liệu thật” mà không phải đoán.
Ghi lại các bước tối thiểu để thiết lập PostgreSQL mới, và đặt các lệnh trong script khi có thể. Bàn giao nên trả lời bốn câu hỏi:
Nếu bạn đã có script (Makefile, shell script, task runner), dùng chúng thay vì mô tả thủ công. Nếu chưa, thêm vài script nhỏ ngay bây giờ.
Giữ luồng nhất quán giữa các môi trường (local, CI, staging). Một baseline tốt trông như sau:
# 1) Create role + database (example names)
createuser app_user --pwprompt
createdb app_db --owner=app_user
# 2) Apply migrations
# Replace with your repo's migration command
./scripts/migrate up
# 3) Seed minimal demo data
./scripts/seed
Với seed, ưu tiên dữ liệu tối thiểu hoạt động hơn là dump giống production. Seeds nên an toàn để chạy nhiều lần (insert idempotent, hoặc quy tắc “chỉ chạy trên DB rỗng”).
Với reset, rõ ràng về an toàn. Lệnh reset chỉ nên nhắm tới môi trường dev theo mặc định. Nếu cung cấp script phá hủy, thêm cơ chế chắn (ví dụ yêu cầu CONFIRM_RESET=1 hoặc kiểm tra APP_ENV=development). Cũng định nghĩa rõ “reset” nghĩa là gì: drop & recreate, wipe tables, hay restore snapshot đã biết.
Bàn giao dễ rối khi repo giống như ngăn kéo linh tinh. Người mới nên biết cái gì quan trọng, cái gì sinh ra tự động, và nơi thay đổi cấu hình.
Commit những thứ giúp project có thể lặp lại: lockfiles, file migration, template config nhỏ như .env.example, và bất kỳ script bootstrap nào.
Giữ những file cá nhân, sinh ra tự động hoặc nhạy cảm ra ngoài source control: file env cục bộ, thiết lập editor, output build, logs, cache và bất cứ thứ gì cho phép truy cập (API keys, mật khẩu DB, file service account).
Quy tắc đơn giản: nếu thay đổi ảnh hưởng mọi người, commit nó. Nếu nó thay đổi theo máy hoặc môi trường, ghi lại và để ngoài repo.
Nếu bạn kèm một ghi chú ngắn “keep vs ignore”, giữ nó ngắn gọn:
README, lockfiles, migrations, seed scripts, .env.example.env, file bí mật, thư mục build, logs, cache cục bộThêm bản đồ cấu trúc thư mục ngắn để dễ hiểu. Ví dụ: “/backend service API, /web frontend, /mobile app, /db migrations và seeds, /scripts helper setup.”
Nếu bạn xuất từ Koder.ai, coi bản xuất như khởi điểm cho bước làm sạch: bỏ bớt rác sinh ra, xác nhận file ignore, và viết bản đồ thư mục.
Bàn giao thất bại lặng lẽ khi CI gần giống local. Nếu ai đó chạy được project trên laptop, CI nên chạy cùng lệnh và trả về cùng kết quả.
Quyết định CI cần chứng minh gì cho mỗi pull request. Phần lớn đội chỉ cần vài thứ nhỏ:
Integration tests và bước deploy ổn nếu đáng tin và rõ phạm vi.
Giữ các bước CI gần với lệnh local để tránh trôi. Nếu local dùng make test, CI cũng nên chạy make test. Nếu không có Makefile hay task runner tương đương, cân nhắc thêm một cái và dùng nó làm entry point chung.
CI thường hỏng vì phụ thuộc vào cấu hình ẩn. Thêm phần “CI variables” ngắn trong README liệt kê tên chính xác CI cần. Tách cấu hình công khai và bí mật.
Ví dụ tên (chỉnh theo stack): APP_ENV, DATABASE_URL, PORT, JWT_SECRET, S3_BUCKET, STRIPE_API_KEY. Trong CI, bí mật phải đến từ kho bí mật CI, không phải file đã commit. Với backend Go + Postgres (phổ biến trong các xuất Koder.ai), cũng ghi rõ liệu migrations chạy tự động hay cần bước rõ ràng.
Quyết định những check nào bắt buộc trước merge và ghi lại. “lint + unit tests + build” thường là đủ. Nếu thêm job tùy chọn (ví dụ build mobile), để không chặn merge trừ khi thật cần.
Cũng làm cho output CI dễ gỡ lỗi: in phiên bản công cụ và fail kèm thông báo rõ. Thêm caching sau khi pipeline ổn định.
Maya nhận một dự án xuất từ Koder.ai. Nó là cấu hình điển hình: web React, API Go và PostgreSQL. Cô ấy nên clone và nhìn thấy màn hình hoạt động mà không đoán.
30 phút đầu của cô ấy nên như sau:
.env.example sang .env (hoặc set cùng giá trị trong shell) cho cả web và api.Trong một bàn giao lộn xộn, cô ấy thường gặp ba chặn chính.
Thứ nhất: app khởi động rồi crash với lỗi mơ hồ “missing config”. Vấn đề thực tế là biến chưa được ghi, như AUTH_JWT_SECRET hoặc DATABASE_URL có format khác. Nếu README liệt kê mọi biến cần thiết, cho ví dụ an toàn và mô tả nơi sử dụng, việc này sửa nhanh.
Thứ hai: API chạy, nhưng trang hiển thị “no data” hoặc lỗi 500. Database tồn tại nhưng không có table hay seed. Một bàn giao sạch bao gồm một hai lệnh tin cậy: chạy migrations, seed dữ liệu demo tối thiểu, và lệnh reset khi cần.
Thứ ba: mọi thứ chạy nhưng frontend trỏ sai port. Maya mở localhost:3000 nhưng API trên localhost:8080, hoặc CORS chặn request. Đây là lúc các mặc định thống nhất hữu dụng: một nơi để đặt WEB_PORT, API_PORT và API_BASE_URL, README nêu rõ URL local mong đợi.
Bàn giao chỉ hoàn tất khi người khác có thể chạy dự án từ một clone sạch mà không cần hỏi. Chứng minh dự án sống được ngoài nền tảng.
Thực hiện bài kiểm tra “clean clone” trên máy mới hoặc container bỏ đi. Đừng dùng lại folder cũ, dependency cache hay database local. Làm đúng theo README. Nếu phải ứng biến, sửa docs hoặc scripts cho tới khi không cần ứng biến nữa.
Các kiểm tra nhanh bắt phần lớn lỗi:
.env.example tồn tại và mọi biến bắt buộc được giải thích với ví dụ an toàn.Những bẫy thường gặp thật nhàm chán, nên dễ bị bỏ sót:
Bước tiếp theo: phân công một người chịu trách nhiệm xác thực bản xuất trong 24–48 giờ, không phải vài tuần. Người đó thực hiện bài test clean clone và báo cáo khoảng trống.
Nếu bạn xây dựng trên Koder.ai (Koder.ai), nên coi checklist này là một phần thói quen: dùng planning mode để ghi đường chạy, chụp snapshot trước thay đổi lớn, và xuất source theo lịch để gói bàn giao luôn cập nhật.
Chọn một mốc ổn định và xem đó là nguồn chân lý.
Ít nhất nên bao gồm:
.env.example và tài liệu biến môi trường rõ ràngBỏ hết thứ gì nhạy cảm và mọi credential thật ra ngoài.
Ghi lại mọi biến môi trường ở một chỗ (thường là README gốc) và kèm .env.example.
Với từng biến, liệt kê:
Đừng commit bí mật. Chỉ commit chỗ giữ.
Một setup đơn giản:
.env.example với các placeholder replace_me.env (được gitignore)Cũng nên ghi cách tạo từng bí mật cần thiết (ví dụ: “tạo chuỗi ngẫu nhiên >=32 ký tự cho ”).
Xoay vòng bất cứ thứ gì có thể đã được chia sẻ hoặc tái sử dụng.
Trật tự xoay vòng thực tế:
.env cục bộXem bản xuất như một môi trường mới và bắt đầu sạch sẽ.
Làm cho lần chạy đầu tiên trở thành “copy, paste, run”:
Nếu dự án cần Docker hoặc Make, nói rõ—đừng để người khác phát hiện từ lỗi.
Có—vì các phiên bản PostgreSQL chính và công cụ có thể thay đổi hành vi.
Ghi ít nhất:
Khóa phiên bản khi có thể và in các phiên bản trong CI để lỗi dễ gỡ.
Cung cấp đường dẫn “từ zero” lặp lại được:
Thêm các cơ chế bảo vệ cho hành động phá hủy (ví dụ: yêu cầu APP_ENV=development hoặc flag xác nhận).
Giữ CI gần với các lệnh local và làm cho cấu hình rõ ràng.
Nếu tests cần migrations, ghi rõ CI chạy migrations tự động hay cần bước riêng.
Chạy bài kiểm tra “clean clone”:
Nếu phải tự chế ngay cả một lần, sửa docs hoặc script cho tới khi không cần improvisation nữa. Đó là cách nhanh nhất để phát hiện giả định ẩn từ môi trường gốc (bao gồm các nền tảng vibe-coding như Koder.ai).
JWT_SECRET