Bắt đầu nhanh
Đây là đúng tài liệu mà bộ khởi đầu gửi cho trợ lý AI (AGENTS.md). Đưa nó cho Claude, Cursor hay Copilot và nhờ làm game.
Quy trình làm việc
npx @livebridge/dev init ten-gametạo thư mục từ game mẫu (id: 3-40 ký tự a-z, 0-9, dấu-, không đổi được sau này).- Sửa
game.js,index.html,style.css,manifest.json. npx @livebridge/dev servechạy thử ởhttp://localhost:5173/index.html?t=lbg_dev. Mở thêm http://localhost:5173/__panel: panel giả lập bấm quà, chat, like, follow, share, người vào phòng, đổi tên và avatar người xem, bật/tắt gửi tên và avatar.npx @livebridge/dev checkchạy đúng các bước kiểm tra tĩnh của máy chủ trên máy bạn. Phải sạch lỗi.- Một lần: tạo token ở https://livebridge.vn/app/dev/cli rồi
npx @livebridge/dev login. Sau đónpx @livebridge/dev upload(thêm--test-onlyđể chỉ thử, chưa phát hành; thêm--createnếu game chưa được tạo trên web). - Mỗi lần tải lên phải tăng `version` trong
manifest.json(ví dụ 1.0.0 thành 1.0.1).
Các file AGENTS.md, CLAUDE.md, README.md, file ẩn (bắt đầu bằng .) và node_modules không được đưa vào bản tải lên.
SDK LiveBridge
Nạp bằng đúng dòng này (trước script của game). Đừng copy hay bundle SDK: serve tự đổi URL này sang bản chạy cục bộ, còn khi chạy thật nó là bản của LiveBridge.
<script src="https://livebridge.vn/sdk/livebridge.js"></script>
<script>
const game = new LiveBridgeGame({
onAction(actionId, event, rule) { /* quà đã được streamer ánh xạ tới hành động của bạn */ },
onGift(event) { /* MỌI quà, kể cả quà chưa ánh xạ */ },
onChat(comment, user, event) {},
onFollow(user, event) {},
onShare(user, event) {},
onMember(user, event) {}, // người vào phòng
onLike(user, event) {}, // event.like.count = số like của lô này
});
</script>Tất cả handler (đều tuỳ chọn):
onReady(config, actionMap): SDK đã đọc xong manifest và bản ánh xạ quà.configlà manifest.json của bạn. `actionMap` có thể là `null` nếu lần đọc đầu thất bại (lỗi mạng, 429): khi đó bản ánh xạ đến sau quaonConfig. Đừng giả địnhactionMapluôn có.onConfig(actionMap): streamer vừa lưu lại ánh xạ quà (không cần tải lại trang), hoặc bản ánh xạ đến muộn sauonReady.onAction(actionId, event, rule): một quà khớp một quy tắc.rulecóactionId,amount(mặc định 1), vàgiftNamehoặcminDiamonds/maxDiamonds.onGift(event): mọi quà. Luôn gọi, kể cả khionActioncũng gọi.onChat(comment, user, event),onFollow(user, event),onShare(user, event),onMember(user, event),onLike(user, event).onEvent(event): mọi sự kiện thô (cả gift, chat...).onConnect(),onDisconnect(): socket mở / đóng. SDK tự kết nối lại sau vài giây, trừ khi link bị thu hồi.onTikTokStatus("connected" | "connecting" | "ended" | "disconnected"): tình trạng phòng TikTok của streamer. Socket có thể mở trong khi streamer chưa bấm kết nối TikTok.apiOrigin(tuỳ chọn): chỉ cần khi bạn tự host SDK. Đừng dùng.- Hàm tiện ích:
LiveBridgeGame.resolveGiftAction(actionMap, event),LiveBridgeGame.getDiamonds(event)(=diamondCount x repeatCount),LiveBridgeGame.getUser(event);game.destroy()để dừng.
Hình dạng sự kiện (sau khi lọc quyền riêng tư; trường có thể thiếu thì kiểm tra trước khi dùng):
{ type: "gift", seq, ts, channel,
user: { id, uniqueId, nickname, avatar, roles?: { moderator, subscriber, follower, member } },
gift: { id, name, diamondCount, repeatCount, icon? } } // chat: chat: { comment }
// like: like: { count, total? }gift.icon luôn là "" với game của nhà phát triển (CSP chặn ảnh quà từ CDN TikTok và LiveBridge chưa có proxy cho ảnh quà): tự vẽ biểu tượng quà trong game nếu cần.
Quy tắc ánh xạ quà: tên quà khớp chính xác > khoảng kim cương (diamondCount x repeatCount nằm trong minDiamonds..maxDiamonds) > hành động có actionId là "default". Streamer có thể đổi ánh xạ bất kỳ lúc nào, nên luôn xử lý cả onGift cho quà chưa ánh xạ.
Quyền riêng tư (streamer chọn cho từng game). Mặc định gửi tên và avatar. Khi streamer tắt tên: user.id thành anon-<16 hex>, user.uniqueId thành viewer-<4 hex>, user.nickname thành Viewer #<4 hex>; mỗi người xem luôn nhận cùng một mã trong cùng phòng và game. user.avatar là URL ảnh qua proxy của LiveBridge (https://livebridge.vn/api/avatar?u=<uniqueId>&s=96, CSP cho phép; chưa có ảnh thì proxy trả ảnh mặc định), không bao giờ là URL CDN TikTok. Khi tắt avatar, và cả khi tắt tên (URL proxy chứa tên thật): user.avatar là "". Game phải hiển thị tốt cả hai trường hợp (ví dụ chữ cái đầu thay avatar).
Chế độ token. Game chỉ có ?t=. Không có ?t= thì SDK ở chế độ demo (không kết nối, không lỗi). Link bị thu hồi (streamer bấm "Ngắt game này", đổi tài khoản TikTok, quản trị gỡ game) thì socket đóng với mã 4003: SDK dừng hẳn và gọi onDisconnect; hãy hiện "Link hết hạn, hãy mở lại game từ LiveBridge". window.__LIVEBRIDGE__.status là idle, open, closed hoặc revoked.
Phải tạo `new LiveBridgeGame({...})` ngay khi trang tải, không chờ người dùng bấm. Bộ kiểm tra tự động mở game trong trình duyệt thật và chờ trạng thái open.
manifest.json
JSON Schema: https://livebridge.vn/schemas/game-manifest.json. Quy tắc:
id: giống id game đã tạo,^[a-z0-9-]{3,40}$, không đổi sau khi tạo; không dùng từ dành riêng (admin,api,app,www,sdk,dev,developers,games,static,cdn,mail,livebridge,test) hay id game có sẵn.version:x.y.z, phải lớn hơn bản đang chạy.name,summary,description: mỗi cái có cảvivàen, không rỗng, không từ không phù hợp.platform:"web".connection:{ "needsApp": false, "sendUsername": true, "sendAvatar": true }(needsAppluônfalse).entry: đường dẫn file HTML chính từ gốc thư mục (phân biệt hoa thường). Game tải lên dùngentry, không dùngurl.cover: ảnh bìa 16:9 (ví dụ 1280x720) có trong thư mục.screenshots: tối đa 8 ảnh.tags: tối đa 5.connectOrigins: danh sách nơi game được phép gọi mạng, dạnghttps://hosthoặcwss://host(chữ thường, không có đường dẫn, không dấu*). Mặc định[].actions: các hành động game làm được, mỗi cái{ id, name, name_vi, description, description_vi }.defaultGiftMapping: ánh xạ gợi ý, mỗi dòng có hoặcgiftNamehoặcminDiamonds(kèmmaxDiamondstuỳ chọn), cộngactionIdphải có trongactions.
Điều cấm
- Không gọi mạng ra ngoài
connectOrigins(fetch, XHR, WebSocket, ảnh, font ngoài danh sách cho phép ở mục CSP). Cần API riêng thì khai báo origin đó trongconnectOrigins. - Không lưu hay gửi dữ liệu người xem đi nơi nào khác: tên, avatar, id, bình luận chỉ dùng để hiển thị trong game, không ghi vào localStorage/cookie/IndexedDB/máy chủ riêng, không đưa vào URL.
- Không hỏi, đọc hay dùng `?key=` hay mã kết nối (room key) của streamer. Game chỉ nhận
?t=. - Không giả định bàn phím hay chuột: game được dùng khi streamer livestream, người điều khiển là người xem qua quà và chat.
- Không dùng dịch vụ phân tích bên ngoài (Google Analytics, Sentry, Mixpanel...) và không nhúng iframe hay script quảng cáo.
- Dữ liệu người xem là không tin cậy: hiển thị bằng
textContent, không bao giờinnerHTML,evalhaydocument.writevới dữ liệu đó. - Không có nội dung vi phạm pháp luật, khiêu dâm, bạo lực cực đoan, thù ghét, hay cờ bạc ăn tiền thật. LiveBridge có quyền gỡ game bất cứ lúc nào (xem điều khoản nhà phát triển).
- Dùng đường dẫn tương đối (
game.js,./img/a.png), không bắt đầu bằng/: game chạy dướihttps://<id-game>.<miền sandbox>/v/<version>/.
CSP (chính sách nội dung của sandbox)
Mọi file của game được trả với CSP này; serve áp dụng đúng như vậy để bạn thấy lỗi sớm:
default-src 'self'.- Script: file của game,
/sdk/của LiveBridge, inline script, WebAssembly ('wasm-unsafe-eval'), và các CDNhttps://cdnjs.cloudflare.com,https://cdn.jsdelivr.net,https://unpkg.com. - Gọi mạng (
fetch, XHR, WebSocket): chính game, API LiveBridge, vàconnectOrigins. - Ảnh, âm thanh, video, font: file của game,
data:,blob:, API LiveBridge, ba CDN trên vàconnectOrigins(https). Google Fonts được phép (CSS từfonts.googleapis.com, font từfonts.gstatic.com). - Web Worker: file của game hoặc
blob:. Không có<object>,<base>,<form action>. - Game được nhúng trong OBS và dashboard (không có
frame-ancestors), nhưng không nhúng trang ngoài.
Cách thử
npx @livebridge/dev serve [thư mục] --port 5173. Giả lập đúng các endpoint token của LiveBridge (/api/game-token/actions|status|manifest,/ws?t=lbg_dev) với token giảlbg_dev. Ánh xạ quà lấy từdefaultGiftMappingtrong manifest.json (khi streamer thật dùng, họ có thể sửa).- Panel
http://localhost:5173/__panel: nút quà (danh sách quà TikTok mẫu, nhập số lần), chat, like x N, follow, share, người vào phòng, "người xem ngẫu nhiên" (tên + avatar), công tắc gửi tên / gửi avatar (xem game thấy gì khi streamer tắt), nút "gửi lại config" (thửonConfig). - Sau mỗi thay đổi: tải lại trang game, rồi
npx @livebridge/dev check. - Khi tải lên, LiveBridge còn mở game trong trình duyệt thật với API giả để kiểm tra: trang phải tải xong trong 20 giây, không có lỗi JavaScript chưa bắt, và SDK phải kết nối.
Checklist trước khi tải lên (mã lỗi và cách sửa)
check và upload in lỗi dạng [mã] (trường) kèm "Cách sửa". Cách sửa thường gặp:
zip_invalid: nén lại bằng zip thường (không mật khẩu, không rar/7z). CLI tự nén nên hiếm gặp.zip_too_big: game giải nén quá 50 MB. Nén ảnh/âm thanh, xoá file thừa, hoặc tải tài nguyên lớn từ CDN.zip_too_many_files: hơn 2.000 file. Gộp JS/CSS, ghép ảnh thành sprite sheet.zip_path_escape: đường dẫn có..,\hoặc bắt đầu bằng/. Đổi tên file.zip_symlink: có liên kết tượng trưng. Thay bằng file thật.zip_duplicate: hai file chỉ khác nhau chữ hoa/thường. Đổi tên.manifest_missing: không cómanifest.jsonở gốc thư mục.manifest_invalid: một trường sai. Đọc tên trường trong lỗi, sửa theo JSON Schema.version_not_newer:versionchưa lớn hơn bản đang chạy. Tăng lên.version_exists: số phiên bản này đã được tải lên. Tăngversion.entry_missing:entrykhông trỏ tới file có thật. Sửa đường dẫn (phân biệt hoa thường).cover_missing: thiếu ảnh bìa (hoặc ảnh trongscreenshots). Thêm file hoặc sửa đường dẫn.file_type_forbidden: chỉ cho phép html htm js mjs css json png jpg jpeg gif webp avif svg ico mp3 ogg wav m4a mp4 webm woff woff2 ttf otf wasm txt map. Xoá file khác.words_blocked: tên/tóm tắt/mô tả có từ không phù hợp. Viết lại.url_not_https,url_unreachable: dành cho gameexternal_web(tải lên từ web, không qua CLI).smoke_timeout: trang không phản hồi trong 20 giây. Tìm vòng lặp vô hạn hoặc tác vụ nặng lúc tải.smoke_js_error: có lỗi JavaScript khi chạy thử. Mở?t=lbg_dev, xem Console, sửa lỗi.smoke_sdk_not_connected: SDK không kết nối. Nạphttps://livebridge.vn/sdk/livebridge.jsvà gọinew LiveBridgeGame({...})ngay khi tải trang.smoke_load_failed: không mở được entry. Kiểm traentryvà file tồn tại.smoke_infra: lỗi phía hệ thống kiểm tra. Tải lại cùng phiên bản sau vài phút, không cần đổi version.sdk_missing(chỉ CLI, chỉ cảnh báo): chưa có file.htmlnào nạp/sdk/livebridge.js.
Giới hạn: tối đa 10 game mỗi nhà phát triển, 20 lần tải lên mỗi ngày, hệ thống giữ file của 5 phiên bản mới nhất.
Cách đọc một lỗi kiểm tra
Mỗi lỗi có mã, trường (nếu có), một câu mô tả và một câu "Cách sửa" bằng tiếng Việt và tiếng Anh. Làm theo thứ tự: (1) sửa lỗi đầu tiên bằng đúng "Cách sửa"; (2) chạy lại check; (3) lặp lại. Nếu nhà phát triển dán cho bạn đoạn bắt đầu bằng LiveBridge upload check failed for <game> v<version>: (nút Sao chép lỗi cho AI trên web hoặc đoạn cuối của check), đó chính là danh sách lỗi: sửa từng mục.