Bạn yêu cầu Claude Code tạo một trò chơi cờ vua trên trình duyệt. Mở trang lên, bạn thấy bàn cờ đã có, các quân cờ được sắp xếp ngay ngắn, con tốt ngoan ngoãn đi theo chuột. Có thể chơi rồi. Nhưng để thử, bạn kéo con tốt tiến lên ba ô cùng lúc - và nó ở luôn tại đó. Sau đó, bạn thử đi hai nước liên tiếp bằng quân đen. Trang vẫn chẳng phản đối.

Trước hai nước đi đó, dự án trông gần như đã hoàn thành. Giờ mới lộ ra phần quan trọng nhất vẫn chưa hoạt động: chẳng có gì kiểm tra luật chơi. Bạn có thể yêu cầu agent chặn nước đi đó của con tốt. Nhưng tiếp theo sẽ phải xử lý lượt đi, chiếu, nhập thành và phong cấp tốt. Sau mỗi lần sửa, vẫn còn câu hỏi: bạn đã bỏ sót điều kiện nào nữa?

Lúc này, bạn nên dừng lại và tìm đoạn mã có sẵn để giải quyết việc này. Luật cờ vua đã được triển khai trong thư viện chess.js. Bạn có thể truyền một nước đi vào thư viện để nhận kết quả kiểm tra. Khi đó, mã của bạn chỉ lo phần kết nối dễ hiểu: lấy nước đi từ bàn cờ, kiểm tra qua thư viện rồi hiển thị vị trí quân cờ chính xác.

Giờ còn phải đưa thư viện vào trình duyệt và tích hợp nó với trang. Một cách là tải thư viện qua liên kết CDN. Phần dưới sẽ giải thích cách hoạt động và vì sao chỉ thêm một liên kết vào mã chưa có nghĩa là con tốt đã thôi đi lung tung.

Thư viện làm gì

Thư viện là mã do người khác viết mà bạn đưa vào dự án để khỏi phải viết lại những thứ đã có. chess.js là một ví dụ điển hình: thư viện biết cách đi của từng quân, hiểu thế nào là chiếu và nhập thành, có thể liệt kê mọi nước đi hợp lệ từ vị trí hiện tại và cho biết ván cờ đã kết thúc hay chưa.

Và đây là lúc bạn dễ mắc bẫy: kết nối thư viện rồi chờ trò chơi tự chạy. Không đâu. Thư viện lưu luật chơi và trạng thái ván cờ trong bộ nhớ; nó không vẽ gì cả, thậm chí còn chẳng biết trên trang có bàn cờ.

Thành phầnPhụ trách việc gìNếu thiếu thì sao
Thư viện chess.jsluật chơi và trạng thái hiện tại của ván cờ: nước đi nào hợp lệ, đến lượt ai, ván cờ đã kết thúc chưakhông ai kiểm tra nước đi, bàn cờ cho phép mọi thứ
Giao diện trangbàn cờ, quân cờ, thao tác kéo thả, làm nổi bật các ôkhông có gì để chơi: đã có luật nhưng không có cách tương tác
Mã kết nốigửi nước đi vừa thực hiện đến thư viện rồi vẽ lại bàn cờ theo phản hồi của thư việnluật chơi và hình ảnh hoạt động riêng rẽ, không ảnh hưởng lẫn nhau

Hãy xem điều gì xảy ra với một nước đi thông thường. Bạn kéo quân tốt từ e2 thẳng đến e5. Giao diện nhận ra thao tác kéo, mã kết nối hỏi thư viện "nước đi này có hợp lệ không?", thư viện trả lời "không" - và mã kết nối đưa quân cờ về e2. Nếu không ai hỏi câu đó, quân tốt sẽ nằm yên ở e5: chẳng có gì ngăn trang vẽ nó ở đó.

Mã kết nối gửi nước đi đến chess.js: nước đi hợp lệ cập nhật bàn cờ, nước đi không hợp lệ đưa quân cờ về vị trí cũBạn di chuyển quân cờMã kết nối lấy nước đichess.js kiểm tra nước điNước đi hợp lệĐã cập nhật vị tríNước đi không hợp lệVị trí không đổiMã kết nối hiển thị trên bàn cờvị trí từ thư viện
Bàn cờ thay đổi theo kết quả kiểm tra nước đi

Cả hai nhánh đều kết thúc bằng cùng một thao tác: mã kết nối hiển thị vị trí từ thư viện. Sau nước đi hợp lệ, vị trí đã được cập nhật; sau nước đi không hợp lệ, vị trí vẫn như cũ, nên quân cờ trở về ô ban đầu.

Điều này gợi ra một điểm quan trọng khi viết yêu cầu. Câu "kết nối chess.js" có thể được thực hiện đúng nguyên văn - chỉ thêm một dòng tải thư viện, rồi dừng ở đó. Hãy yêu cầu kết nối đầy đủ: gửi nước đi từ bàn cờ vào thư viện, dùng phản hồi của thư viện để quyết định có di chuyển quân cờ hay không, rồi lấy vị trí sau nước đi từ trạng thái của thư viện chứ không phải từ chỗ bạn thả chuột.

Thư viện và skill nằm ở hai nơi khác nhau

Bạn rất dễ nhầm lẫn vì cả hai đều được "kết nối". Skill thay đổi cách agent hoạt động - mở rộng hướng dẫn và bổ sung kỹ năng cho agent. Còn thư viện hoàn toàn không liên quan đến agent: đó là mã bên trong ứng dụng của bạn, chạy trong trình duyệt của người dùng. Agent có thể kết nối thư viện, nhưng sau đó thư viện vẫn hoạt động mà không cần agent.

Trình duyệt nhận mã qua CDN như thế nào

Tệp thư viện cần được lấy từ đâu đó. Bạn có thể tải tệp xuống và đặt cạnh trang của mình, hoặc chèn vào mã trang một liên kết đến tệp đó trên dịch vụ bên ngoài. Người ta thường dùng CDN (Content Delivery Network, mạng phân phối nội dung) cho việc này. Đây là mạng lưới máy chủ cung cấp tệp cho người dùng ở nhiều nơi khác nhau. CDN thường được dùng để phân phối hình ảnh, stylesheet và thư viện JavaScript. Trong ví dụ này, dịch vụ jsDelivr cung cấp tệp thư viện.

Khi bạn mở trang, trình duyệt đọc mã và gặp liên kết đến thư viện. Trình duyệt gửi yêu cầu đến địa chỉ đó, tải tệp về rồi chạy mã trang có sử dụng thư viện. Thư viện chạy trong trình duyệt của người dùng. CDN chỉ phân phối mã; việc kiểm tra nước đi diễn ra trên thiết bị của bạn.

Trình duyệt yêu cầu thư viện từ CDN, nhận tệp và chạy mã bên trong trangCDN jsDelivrTệp thư việnTrình duyệt của người dùng1. Yêu cầutheo liên kết2. Tệpthư việnTrang đã tải thư viện3. Mã trang sử dụng chess.js
CDN phân phối tệp, trình duyệt chạy mã

Khung trong sơ đồ tách trình duyệt khỏi dịch vụ bên ngoài. Sau khi tải, thư viện nằm bên trong trang và mã kết nối gọi nó ngay tại đó. Không cần gửi từng nước đi đến CDN.

Cách kết nối chess.js như sau:

<script type="module">
  import { Chess } from 'https://cdn.jsdelivr.net/npm/chess.js@1.4.0/+esm'

  const chess = new Chess()
  console.log(chess.fen())
  // rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1
</script>

Ở đây có ba chi tiết quan trọng. Đầu tiên là type="module". Thư viện được cung cấp dưới dạng ES module, và chỉ có thể lấy Chess bằng cách import; thẻ <script src="..."> thông thường không thể phân tích tệp này - nó sẽ lỗi ở câu lệnh export bên trong. Một số thư viện còn có dạng phân phối kiểu cũ, không dùng module: khi đó chỉ cần thẻ thông thường và biến toàn cục sẽ tự xuất hiện trên trang. chess.js không có bản dựng như vậy, nên chỉ có một cách kết nối.

Chi tiết thứ hai là số phiên bản ngay trong địa chỉ, chess.js@1.4.0. Cách kết nối và tên các phương thức cần dựa trên tài liệu của đúng phiên bản được ghi trong liên kết. Địa chỉ không có số phiên bản sớm muộn cũng sẽ dẫn đến một tệp khác, khiến mã viết theo tài liệu cũ ngừng hoạt động.

Chi tiết thứ ba, cũng dễ bị bỏ qua nhất, là phần đuôi /+esm ở cuối địa chỉ. Nó không phải để trang trí mà là yêu cầu CDN đóng gói tệp dưới dạng module: thiếu phần này, cùng địa chỉ đó sẽ trả về một bản dựng khác và import sẽ không tìm thấy gì.

Bạn có thể kiểm tra thư viện đã tải thành công hay chưa mà không cần hoàn thiện cả trò chơi - thêm vài dòng vào cùng thẻ <script type="module"> rồi mở console của trình duyệt (tab Console trong công cụ dành cho nhà phát triển, F12 hoặc Ctrl+Shift+I):

// quân tốt trắng không thể đi thẳng từ e2 đến e5
try {
  chess.move('e5')
} catch (error) {
  console.log('nước đi bị từ chối:', error.message) // Invalid move: e5
}

chess.move('e4')          // thư viện chấp nhận nước đi này
console.log(chess.turn()) // b, đến lượt bên đen

Nếu console hiển thị vị trí ban đầu, nước đi bị từ chối và đến lượt bên đen sau e4, tức là tệp đã được tải và luật chơi hoạt động. Bước tiếp theo là kết nối chúng với bàn cờ.

Có một lưu ý để bạn không kỳ vọng quá mức: CDN không loại bỏ sự phụ thuộc vào mạng. Trình duyệt có thể dùng lại tệp trong bộ nhớ đệm, tức bản sao đã lưu, nên không nhất thiết phải tải lại mỗi lần mở trang. Nhưng nếu không có bản sao phù hợp và CDN không truy cập được, thư viện sẽ không tải được và trò chơi không thể áp dụng luật của nó.

Nếu console không có gì

Lỗi ở bước này hầu như luôn nằm ngay trong phần kết nối: sai địa chỉ, sai phiên bản hoặc sai cách import. Đừng sửa dòng mã theo kiểu đoán mò - hãy yêu cầu agent đối chiếu để tìm chính xác chỗ sai. Một lần kiểm tra ngắn thay vì nửa giờ thử hết cách này đến cách khác.

Kết hợp với Claude Code như thế nào

Yêu cầu "kết nối thư viện qua CDN" để agent tự quyết định một số việc: lấy tệp ở đâu, chọn phiên bản nào, tải vào trang ra sao và xác nhận kết quả bằng cách nào. Tốt hơn là nêu rõ các lựa chọn này ngay trong yêu cầu. Dưới đây là prompt cho từng tình huống; bạn không cần gửi tất cả cùng lúc.

Chọn liên kết để kết nối

Nếu agent đề xuất một thư viện, trước tiên hãy yêu cầu agent tìm hiểu cách kết nối thư viện đó với dự án của bạn. Như vậy, bạn sẽ có địa chỉ cụ thể kèm lời giải thích vì sao lại là địa chỉ đó.

Hãy xem trang của tôi được cấu trúc như thế nào và kiểm tra xem chess.js đã được kết nối chưa.
Tìm trong tài liệu của thư viện và jsDelivr cách tải qua CDN phù hợp với trình duyệt.
Đề xuất URL có phiên bản cụ thể và giải thích các phần trong địa chỉ.
Đưa ra liên kết đến tài liệu. Tạm thời đừng sửa mã.
Nếu không thể kiểm tra tài liệu, hãy nói rõ điều đó.

Trong câu trả lời, hãy tìm số phiên bản, cách kết nối và lý do chọn cách đó. Chỉ nói "đây là liên kết hoạt động" thì chưa đủ: bạn không biết agent đã đối chiếu địa chỉ với tài liệu hay tệp đó có phù hợp với trang của mình không.

Kết nối thư viện với bàn cờ

Sau khi chọn địa chỉ, hãy giao cho agent một việc có kết quả nhìn thấy được. Với trang HTML đơn giản, bạn có thể nêu ngay rằng mình muốn giữ nguyên cách chạy hiện tại.

Kết nối chess.js bằng địa chỉ CDN đã chọn, cố định phiên bản.
Giữ nguyên cách chạy trang hiện tại. Kết nối thư viện
với bàn cờ: gửi từng nước đi vào thư viện và hiển thị vị trí từ trạng thái của thư viện.
Nếu nước đi không hợp lệ, đưa quân cờ về ô ban đầu.
Cho tôi biết phần kết nối được thêm ở đâu và phản hồi của thư viện được xử lý ở đâu.

Ở đây có hai kết quả riêng: trình duyệt đã nhận thư viện, còn các thao tác trên bàn cờ bắt đầu tuân theo luật của thư viện. Khi yêu cầu agent chỉ ra cả hai chỗ trong mã, bạn sẽ thấy chính xác agent đã thêm những gì.

Kiểm tra kết quả trong trình duyệt

Liên kết xuất hiện trong HTML chỉ xác nhận tệp đã được chỉnh sửa. Yêu cầu tiếp theo giúp kiểm tra việc tải thư viện và cách trò chơi hoạt động.

Mở trang và xem trong tab Network của công cụ dành cho nhà phát triển
chess.js đã tải được chưa. Kiểm tra lỗi trong Console. Sau đó, từ vị trí ban đầu,
thử e2-e5: nước đi phải bị từ chối, quân tốt vẫn ở e2.
Tiếp theo, đi e2-e4: nước đi phải thành công và đến lượt bên đen.
Hãy cho biết bạn quan sát được gì ở từng bước. Nếu bạn không truy cập được trình duyệt,
hãy đưa cho tôi các bước kiểm tra ngắn gọn và nói rõ bạn chưa tự kiểm tra.

Tab Network hiển thị các yêu cầu mạng của trang, còn Console hiển thị thông báo và lỗi từ mã. Nếu tệp đã tải nhưng quân tốt vẫn đi được đến e5, hãy tìm nguyên nhân trong phần xử lý nước đi. Chỉ thay liên kết CDN sẽ không sửa được phần kết nối này.

Tìm hiểu lỗi tải thư viện

Nếu có lỗi, hãy gửi agent nguyên văn thông báo lỗi trong Console và địa chỉ yêu cầu thất bại trong Network. Nhờ vậy, agent có thể kiểm tra đúng nguyên nhân thay vì thử hết liên kết này đến liên kết khác.

Sau khi kết nối thư viện, trang báo lỗi.
Thông báo trong Console: [dán toàn bộ thông báo vào đây].
URL và kết quả yêu cầu trong Network: [dán địa chỉ và trạng thái vào đây].
Hãy kiểm tra tệp có truy cập được không, định dạng có phù hợp với cách import của chúng ta không
và tên trong mã có khớp với tài liệu của phiên bản đã chọn không.
Trước tiên, dựa trên dữ liệu này, hãy nêu nguyên nhân; sau đó sửa ở mức tối thiểu
và kiểm tra lại. Đừng đồng thời thay đổi CDN, phiên bản và mã trò chơi.

Thay phần văn bản trong ngoặc vuông bằng dữ liệu của bạn. Nếu hoàn toàn không thấy yêu cầu tải thư viện trong Network, hãy nói rõ - đây cũng là một manh mối hữu ích. Sau khi sửa, hãy kiểm tra lại hai nước đi để chắc rằng toàn bộ phần kết nối đã hoạt động.

Xử lý khi CDN không truy cập được

Nếu thư viện không tải được, bàn cờ trông vẫn hoạt động có thể khiến người dùng tưởng rằng vẫn chơi được. Hãy yêu cầu agent giúp người dùng hiểu rõ trạng thái này.

Hãy xử lý trường hợp không tải được chess.js từ CDN.
Khi thư viện chưa sẵn sàng, đừng cho phép đi quân. Nếu có lỗi, hãy hiển thị
thông báo dễ hiểu và tùy chọn tải lại trang.
Kiểm tra hoạt động khi yêu cầu đến CDN bị chặn, rồi kiểm tra lại sau khi
bỏ chặn. Lưu ý bộ nhớ đệm: chỉ ngắt mạng có thể vẫn giữ lại bản sao đã tải trước đó.
Hãy mô tả chính xác cách bạn kiểm tra lỗi.

Tốt hơn nên kiểm tra riêng tình huống này, không gộp vào một ván cờ thông thường. Kết quả cần cho thấy rõ hai trạng thái: thư viện sẵn sàng và các nước đi được kiểm tra; hoặc tải thư viện thất bại và trang giải thích vì sao chưa thể chơi.