Sematkan KorinAI di halaman HTML apa pun
Tambahkan widget chat KorinAI ke situs mana pun menggunakan skrip CDN tunggal. Tidak perlu framework.
Mulai Cepat
Tersedia Playground HTML siap pakai: Playground. Buka di browser untuk mencoba varian Floating vs Page dan salin kode embed yang dihasilkan.
Sertakan skrip
<!-- jsDelivr (disarankan) -->
<script src="https://cdn.jsdelivr.net/npm/@korinai/embed@latest/dist/embed.js"></script>
<!-- atau unpkg -->
<!-- <script src="https://unpkg.com/@korinai/embed@latest/dist/embed.js"></script> -->Tambah elemen container
<div id="korin-floating-chat"></div>Inisialisasi
Utamakan getAuthToken untuk token berumur pendek. Gunakan situs (origin) HTTPS.
<script>
// window.KorinAI diekspos oleh build IIFE dari CDN
window.KorinAI.init({
target: "#korin-floating-chat",
variant: "floating", // 'floating' | 'page'
// Opsi provider
baseUrl: "https://api.korinai.com",
chatApi: "https://api.korinai.com/api/chat",
language: "id",
// authToken: "TOKEN_STATIS_ANDA", // tidak direkomendasikan
// getAuthToken: async () => "TOKEN_DINAMIS_ANDA", // direkomendasikan
// Opsi bantu (opsional)
ensureStyles: true,
// Properti komponen (diteruskan)
props: {
title: "Chat dengan KorinAI",
showFloatingButton: true,
triggerIconSize: 28,
// Bisa assign props PageChat
variant: "flat",
ui: { showAttach: true },
},
});
// Jika perlu
// window.KorinAI.unmount('#korin-floating-chat');
// window.KorinAI.toggleFloatingChat(true);
</script>Varian
- Widget mengambang: variant: 'floating', mount ke elemen terposisi (mis. pojok kanan bawah).
- Widget halaman penuh: variant: 'page', mount ke container konten biasa.
Anda bahkan bisa memasang keduanya:
<div id="korin-page-chat" style="min-height: 520px"></div>
<div
id="korin-floating-chat"
style="position: fixed; bottom: 24px; right: 24px"
></div>
<script>
window.KorinAI.init({
target: "#korin-page-chat",
variant: "page",
ensureStyles: false,
baseUrl: "https://api.korinai.com",
chatApi: "https://api.korinai.com/api/chat",
language: "id",
props: { variant: "flat" },
});
window.KorinAI.init({
target: "#korin-floating-chat",
variant: "floating",
baseUrl: "https://api.korinai.com",
chatApi: "https://api.korinai.com/api/chat",
language: "id",
props: { title: "Chat" },
});
</script>Catatan
- Utamakan getAuthToken untuk token berumur pendek; hindari hardcode rahasia di HTML.
- Layani skrip CDN melalui HTTPS dan dari origin tepercaya (jsDelivr atau unpkg).
Terjemahan
Anda dapat mengganti teks UI dengan memberikan objek translations (hanya kunci yang Anda perlukan):
<script>
window.KorinAI.init({
target: "#korin-floating-chat",
baseUrl: "https://api.korinai.com",
variant: "floating",
language: "id",
translations: {
en: {
startChat: "Start chat",
thinking: "Thinking…",
preparingExperience: "Setting things up for you…",
},
id: {
startChat: "Mulai Obrolan",
thinking: "Memproses…",
},
},
props: { title: "Chat dengan KorinAI" },
});
</script>Untuk daftar lengkap kunci terjemahan, lihat tipe ChatTranslations di paket @korinai/libs.
Objek terjemahan chat default
Sumber kebenaran ada di packages/korin-libs/contexts/korinai-context.tsx sebagai KORIN_TRANSLATIONS.
export const KORIN_TRANSLATIONS = {
en: {
startChat: "Start Chat",
closeChat: "Close Chat",
newChat: "New Chat",
chatHistory: "Chat History",
loadingConversation: "Loading conversation...",
noChatHistory: "No chat history yet",
startConversation: "Start a conversation to see it here",
previous: "Previous",
next: "Next",
page: "Page",
of: "of",
thinking: "Thinking...",
usingTool: "Using {toolName}...",
attachedFile: "Attached file",
sharedLink: "Shared a link",
failedToLoadHistory: "Failed to load chat history",
tryAgainLater: "Please try again later",
ai: "AI",
helloImYourAIAssistant:
"Hello! I'm your AI assistant. How can I help you today? ",
preparingExperience:
"Preparing your chat experience… Please ensure your API URL and API key are configured.",
templates: "Templates",
fileSizeError: "File size must be less than 10MB",
fileTypeError: "File type not supported",
uploadSuccess: "File uploaded successfully",
uploadFailed: "Upload failed",
dropFile: "Drop your file here",
retry: "Retry",
selectAgent: "Select Agent",
attachFile: "Attach File",
stopGenerating: "Stop generating",
sendMessage: "Send message",
noCredits: "No credits available",
selectFile: "Select File",
},
id: {
startChat: "Mulai Obrolan",
closeChat: "Tutup Obrolan",
newChat: "Obrolan Baru",
chatHistory: "Riwayat Obrolan",
loadingConversation: "Memuat percakapan...",
noChatHistory: "Belum ada riwayat obrolan",
startConversation: "Mulai percakapan untuk melihatnya di sini",
previous: "Sebelumnya",
next: "Selanjutnya",
page: "Halaman",
of: "dari",
thinking: "Memproses...",
usingTool: "Menggunakan {toolName}...",
attachedFile: "Berkas terlampir",
sharedLink: "Membagikan tautan",
failedToLoadHistory: "Gagal memuat riwayat obrolan",
tryAgainLater: "Silakan coba lagi nanti",
ai: "AI",
helloImYourAIAssistant:
"Halo! Saya asisten AI Anda. Ada yang bisa saya bantu? 👋",
preparingExperience:
"Menyiapkan pengalaman chat Anda… Pastikan URL API dan kunci API Anda telah dikonfigurasi.",
templates: "Template",
fileSizeError: "Ukuran file harus kurang dari 10MB",
fileTypeError: "Tipe file tidak didukung",
uploadSuccess: "File berhasil diunggah",
uploadFailed: "Gagal mengunggah",
dropFile: "Letakkan file Anda di sini",
retry: "Coba Lagi",
selectAgent: "Pilih Agen",
attachFile: "Lampirkan File",
stopGenerating: "Hentikan pembuatan",
sendMessage: "Kirim pesan",
noCredits: "Kredit tidak tersedia",
selectFile: "Pilih File",
},
} as const;Pemecahan masalah
- Gaya/posisi aneh: setel ensureStyles: true atau sertakan embed.css dari CDN.
- Error autentikasi: utamakan getAuthToken dan pastikan issuer, scope, serta kedaluwarsa token benar.
- Tidak ada pesan: periksa baseUrl, chatApi (seharusnya https://api.korinai.com/api/chat), dan Network Console.
- Banyak mount: Anda bisa memanggil KorinAI.init dua kali (target berbeda). Gunakan KorinAI.unmount(target) untuk melepas.
Referensi
Gunakan opsi paling penting berikut; detail lengkap tipe tersedia di paket sumber @korinai/embed (TypeScript types):
- target: elemen atau selector CSS tempat mount.
- variant: 'floating' atau 'page'.
- props: properti yang diteruskan ke komponen.
- baseUrl, chatApi, language.
- authToken atau getAuthToken (disarankan).
- translations untuk menimpa teks UI.
InitOptions
| Prop | Tipe | Deskripsi |
|---|---|---|
| target | Element | string | Elemen atau selector CSS tempat mount. |
| variant | 'floating' | 'page' | Varian UI yang dirender. Default: 'floating'. |
| props | Record<string, unknown> | Props yang diteruskan ke komponen yang dirender. Default: {}. |
| ensureStyles | boolean | Sisipkan styling/posisi minimum agar terlihat. Default: true. |
| debugOverlay | boolean | Tampilkan badge kecil “mounted” untuk debug. Default: false. |
| stylesheetHref | string | string[] | Muat stylesheet eksternal bila perlu. |
| verbose | boolean | Log detail ke console. Default: false. |
| baseUrl | string | Base URL API untuk provider. |
| chatApi | string | Endpoint Chat API. |
| configLanguage | string | Field bahasa konfigurasi provider (lanjutan). |
| minimumCreditsWarning | string | Ambang peringatan kredit rendah. |
| authToken | string | Token statis. Utamakan getAuthToken. |
| language | string | Properti bahasa untuk provider. |
| getAuthToken | () => Promise<string> | Pengambil token async. |
| translations | ChatTranslations | Peta i18n opsional untuk menimpa teks bawaan. |
Props FloatingChat
| Prop | Tipe | Deskripsi |
|---|---|---|
| title | string | Judul chat di header. |
| triggerIcon | ReactNode | Konten pemicu kustom (mengganti ikon default). |
| triggerIconSize | number | Ukuran ikon pemicu (px). Default: 28. |
| branding | { logoLightUrl?, logoDarkUrl?, logoSize?: {width:number; height:number}, headerLogoSize?: {width:number; height:number}, showHeaderLogo? } | Opsi branding untuk UI. |
| buttonClassName | string | Kelas tambahan untuk wrapper tombol mengambang. |
| chatWindowClassName | string | Kelas tambahan untuk kontainer jendela chat. |
| open | boolean | State terbuka terkontrol. Pasangkan dengan onOpenChange. |
| defaultOpen | boolean | State terbuka awal (uncontrolled). Default: false. |
| onOpenChange | (open: boolean) => void | Dipanggil saat state open berubah. |
| showFloatingButton | boolean | Apakah tombol pemicu mengambang ditampilkan. Default: true. |
| className | string | Kelas CSS tambahan untuk kontainer luar. |
| title | string | Teks judul header. |
| showCloseButton | boolean | Tampilkan tombol tutup. Default: false. |
| onClose | () => void | Dipanggil saat tombol tutup diklik. |
| hideHistory | boolean | Sembunyikan daftar riwayat. Default: false. |
| pageSize | number | Ukuran halaman riwayat. Default: 10. |
| defaultRoomId | string | Room id awal. |
| showRoomName | boolean | Tampilkan nama room saat ini. Default: true. |
| onRoomChange | (roomId: string) => void | Notifikasi perubahan room. |
| onSend | ({ text: string, roomId: string }) => void | Dipanggil saat kirim pesan. |
| headerRightSlot | ReactNode | Konten kustom di kanan header. |
| variant | 'card' | 'flat' | Gaya visual. Default: 'flat'. |
| chatInputVariant | 'default' | 'compact' | Preset kerapatan input. |
| throttleMs | number | Throttle ketik/kirim pengguna. Default: 0. |
| requestHeaders | Record<string,string> | Header ekstra untuk panggilan API. Default: {}. |
| requestBody | { requesterId?, participantEmail?, participantId?, roomId?, gallery_id?, file_caption?, file_url?, extra_context?, requesterEmail?, messageId?, secrets?: Array<{key:string; value:string}> } | Field body tambahan untuk panggilan API. Default: {}. |
| ui | { showStop?, showAttach?, showActions?, showAgentSelector?, defaultAgentUsername? } | Toggle fitur UI. |
| branding | { logoLightUrl?, logoDarkUrl?, logoSize?: {width:number; height:number}, showHeaderLogo?, headerLogoSize?: {width:number; height:number} } | Branding header dan konten. |
Props PageChat
| Prop | Tipe | Deskripsi |
|---|---|---|
| className | string | Kelas CSS tambahan untuk kontainer luar. |
| title | string | Teks judul header. |
| showCloseButton | boolean | Tampilkan tombol tutup. Default: false. |
| onClose | () => void | Dipanggil saat tombol tutup diklik. |
| hideHistory | boolean | Sembunyikan daftar riwayat. Default: false. |
| pageSize | number | Ukuran halaman riwayat. Default: 10. |
| defaultRoomId | string | Room id awal. |
| showRoomName | boolean | Tampilkan nama room saat ini. Default: true. |
| onRoomChange | (roomId: string) => void | Notifikasi perubahan room. |
| onSend | ({ text: string, roomId: string }) => void | Dipanggil saat kirim pesan. |
| headerRightSlot | ReactNode | Konten kustom di kanan header. |
| variant | 'card' | 'flat' | Gaya visual. Default: 'flat'. |
| chatInputVariant | 'default' | 'compact' | Preset kerapatan input. |
| throttleMs | number | Throttle ketik/kirim pengguna. Default: 0. |
| requestHeaders | Record<string,string> | Header ekstra untuk panggilan API. Default: {}. |
| requestBody | { requesterId?, participantEmail?, participantId?, roomId?, gallery_id?, file_caption?, file_url?, extra_context?, requesterEmail?, messageId?, secrets?: Array<{key:string; value:string}> } | Field body tambahan untuk panggilan API. Default: {}. |
| ui | { showStop?, showAttach?, showActions?, showAgentSelector?, defaultAgentUsername? } | Toggle fitur UI. |
| branding | { logoLightUrl?, logoDarkUrl?, logoSize?: {width:number; height:number}, showHeaderLogo?, headerLogoSize?: {width:number; height:number} } | Branding header dan konten. |
API Publik
- KorinAI.init(options) → { unmount(): void; el: Element }
- KorinAI.unmount(target)
- KorinAI.toggleFloatingChat(open?: boolean)
- Global varian: window.KorinAI.floating, window.KorinAI.page berisi __open, reload(newOptions?), dan bidang diagnostik seperti __version?, __verbose?.
Contoh:
<script>
const { unmount } = window.KorinAI.init({
target: "#korin-floating-chat",
variant: "floating",
baseUrl,
chatApi,
});
// Kemudian
window.KorinAI.toggleFloatingChat(true);
unmount();
// Muat ulang varian floating dengan properti baru saat runtime
window.KorinAI.floating.reload({ props: { showFloatingButton: false } });
</script>