fix: implement lessons feedback

This commit is contained in:
Tim Rijkse
2026-01-30 11:56:39 +01:00
parent 04f32babd3
commit 1e324e2f0e
18 changed files with 3828 additions and 3199 deletions

View File

@@ -1,329 +1,336 @@
# Les 15: Vercel AI SDK - AI Features in je App
# Les 15: MCP & Context Management
---
## Hoofdstuk
**Hoofdstuk 3: Advanced** (Les 10-18)
**Deel 4: Advanced AI Features** (Les 13-18)
## Beschrijving
Bouw AI-powered features in je apps met de Vercel AI SDK. Leer hoe je chat interfaces, streaming responses en AI-gegenereerde content implementeert.
Leer werken met Model Context Protocol (MCP) en geavanceerd context management. Begrijp hoe je AI tools maximale context geeft voor betere resultaten.
---
## Te Behandelen
### Waarom Vercel AI SDK?
### Groepsdiscussie (15 min)
Bespreek klassikaal de project setup ervaringen uit Les 14 - welke structuur conventies werken goed en welke niet?
**Het probleem:** Direct API calls naar OpenAI/Anthropic zijn complex:
- Streaming handmatig implementeren
- Error handling
- State management
### Wat is Context?
**De oplossing:** Vercel AI SDK
- Simpele React hooks
- Built-in streaming
- Provider-agnostic (OpenAI, Anthropic, etc.)
- Edge-ready
**Context = wat de AI weet over jouw situatie**
**Soorten context:**
- **Code context:** welke files, welke functies
- **Project context:** tech stack, conventies
- **Taak context:** wat je probeert te bereiken
- **Historische context:** eerdere conversatie
**Meer context = betere antwoorden**
---
### Installatie & Setup
### Model Context Protocol (MCP)
```bash
npm install ai @ai-sdk/openai
# of voor Anthropic:
npm install ai @ai-sdk/anthropic
**Wat is MCP?**
- Open protocol van Anthropic
- Standaard manier om AI models context te geven
- Verbindt AI met externe tools en data
**Waarom MCP?**
- AI kan nu "tools gebruiken"
- Toegang tot je filesystem
- Database queries uitvoeren
- Web searches doen
- En meer...
**Hoe werkt het:**
```
**Environment variable:**
```bash
# .env.local
OPENAI_API_KEY=sk-xxxxx
Jij → vraag → AI → MCP → Tool → resultaat → AI → antwoord → Jij
```
---
### Core Hooks
### MCP in de Praktijk
#### useChat - Voor Conversaties
**Cursor gebruikt MCP onder de hood:**
- `@file` mentions = file context via MCP
- `@codebase` = codebase search via MCP
- `@Docs` = documentation lookup via MCP
- `@Web` = web search via MCP
```tsx
'use client'
import { useChat } from 'ai/react'
**Claude Desktop met MCP:**
- Kan tools uitvoeren
- Filesystem access
- Terminal commands
- Database queries
export function ChatComponent() {
const { messages, input, handleInputChange, handleSubmit, isLoading } = useChat()
---
return (
<div className="flex flex-col h-screen">
<div className="flex-1 overflow-y-auto p-4">
{messages.map(m => (
<div key={m.id} className={m.role === 'user' ? 'text-right' : 'text-left'}>
<span className="inline-block p-2 rounded-lg bg-gray-100">
{m.content}
</span>
</div>
))}
</div>
### Context Management Strategieën
<form onSubmit={handleSubmit} className="p-4 border-t">
<input
value={input}
onChange={handleInputChange}
placeholder="Type a message..."
className="w-full p-2 border rounded"
/>
<button type="submit" disabled={isLoading}>
{isLoading ? 'Sending...' : 'Send'}
</button>
</form>
</div>
)
}
**1. Expliciete Context**
Geef context direct in je prompt:
```
Context: Next.js 14 project met TypeScript en Supabase.
Dit is een e-commerce app voor verkoop van boeken.
Vraag: Hoe implementeer ik een winkelwagen?
```
#### useCompletion - Voor Single Completions
**2. File Context**
Gebruik @ mentions om relevante files toe te voegen:
```
@src/types/product.ts
@src/lib/supabase.ts
Hoe maak ik een addToCart functie?
```
```tsx
import { useCompletion } from 'ai/react'
**3. Project Context**
Gebruik .cursorrules of Claude Project instructions:
```
# In .cursorrules
Dit project is een e-commerce platform.
Alle prices zijn in cents (niet euros).
```
export function SummaryComponent() {
const { completion, input, handleInputChange, handleSubmit, isLoading } = useCompletion()
**4. Fresh Context**
Begin nieuwe chat voor nieuw onderwerp:
- Voorkomt context vervuiling
- AI raakt niet in de war met oude info
return (
<div>
<form onSubmit={handleSubmit}>
<textarea
value={input}
onChange={handleInputChange}
placeholder="Paste text to summarize..."
/>
<button type="submit">Summarize</button>
</form>
{completion && <p>{completion}</p>}
</div>
)
}
---
### @ Mentions Strategisch Gebruiken
**Cursor @ mentions:**
| Mention | Wanneer | Voorbeeld |
|---------|---------|-----------|
| `@file.tsx` | Specifieke file context | `@Button.tsx hoe voeg ik loading toe?` |
| `@folder/` | Hele folder context | `@components/ welke patterns gebruik ik?` |
| `@codebase` | Zoeken in project | `@codebase waar handle ik auth?` |
| `@Docs` | Officiële documentatie | `@Docs Next.js App Router` |
| `@Web` | Live web search | `@Web Supabase RLS policies` |
**Best practice:** Combineer mentions voor rijke context:
```
@src/components/auth/LoginForm.tsx
@src/lib/supabase.ts
@Docs Supabase Auth
Hoe voeg ik Google OAuth toe aan mijn login?
```
---
### API Routes
### Claude Projects voor Persistente Context
**app/api/chat/route.ts:**
```typescript
import { openai } from '@ai-sdk/openai'
import { streamText } from 'ai'
**Wat kun je toevoegen aan een Project:**
- Instructies (system prompt)
- Files (code, docs, schema's)
- Kennis die over sessies heen blijft
export async function POST(req: Request) {
const { messages } = await req.json()
**Project Instructions Template:**
```markdown
# Project: [Naam]
const result = streamText({
model: openai('gpt-4o-mini'),
system: 'You are a helpful cooking assistant. Suggest recipes based on ingredients.',
messages,
})
## Tech Stack
- Next.js 14 met App Router
- TypeScript strict
- Tailwind CSS
- Supabase
return result.toDataStreamResponse()
}
## Code Conventies
[jouw conventies]
## Database Schema
[beschrijf je schema]
## Current Focus
[waar werk je nu aan]
```
**Met custom system prompt:**
```typescript
const result = streamText({
model: openai('gpt-4o-mini'),
system: `You are a recipe assistant for the AI Recipe Generator app.
When the user provides ingredients:
1. Suggest 2-3 recipes they could make
2. List required additional ingredients (if any)
3. Provide brief cooking instructions
Be concise and practical.`,
messages,
})
```
**Tip:** Upload je database schema, README, en belangrijke types files.
---
### Streaming Responses
### Context Windows en Limieten
**Waarom streaming?**
- Betere UX (user ziet direct resultaat)
- Snellere perceived performance
- Geen wachten op complete response
**Wat is een context window?**
- Maximum hoeveelheid tekst die AI kan "zien"
- Gemeten in tokens (±4 karakters per token)
**Hoe het werkt:**
1. Server stuurt tokens één voor één
2. Client rendert elke token direct
3. User ziet "typing" effect
**Limieten per model:**
| Model | Context Window |
|-------|---------------|
| GPT-4o | 128K tokens |
| Claude 3 Sonnet | 200K tokens |
| Claude 3 Opus | 200K tokens |
**Loading indicator:**
```tsx
{isLoading && (
<div className="flex items-center gap-2">
<div className="animate-pulse"></div>
<span>AI is thinking...</span>
</div>
)}
```
**Praktisch:**
- Lange conversaties → context vol
- Veel file mentions → context vol
- Start fresh chat wanneer nodig
**Signs van vol context:**
- AI vergeet eerdere instructies
- Antwoorden worden minder relevant
- AI herhaalt zichzelf
---
### Integratie met Supabase
### Context Hygiene
**Conversations opslaan:**
**Do's:**
- Geef alleen relevante context
- Wees specifiek in file mentions
- Start nieuwe chat voor nieuw onderwerp
- Gebruik project-level context voor consistentie
```typescript
// Maak tabel in Supabase:
// conversations: id, user_id, created_at
// messages: id, conversation_id, role, content, created_at
// Na elke message:
async function saveMessage(conversationId: string, role: string, content: string) {
await supabase.from('messages').insert({
conversation_id: conversationId,
role,
content
})
}
```
**In je component:**
```tsx
const { messages, input, handleSubmit } = useChat({
onFinish: async (message) => {
await saveMessage(conversationId, message.role, message.content)
}
})
```
**Don'ts:**
- Hele codebase als context geven
- Oude irrelevante chats voortzetten
- Te veel files tegelijk mentionen
- Context herhalen die AI al heeft
---
### Error Handling
### Debugging met Context
```tsx
const { messages, error, reload } = useChat()
**Wanneer AI verkeerde antwoorden geeft:**
{error && (
<div className="p-4 bg-red-100 text-red-700 rounded">
<p>Something went wrong. Please try again.</p>
<button onClick={reload}>Retry</button>
</div>
)}
1. **Check context:** Heeft AI de juiste files?
2. **Check instructies:** Zijn project rules geladen?
3. **Fresh start:** Begin nieuwe chat
4. **Explicieter:** Voeg meer context toe in prompt
**Debug prompt:**
```
Ik merk dat je antwoord niet klopt.
Heb je toegang tot @src/lib/auth.ts?
Dit is de huidige implementatie: [plak code]
Kun je opnieuw kijken?
```
---
### Cost Management
**Model keuze:**
| Model | Kosten | Gebruik voor |
|-------|--------|--------------|
| gpt-4o-mini | Goedkoop | Meeste taken |
| gpt-4o | Duur | Complexe reasoning |
| claude-3-haiku | Goedkoop | Simpele taken |
| claude-3-sonnet | Medium | Balans |
**Bespaartips:**
1. Gebruik gpt-4o-mini als default
2. Korte system prompts
3. Beperk conversation history
4. Caching waar mogelijk
---
## Tools
- Vercel AI SDK (`ai` package)
- Next.js API Routes
- OpenAI API / Anthropic API
- Cursor
- Supabase
- Cursor (@ mentions)
- Claude Projects
- ChatGPT
---
## Lesopdracht (2 uur)
### Bouw een AI Chat Component
### Context Management Oefenen
**Deel 1: Setup (20 min)**
1. `npm install ai @ai-sdk/openai`
2. Voeg `OPENAI_API_KEY` toe aan `.env.local`
3. Maak `app/api/chat/route.ts`
**Deel 1: @ Mentions Mastery (45 min)**
**Deel 2: Basic Chat (40 min)**
1. Maak `components/Chat.tsx`
2. Implementeer `useChat` hook
3. Bouw chat UI met Tailwind
4. Test streaming werkt
Voer deze taken uit in Cursor:
**Deel 3: System Prompt (30 min)**
1. Schrijf system prompt voor je eindproject:
- Recipe Generator: cooking assistant
- Budget Buddy: financial advisor
- Travel Planner: travel expert
2. Test met relevante vragen
1. **Single file context:**
- Open je TodoList component
- Vraag: "@TodoList.tsx Hoe kan ik infinite scroll toevoegen?"
- Noteer kwaliteit antwoord
**Deel 4: Supabase Integratie (30 min)**
1. Maak `messages` tabel
2. Sla berichten op met `onFinish`
3. Laad history bij page load
2. **Multi-file context:**
- Vraag: "@src/components/ @src/types/ Welke types mis ik?"
- Noteer hoe context helpt
3. **Docs context:**
- Vraag: "@Docs Supabase realtime Hoe voeg ik real-time updates toe aan mijn todo app?"
- Noteer of antwoord up-to-date is
4. **Codebase search:**
- Vraag: "@codebase Waar handle ik error states?"
- Noteer of het de juiste plekken vindt
**Deel 2: Claude Project Setup (30 min)**
1. Maak Claude Project voor je eindproject
2. Schrijf comprehensive instructions
3. Upload 3-5 belangrijke files:
- Database schema/types
- Main component
- Supabase client
4. Test met 3 vragen
**Deel 3: Context Vergelijking (45 min)**
Voer dezelfde taak uit met:
1. Geen context (nieuwe chat, geen mentions)
2. File context (@mentions)
3. Project context (Claude Project)
Taak: "Implementeer een search feature voor todos"
Noteer:
- Kwaliteit code
- Relevantie voor jouw project
- Hoeveel aanpassing nodig
### Deliverable
- Werkende AI chat met streaming
- Custom system prompt
- Messages opgeslagen in Supabase
- Notities over @ mentions effectiviteit
- Claude Project met instructions
- Context vergelijkingsnotities
---
## Huiswerk (2 uur)
### Bouw AI Feature voor Eindproject
### Optimaliseer Je Context Strategie
**Deel 1: Core AI Feature (1 uur)**
**Deel 1: .cursorrules Perfectioneren (30 min)**
Implementeer de AI chat die past bij je eindproject:
Update je .cursorrules met:
- Specifieke file structure info
- Naming conventions met voorbeelden
- Common patterns in je project
- DON'Ts specifiek voor jouw situatie
| Project | AI Feature |
|---------|-----------|
| Recipe Generator | "Wat kan ik maken met kip en rijst?" |
| Budget Buddy | "Analyseer mijn uitgaven deze maand" |
| Travel Planner | "Plan een weekend Barcelona" |
**Deel 2: Claude Project Uitbreiden (45 min)**
- Custom system prompt
- Context uit je database meegeven
1. Upload alle relevante project files
2. Test met complexe vragen:
- "Hoe implementeer ik feature X?"
- "Review mijn auth implementatie"
- "Wat ontbreekt er nog?"
3. Itereer op instructions
**Deel 2: UX Polish (30 min)**
**Deel 3: Context Documentation (45 min)**
Voeg toe:
- Streaming indicator
- Suggested prompts / quick actions
- Copy response button
- Clear chat button
- Error handling
Maak `docs/CONTEXT-GUIDE.md`:
```markdown
# Context Guide voor [Project]
**Deel 3: Documentatie (30 min)**
## Cursor @ Mentions
- Voor UI changes: @src/components/
- Voor data logic: @src/lib/ @src/hooks/
- Voor types: @src/types/
Maak `docs/AI-FEATURE.md`:
- Welke AI feature heb je gebouwd?
- Wat doet de system prompt?
- Hoe integreert het met Supabase?
- Welke model keuzes heb je gemaakt?
## Claude Project
- Project URL: [link]
- Uploaded files: [lijst]
- Best practices: [jouw learnings]
## Common Prompts
[verzameling werkende prompts]
```
### Deliverable
- AI feature in eindproject
- Deployed preview
- AI-FEATURE.md documentatie
- Geoptimaliseerde .cursorrules
- Complete Claude Project
- docs/CONTEXT-GUIDE.md
---
## Leerdoelen
Na deze les kan de student:
- Vercel AI SDK installeren en configureren
- `useChat` en `useCompletion` hooks gebruiken
- Streaming responses implementeren
- API routes opzetten voor AI providers
- Custom system prompts schrijven
- Chat history opslaan in Supabase
- Error handling en loading states implementeren
- Kostenbewust omgaan met AI APIs
- Uitleggen wat context is en waarom het belangrijk is
- Model Context Protocol (MCP) begrijpen
- @ mentions strategisch gebruiken in Cursor
- Een Claude Project opzetten met effectieve instructions
- Context windows en limieten begrijpen
- Context management best practices toepassen
- Debuggen wanneer AI verkeerde antwoorden geeft door context issues