Batas klien yang kecil
Tandai hanya modul chat interaktif dengan use client, bukan memindahkan seluruh halaman atau layout ke browser.
Gunakan @openstaticfish/chattybox dalam batas klien yang terfokus, sementara bagian lain aplikasi App Router tetap dirender di server. ChattyBox menangani retrieval, sitasi, percakapan, dan penskalaan.
Percakapan ilustratif — bukan chat langsung.
ChattyBox merayapi situs web, dokumentasi, pusat bantuan, CMS, atau basis pengetahuan yang sudah ada, lalu menyematkan chatbot yang menjawab berdasarkan konten terbitan Anda sendiri, bukan memori model generik.
Instal @openstaticfish/chattybox di aplikasi Next.js.
Tambahkan kunci API widget publik dan URL API sebagai environment variable NEXT_PUBLIC.
Buat komponen klien untuk state chat dan interaksi browser.
Impor komponen klien tersebut dari halaman atau layout Server Component.
Peluncuran tiga langkah
Pertahankan SDK di sisi klien tempat interaksi chat berlangsung dan gunakan Server Components untuk bagian aplikasi lainnya.
Gunakan pos pemeriksaan ini untuk memutuskan apakah ChattyBox harus ditempatkan di samping platform dokumen Anda, menggantikan asisten terpisah, atau tetap terisolasi untuk pengujian.
Tandai hanya modul chat interaktif dengan use client, bukan memindahkan seluruh halaman atau layout ke browser.
Gunakan kunci proyek yang aman untuk browser dengan origin yang diizinkan; jangan pernah mengekspos kredensial pengelolaan melalui variabel NEXT_PUBLIC.
Tampilkan pesan dan sitasi dalam navigasi, area akun, shell dokumentasi, atau alur support Anda sendiri.
Hindari menambahkan route handler hanya untuk mem-proxy API browser terkelola, kecuali produk Anda memiliki kebutuhan server-side yang konkret.
SDK menggunakan fetch dan kredensial proyek yang terlihat di browser, jadi inisialisasikan dalam modul klien. Jangan masukkan secret dan API pengelolaan ke variabel NEXT_PUBLIC.
'use client';
import { useState, type FormEvent } from 'react';
import { Chattybox, ChattyboxError, type ChatResponse } from '@openstaticfish/chattybox';
const chattybox = new Chattybox({
apiKey: process.env.NEXT_PUBLIC_CHATTYBOX_API_KEY!,
baseUrl: process.env.NEXT_PUBLIC_CHATTYBOX_API_URL!,
});
export function Chat() {
const [question, setQuestion] = useState('');
const [answer, setAnswer] = useState<ChatResponse | null>(null);
const [pending, setPending] = useState(false);
const [error, setError] = useState('');
async function ask(event: FormEvent<HTMLFormElement>) {
event.preventDefault();
const message = question.trim();
if (pending || !message || message.length > 2000) return;
setPending(true);
setError('');
try {
setAnswer(await chattybox.sendMessage({
message,
// Same ID includes up to 12 recent saved messages, not the full transcript.
conversationId: answer?.conversationId,
}));
setQuestion('');
} catch (failure) {
setError(failure instanceof ChattyboxError
? failure.status + ': ' + failure.message
: 'Chat could not be completed.');
} finally {
setPending(false);
}
}
const sources = answer?.sources.filter((source) => {
try { return ['https:', 'http:'].includes(new URL(source).protocol); }
catch { return false; }
}) ?? [];
return (
<section aria-label="Chat">
<form onSubmit={ask}>
<label>Question
<input value={question} maxLength={2000} disabled={pending}
onChange={(event) => setQuestion(event.target.value)} />
</label>
<button type="submit" disabled={pending || !question.trim()}>
{pending ? 'Sending...' : 'Send'}
</button>
</form>
{error && <p role="alert">{error}</p>}
<div aria-live="polite" aria-busy={pending}>
<p style={{ whiteSpace: 'pre-wrap' }}>{answer?.message}</p>
{sources.length > 0 && <ul aria-label="Sources">
{sources.map((source, index) => <li key={index}>
<a href={source} target="_blank" rel="noopener noreferrer">{source}</a>
</li>)}
</ul>}
</div>
</section>
);
}
// Import and render <Chat /> from your page or layout. This shows the latest answer, not a saved transcript.
// No automatic retries: see the SDK retry-safety guide before adding retries.Ya. Gunakan dalam komponen klien untuk state chat interaktif dan tampilkan komponen tersebut dari halaman atau layout App Router.
Tidak untuk integrasi browser normal. Kunci widget publik dirancang untuk penggunaan klien dan dapat dibatasi ke origin yang disetujui.
Kunci widget publik mengidentifikasi proyek, tetapi bukan kredensial pengelolaan. Batasi ke origin production dan preview Anda, dan jangan pernah mengekspos secret administratif.
Ya. Panduan instalasi yang dihosting menunjukkan jalur next/script jika Anda memilih UI yang dikelola alih-alih antarmuka SDK kustom.
Tidak perlu kartu kredit
Paket gratis. Tanpa kartu.