Chatbot AI Pertamamu
Bangun chatbot web dengan streaming jawaban real-time: Next.js, satu API route, satu komponen chat. Fondasi untuk semua project lain.
Next.jsTypeScriptAPI AI (OpenAI-compatible)≈ 45 menit
Kamu akan membangun chatbot yang jawabannya muncul kata demi kata (streaming) — persis seperti ChatGPT. Ini project fondasi: semua project lain di situs ini dibangun di atas polanya.
0. Prasyarat
- Node.js terpasang, paham dasar React/Next.js.
- API key dari provider apa pun yang kompatibel OpenAI (OpenAI, Gemini OpenAI-compat, GLM, dll).
1. Siapkan project dan kunci
npx create-next-app@latest chatbotku --typescript --app --src-dir
cd chatbotku
Buat file .env.local:
AI_BASE_URL=https://api.openai.com/v1
AI_API_KEY=sk-...
AI_MODEL=gpt-4o-mini
Penting: key hanya di server. Jangan pernah dipanggil dari komponen browser.
2. API route streaming
Buat src/app/api/chat/route.ts:
export async function POST(req: Request) {
const { messages } = await req.json();
const res = await fetch(
`${process.env.AI_BASE_URL}/chat/completions`,
{
method: "POST",
headers: {
"content-type": "application/json",
authorization: `Bearer ${process.env.AI_API_KEY}`,
},
body: JSON.stringify({
model: process.env.AI_MODEL,
messages,
stream: true,
}),
}
);
return new Response(res.body, {
headers: { "content-type": "text/plain; charset=utf-8" },
});
}
Kita tidak mengubah data provider sama sekali — cukup meneruskan stream-nya.
3. Komponen chat yang membaca stream
Inti pola streaming di browser: baca potongan dari fetch, tambahkan ke state.
"use client";
import { useState } from "react";
export function Chat() {
const [messages, setMessages] = useState<{role: string; content: string}[]>([]);
const [input, setInput] = useState("");
const [busy, setBusy] = useState(false);
async function kirim() {
const history = [...messages, { role: "user", content: input }];
setMessages([...history, { role: "assistant", content: "" }]);
setInput("");
setBusy(true);
const res = await fetch("/api/chat", {
method: "POST",
body: JSON.stringify({ messages: history }),
});
const reader = res.body!.getReader();
const decoder = new TextDecoder();
for (;;) {
const { done, value } = await reader.read();
if (done) break;
const chunk = decoder.decode(value);
setMessages((prev) => {
const last = prev[prev.length - 1];
return [...prev.slice(0, -1),
{ role: "assistant", content: last.content + chunk }];
});
}
setBusy(false);
}
return (
<div>
{messages.map((m, i) => <p key={i}><b>{m.role}:</b> {m.content}</p>)}
<input value={input} onChange={(e) => setInput(e.target.value)} />
<button onClick={kirim} disabled={busy}>Kirim</button>
</div>
);
}
4. Tambahkan persona
Di API route, sisipkan system prompt sebelum messages dari user:
const withSystem = [
{ role: "system", content: "Kamu asisten ramah berbahasa Indonesia. Jawab singkat dan jelas." },
...messages,
];
Jalankan npm run dev — chatbot kamu hidup, dengan jawaban mengalir real-time.
5. Pola selesai. Tantangan lanjutan
- Simpan riwayat percakapan di
localStorage. - Batasi panjang riwayat (ingat materi context window).
- Tambahkan tombol stop (pakai
AbortController). - Rate limit sederhana di API route (lihat pola di situs ini — kita pakai window per-IP).