# Les 14: AI Chat Interface & Streaming

---

## Hoofdstuk
**Deel 4: Advanced AI & Deployment** (Les 13-18)

## Beschrijving
Bouwen van professionele chat interfaces met streaming responses. Message rendering, markdown support, error handling, loading states, en UX patterns voor AI-powered features.

---

## Te Behandelen (~45 min)

- Chat UI patterns en best practices
- useChat hook deep dive (state, loading, error)
- Streaming response handling en real-time updates
- Message rendering strategies en optimizations
- Markdown rendering in chat messages
- Error handling en error boundaries
- Loading states en skeleton loaders
- User input validation and sanitization
- Accessibility in chat interfaces (ARIA labels)
- Message persistence (localStorage of database)
- Performance optimization

---

### useChat Hook Deep Dive

**State management met useChat:**

```typescript
'use client'
import { useChat } from 'ai/react'

export function ChatComponent() {
  const {
    messages,           // All messages in conversation
    input,             // Current input text
    handleInputChange, // Update input
    handleSubmit,      // Send message
    isLoading,         // Is AI responding?
    error,             // Any errors?
  } = useChat({
    api: '/api/chat',
    initialMessages: [], // Optional: pre-load messages
  })

  return (
    <>
      <div>
        {messages.map((msg) => (
          <div key={msg.id}>
            <strong>{msg.role}:</strong> {msg.content}
          </div>
        ))}
      </div>
      {isLoading && <div>AI is thinking...</div>}
      {error && <div>Error: {error.message}</div>}
      <form onSubmit={handleSubmit}>
        <input
          value={input}
          onChange={handleInputChange}
          disabled={isLoading}
        />
        <button type="submit" disabled={isLoading}>Send</button>
      </form>
    </>
  )
}
```

---

### Message Rendering Patterns

**Basic pattern:**
```typescript
<div className="space-y-4">
  {messages.map((msg) => (
    <div
      key={msg.id}
      className={msg.role === 'user' ? 'ml-auto' : 'mr-auto'}
    >
      <div className="bg-gray-200 p-3 rounded">
        {msg.content}
      </div>
    </div>
  ))}
</div>
```

**With markdown rendering:**
```typescript
import ReactMarkdown from 'react-markdown'

<div className="bg-gray-200 p-3 rounded">
  <ReactMarkdown>{msg.content}</ReactMarkdown>
</div>
```

**With message types:**
```typescript
{messages.map((msg) => (
  <div key={msg.id} className={msg.role === 'user' ? 'user-message' : 'ai-message'}>
    {msg.content}
  </div>
))}
```

---

### Error Handling

**Structured error handling:**

```typescript
try {
  const response = await fetch('/api/chat', {
    method: 'POST',
    body: JSON.stringify({ messages }),
  })

  if (!response.ok) {
    throw new Error(`API error: ${response.status}`)
  }

  // Handle streaming...
} catch (error) {
  console.error('Chat error:', error)
  setError({
    message: 'Failed to send message',
    code: error instanceof Error ? error.message : 'unknown'
  })
}
```

**Error boundary:**
```typescript
<ErrorBoundary fallback={<div>Chat error occurred</div>}>
  <ChatComponent />
</ErrorBoundary>
```

---

### Loading States

**Skeleton loader:**
```typescript
function MessageSkeleton() {
  return (
    <div className="animate-pulse">
      <div className="bg-gray-300 h-4 rounded w-48 mb-2" />
      <div className="bg-gray-300 h-4 rounded w-64" />
    </div>
  )
}

{isLoading && <MessageSkeleton />}
```

---

### Input Validation

**Validate before sending:**

```typescript
function handleSubmit(e: React.FormEvent) {
  e.preventDefault()

  // Trim whitespace
  const trimmedInput = input.trim()

  // Validate non-empty
  if (!trimmedInput) {
    setError('Message cannot be empty')
    return
  }

  // Validate length
  if (trimmedInput.length > 1000) {
    setError('Message too long (max 1000 chars)')
    return
  }

  // Send message
  handleSubmit(e)
}
```

---

### Message Persistence

**Save to localStorage:**

```typescript
const [messages, setMessages] = useState(() => {
  const saved = localStorage.getItem('chat_history')
  return saved ? JSON.parse(saved) : []
})

// Save whenever messages change
useEffect(() => {
  localStorage.setItem('chat_history', JSON.stringify(messages))
}, [messages])
```

**Save to database:**
```typescript
const saveMessage = async (message: Message) => {
  await fetch('/api/messages', {
    method: 'POST',
    body: JSON.stringify({
      content: message.content,
      role: message.role,
      userId: user.id,
    }),
  })
}
```

---

## Tools
- Vercel AI SDK
- React Markdown
- Cursor
- TypeScript

---

## Lesopdracht (2 uur, klassikaal)

### Build Professional Chat Interface

**Groepsdiscussie (15 min):**
Bespreek klassikaal de Vercel AI SDK ervaringen uit Les 13 - welke tool calling patterns werkten goed?

**Deel 1: Chat Component (45 min)**

Build components/ChatInterface.tsx:
1. Use useChat hook
2. Render messages with proper styling
3. User vs AI message styling
4. Input form with validation
5. Tailwind + shadcn/ui components

**Deel 2: Markdown & Error Handling (30 min)**

1. Install react-markdown: `npm install react-markdown`
2. Render AI responses with markdown
3. Add error boundary
4. Show error messages to user
5. Proper loading states

**Deel 3: UX Improvements (30 min)**

1. Auto-scroll to latest message
2. Disable input while loading
3. Show message count/token usage
4. Add clear chat history button
5. Save messages to localStorage

**Deel 4: Testing (15 min)**

Test chat interface locally with various inputs and error scenarios.

### Deliverable
- Werkende chat interface component
- Markdown rendering working
- Error handling implemented
- LocalStorage persistence
- GitHub commit with chat UI

---

## Huiswerk (2 uur)

### Integrate Chat into Your Project

**Deel 1: Project Integration (1 uur)**

1. Add chat component to your app
2. Connect to your API route with tools
3. Style to match your design
4. Test with actual tools/integrations
5. Fix any bugs

**Deel 2: Enhanced Features (30 min)**

Add one of these:
- Message copy button
- Regenerate response option
- Clear history confirmation
- Export chat history
- Message timestamps

**Deel 3: Performance & Polish (30 min)**

1. Optimize re-renders (useMemo, useCallback)
2. Virtual scrolling for long chats
3. Better accessibility (keyboard nav)
4. Mobile responsive tweaks
5. Update docs/AI-DECISIONS.md

### Deliverable
- Chat fully integrated in project
- Enhanced features implemented
- Performance optimized
- GitHub commits with improvements

---

## Leerdoelen

Na deze les kan de student:
- useChat hook volledig begrijpen en gebruiken
- Professionele chat UI patterns implementeren
- Markdown rendering in chat messages
- Error handling en error boundaries toepassen
- Loading states en skeletons bouwen
- User input valideren en sanitizen
- Message persistence (localStorage/DB)
- Accessibility in chat interfaces verbeteren
- Performance optimizations toepassen
- Complete chat feature in Next.js app integreren
