Bikin chatbot AI itu dulu requires ML expertise + GPU + bulan-bulan training. Sekarang? 2 jam, satu file Next.js, dan pemahaman Claude API basic. Tutorial ini gue test sendiri — dari blank Vercel project sampai chatbot live, total 1 jam 47 menit.
Customer service chatbot adalah salah satu use case AI paling impactful untuk bisnis. Tapi banyak yang mikir butuh expertise tinggi. Realita-nya, dengan Claude API, lo bisa build production-grade chatbot dalam beberapa jam.
Tutorial ini end-to-end: setup, code, deploy, monitoring. Stack yang gue pake: Claude API + Next.js 15 + Vercel.
Prerequisites
- Account Anthropic dengan API access (claude.com)
- Node.js 20+ installed
- Account Vercel (gratis untuk hobby)
- Basic familiarity dengan React/Next.js
Cost estimate: ~$5 untuk testing + bulan pertama deployment.
Step 1: Setup Project (10 menit)
Bikin Next.js project baru:
npx create-next-app@latest my-chatbot
cd my-chatbot
npm install @anthropic-ai/sdk
Follow prompt, pilih:
- TypeScript: Yes
- ESLint: Yes
- Tailwind: Yes
- App Router: Yes
Setup environment variable di .env.local:
ANTHROPIC_API_KEY=sk-ant-xxxxx
Step 2: API Route untuk Claude (20 menit)
Bikin API route di app/api/chat/route.ts:
import Anthropic from '@anthropic-ai/sdk';
import { NextRequest, NextResponse } from 'next/server';
const anthropic = new Anthropic({
apiKey: process.env.ANTHROPIC_API_KEY,
});
const SYSTEM_PROMPT = `Lo customer service untuk RUSH.IT, blog tech
Indonesia. Jawab dalam bahasa Indonesia santai tapi profesional.
Kalau nggak tau jawaban, jujur bilang dan suggest contact human team.`;
export async function POST(req: NextRequest) {
try {
const { messages } = await req.json();
const response = await anthropic.messages.create({
model: 'claude-sonnet-4-6',
max_tokens: 1024,
system: SYSTEM_PROMPT,
messages: messages,
});
return NextResponse.json({
message: response.content[0].text,
});
} catch (error) {
console.error('API error:', error);
return NextResponse.json(
{ error: 'Something went wrong' },
{ status: 500 }
);
}
}
Yang penting di sini:
- System prompt — define personality dan behavior chatbot
- Model — Sonnet 4.6 sweet spot untuk cost vs quality
- max_tokens — limit response length untuk cost control
Step 3: Frontend Chat UI (30 menit)
Bikin component components/Chat.tsx:
'use client';
import { useState, useRef, useEffect } from 'react';
interface Message {
role: 'user' | 'assistant';
content: string;
}
export default function Chat() {
const [messages, setMessages] = useState<Message[]>([]);
const [input, setInput] = useState('');
const [loading, setLoading] = useState(false);
const messagesEndRef = useRef<HTMLDivElement>(null);
useEffect(() => {
messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
}, [messages]);
async function handleSubmit(e: React.FormEvent) {
e.preventDefault();
if (!input.trim() || loading) return;
const userMessage: Message = { role: 'user', content: input };
const newMessages = [...messages, userMessage];
setMessages(newMessages);
setInput('');
setLoading(true);
try {
const res = await fetch('/api/chat', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ messages: newMessages }),
});
const data = await res.json();
setMessages([...newMessages, {
role: 'assistant',
content: data.message,
}]);
} catch (error) {
setMessages([...newMessages, {
role: 'assistant',
content: 'Maaf, ada error. Coba lagi nanti ya.',
}]);
} finally {
setLoading(false);
}
}
return (
<div className="flex flex-col h-screen max-w-2xl mx-auto">
<div className="flex-1 overflow-y-auto p-4 space-y-4">
{messages.map((msg, i) => (
<div
key={i}
className={`p-4 rounded ${
msg.role === 'user'
? 'bg-blue-100 ml-auto max-w-md'
: 'bg-gray-100 mr-auto max-w-md'
}`}
>
{msg.content}
</div>
))}
{loading && (
<div className="bg-gray-100 p-4 rounded max-w-md">
Typing...
</div>
)}
<div ref={messagesEndRef} />
</div>
<form onSubmit={handleSubmit} className="p-4 border-t">
<div className="flex gap-2">
<input
value={input}
onChange={(e) => setInput(e.target.value)}
placeholder="Ketik pesan..."
className="flex-1 p-3 border rounded"
disabled={loading}
/>
<button
type="submit"
disabled={loading}
className="px-6 bg-blue-500 text-white rounded"
>
Kirim
</button>
</div>
</form>
</div>
);
}
Update app/page.tsx:
import Chat from '@/components/Chat';
export default function Home() {
return <Chat />;
}
Test local: npm run dev, buka localhost:3000.
Setelah step ini lo udah punya chatbot working. Sisa 1 jam buat polish, security, dan deployment.
Step 4: Streaming Response (15 menit)
Default response baru muncul setelah complete generation. Untuk UX yang lebih baik, pakai streaming.
Update API route:
export async function POST(req: NextRequest) {
const { messages } = await req.json();
const stream = await anthropic.messages.stream({
model: 'claude-sonnet-4-6',
max_tokens: 1024,
system: SYSTEM_PROMPT,
messages: messages,
});
const encoder = new TextEncoder();
const readable = new ReadableStream({
async start(controller) {
for await (const event of stream) {
if (event.type === 'content_block_delta') {
const text = event.delta.type === 'text_delta'
? event.delta.text
: '';
controller.enqueue(encoder.encode(text));
}
}
controller.close();
},
});
return new Response(readable, {
headers: { 'Content-Type': 'text/plain; charset=utf-8' },
});
}
Update frontend untuk handle streaming:
// Replace the fetch logic in handleSubmit
const res = await fetch('/api/chat', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ messages: newMessages }),
});
if (!res.body) return;
const reader = res.body.getReader();
const decoder = new TextDecoder();
let assistantMessage = '';
setMessages([...newMessages, { role: 'assistant', content: '' }]);
while (true) {
const { done, value } = await reader.read();
if (done) break;
const text = decoder.decode(value);
assistantMessage += text;
setMessages(prev => {
const updated = [...prev];
updated[updated.length - 1] = {
role: 'assistant',
content: assistantMessage,
};
return updated;
});
}
Step 5: Rate Limiting & Security (15 menit)
Production chatbot wajib ada protection. Install rate limiter:
npm install @upstash/ratelimit @upstash/redis
Setup di API route:
import { Ratelimit } from '@upstash/ratelimit';
import { Redis } from '@upstash/redis';
const ratelimit = new Ratelimit({
redis: Redis.fromEnv(),
limiter: Ratelimit.slidingWindow(10, '1 m'), // 10 req/min
});
export async function POST(req: NextRequest) {
const ip = req.headers.get('x-forwarded-for') ?? 'anonymous';
const { success } = await ratelimit.limit(ip);
if (!success) {
return NextResponse.json(
{ error: 'Rate limit exceeded' },
{ status: 429 }
);
}
// ... rest of the code
}
Daftar Upstash gratis untuk Redis serverless. Setup env variables.
Step 6: Knowledge Base Integration (15 menit)
Untuk chatbot yang lebih useful, tambahin context spesifik bisnis lo. Update system prompt:
const SYSTEM_PROMPT = `Lo customer service untuk RUSH.IT.
KNOWLEDGE BASE:
- RUSH.IT adalah blog tech Indonesia
- Topik utama: SEO, Dev, AI, Cybersec
- Update artikel 2-3x seminggu
- Newsletter rilis tiap Senin
- Email kontak: [email protected]
GUIDELINES:
- Jawab dalam bahasa Indonesia
- Tone: santai tapi profesional
- Kalau pertanyaan complex, redirect ke email kontak
- Jangan reveal informasi internal yang sensitive
- Selalu helpful, never argumentative`;
Untuk knowledge base yang lebih besar, lo bisa pakai:
- Vector database (Pinecone, Weaviate) untuk RAG
- Embedding dari content existing
- Retrieval logic sebelum kirim ke Claude
Tapi untuk MVP, hardcoded knowledge di system prompt cukup.
Step 7: Deploy ke Vercel (10 menit)
# Install Vercel CLI
npm install -g vercel
# Deploy
vercel
Add environment variables di Vercel dashboard:
ANTHROPIC_API_KEYUPSTASH_REDIS_REST_URLUPSTASH_REDIS_REST_TOKEN
Live dalam 2-3 menit.
Step 8: Monitoring & Analytics (10 menit)
Wajib track untuk production:
- Vercel Analytics — page views, performance
- Sentry — error tracking
- Custom logging — log conversation untuk improvement
Simple logging di API route:
// Log to your analytics service
await logConversation({
userId: ip,
userMessage: messages[messages.length - 1].content,
assistantMessage: response.content[0].text,
timestamp: new Date(),
tokenUsage: response.usage,
});
Cost Analysis
Untuk chatbot dengan ~1000 conversations/bulan (rata-rata 5 message exchange):
- Claude Sonnet 4.6 API: ~$15-25/bulan
- Vercel hosting: Gratis (hobby plan)
- Upstash Redis: Gratis (10k commands/day)
Total: $15-25/bulan untuk chatbot production-ready. Compare dengan customer service human Rp 5jt+/bulan — ROI clear.
Optimization Tips
1. Caching Common Queries
Pertanyaan umum bisa di-cache:
- "Jam buka?" → cache jawaban static
- "Cara order?" → cache jawaban
- Pertanyaan complex → tetap call API
2. Prompt Engineering
Iterate system prompt based on real conversation log:
- Identify common failures
- Add specific instructions
- Test variations
3. Fallback to Human
Set threshold untuk redirect ke human team:
- 3x failed answer in same conversation
- Sensitive topics (refund, complaint)
- User explicitly request human
Kesimpulan
Bikin chatbot AI di 2026 = building blocks yang udah tersedia. Tantangan-nya:
- Define use case yang clear
- Iterate prompt continuously
- Monitor & improve based on real data
- Balance otomasi vs human touch
Tutorial ini foundation. Dari sini lo bisa expand:
- Multi-channel (WhatsApp, Telegram via webhook)
- Voice support (text-to-speech)
- Knowledge base dengan RAG
- Multi-agent untuk specialized tasks
Source code lengkap available di GitHub (link akan ditambahkan). Happy building!