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,187 +1,332 @@
# Les 17: Eindopdracht Kickoff
# Les 17: Vercel AI SDK - AI Features in je App
---
## Hoofdstuk
**Hoofdstuk 3: Advanced** (Les 10-18)
**Deel 4: Advanced AI Features** (Les 13-18)
## Beschrijving
Bespreking van de eindopdracht requirements, planning maken, en laatste vragen beantwoorden voordat studenten zelfstandig verder werken.
Bouw AI-powered features in je apps met de Vercel AI SDK. Leer hoe je chat interfaces, streaming responses en AI-gegenereerde content implementeert.
---
## Te Behandelen
### Eindopdracht Overview
### Groepsdiscussie (15 min)
Bespreek klassikaal de Cursor .cursorrules ervaringen uit Les 16 - welke regels zorgen voor betere AI output?
**Wat is de eindopdracht?**
- Bouw een AI-powered web applicatie
- Gebruik alle tools die je hebt geleerd
- Vrije keuze in implementatie
### Waarom Vercel AI SDK?
**Drie voorbeeldprojecten:**
1. **AI Recipe Generator** - Recepten op basis van ingrediënten
2. **Smart Budget Buddy** - Financieel overzicht met AI insights
3. **Travel Planner AI** - Reisplanning met AI suggesties
**Het probleem:** Direct API calls naar OpenAI/Anthropic zijn complex:
- Streaming handmatig implementeren
- Error handling
- State management
**Of:** Eigen idee (met goedkeuring docent)
**De oplossing:** Vercel AI SDK
- Simpele React hooks
- Built-in streaming
- Provider-agnostic (OpenAI, Anthropic, etc.)
- Edge-ready
---
### Requirements Doorlopen
### Installatie & Setup
**Technische vereisten:**
- Next.js 14 met App Router
- TypeScript
- Tailwind CSS
- Supabase (database + auth)
- Vercel AI SDK (chat of completion feature)
- Deployed op Vercel
```bash
npm install ai @ai-sdk/openai
# of voor Anthropic:
npm install ai @ai-sdk/anthropic
```
**Documentatie vereisten:**
- `docs/PROJECT-BRIEF.md` - Project beschrijving
- `docs/PROMPT-LOG.md` - Minimaal 10 prompts
- `docs/AI-DECISIONS.md` - Minimaal 5 beslissingen
- Complete README met setup instructies
**Environment variable:**
```bash
# .env.local
OPENAI_API_KEY=sk-xxxxx
```
---
### Beoordelingscriteria
### Core Hooks
| Criterium | Weging |
|-----------|--------|
| Technische uitvoering | 40% |
| AI integratie | 25% |
| Documentatie (PROMPT-LOG, AI-DECISIONS) | 20% |
| Code kwaliteit & organisatie | 15% |
#### useChat - Voor Conversaties
**Minimale vereisten:**
- App werkt in productie
- Auth + CRUD werkt
- AI feature werkt
- Documentatie compleet
```tsx
'use client'
import { useChat } from 'ai/react'
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>
<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>
)
}
```
#### useCompletion - Voor Single Completions
```tsx
import { useCompletion } from 'ai/react'
export function SummaryComponent() {
const { completion, input, handleInputChange, handleSubmit, isLoading } = useCompletion()
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>
)
}
```
---
### Timeline
### API Routes
**Nu tot deadline:**
- Les 17: Kickoff, planning maken
- Les 18: Werksessie met docent support
- Daarna: Zelfstandig afronden
**app/api/chat/route.ts:**
```typescript
import { openai } from '@ai-sdk/openai'
import { streamText } from 'ai'
**Tips:**
- Focus eerst op werkende MVP
- Dan pas polish
- Documenteer TIJDENS het bouwen
export async function POST(req: Request) {
const { messages } = await req.json()
const result = streamText({
model: openai('gpt-4o-mini'),
system: 'You are a helpful cooking assistant. Suggest recipes based on ingredients.',
messages,
})
return result.toDataStreamResponse()
}
```
**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,
})
```
---
### Veel Voorkomende Vragen
### Streaming Responses
**Q: Mag ik een ander project doen dan de voorbeelden?**
A: Ja, met goedkeuring. Bespreek je idee met de docent.
**Waarom streaming?**
- Betere UX (user ziet direct resultaat)
- Snellere perceived performance
- Geen wachten op complete response
**Q: Moet ik alle AI tools gebruiken?**
A: Je moet minimaal Cursor en Vercel AI SDK gebruiken. De rest is optioneel.
**Hoe het werkt:**
1. Server stuurt tokens één voor één
2. Client rendert elke token direct
3. User ziet "typing" effect
**Q: Wat als ik vastloop?**
A: Documenteer het probleem in PROMPT-LOG, vraag hulp in Les 18.
**Q: Hoeveel prompts moet ik loggen?**
A: Minimaal 10, maar meer is beter. Focus op prompts waarvan je iets leerde.
**Loading indicator:**
```tsx
{isLoading && (
<div className="flex items-center gap-2">
<div className="animate-pulse"></div>
<span>AI is thinking...</span>
</div>
)}
```
---
### Planning Maken
### Integratie met Supabase
**Wat moet je nog doen?**
**Conversations opslaan:**
Maak checklist:
- [ ] Core features compleet
- [ ] AI feature werkt
- [ ] Auth werkt
- [ ] Design afgewerkt
- [ ] Edge cases gehandled
- [ ] Documentatie compleet
- [ ] Deployed en getest
```typescript
// Maak tabel in Supabase:
// conversations: id, user_id, created_at
// messages: id, conversation_id, role, content, created_at
**Prioriteer:**
1. Wat werkt nog niet?
2. Wat is kritiek vs nice-to-have?
3. Hoeveel tijd heb je?
// 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)
}
})
```
---
### Error Handling
```tsx
const { messages, error, reload } = useChat()
{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>
)}
```
---
### 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
- Alle geleerde tools
- Supabase
---
## Lesopdracht (2 uur)
### Plan Je Afronding
### Bouw een AI Chat Component
**Deel 1: Status Check (30 min)**
**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`
Beantwoord voor jezelf:
1. Welke features werken al?
2. Welke features missen nog?
3. Wat is je grootste blocker?
4. Hoe staat je documentatie ervoor?
**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
Maak een eerlijke inschatting.
**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
**Deel 2: Planning Maken (30 min)**
Maak gedetailleerde planning:
- Wat doe je vandaag?
- Wat doe je in Les 18?
- Wat doe je thuis?
- Wanneer ben je klaar?
**Deel 3: Begin Met Hoogste Prioriteit (1 uur)**
Start met de belangrijkste ontbrekende onderdelen:
- Werkt je AI feature? → Prioriteit 1
- Werkt auth? → Prioriteit 2
- Is het deployed? → Prioriteit 3
Vraag hulp als je vastloopt!
**Deel 4: Supabase Integratie (30 min)**
1. Maak `messages` tabel
2. Sla berichten op met `onFinish`
3. Laad history bij page load
### Deliverable
- Statusoverzicht: wat werkt, wat niet
- Planning voor afronden
- Voortgang op hoogste prioriteit
- Werkende AI chat met streaming
- Custom system prompt
- Messages opgeslagen in Supabase
---
## Huiswerk
## Huiswerk (2 uur)
### Werk aan je Eindopdracht
### Bouw AI Feature voor Eindproject
**Dit is geen nieuw huiswerk - gebruik deze tijd om je eindopdracht af te ronden.**
**Deel 1: Core AI Feature (1 uur)**
Focus op:
1. Features compleet maken
2. Bugs fixen
3. Documentatie bijwerken
4. Testen in productie
Implementeer de AI chat die past bij je eindproject:
**Bereid vragen voor:**
Schrijf op waar je hulp bij nodig hebt voor Les 18 (werksessie).
| 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" |
- Custom system prompt
- Context uit je database meegeven
**Deel 2: UX Polish (30 min)**
Voeg toe:
- Streaming indicator
- Suggested prompts / quick actions
- Copy response button
- Clear chat button
- Error handling
**Deel 3: Documentatie (30 min)**
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?
### Deliverable
- Voortgang op eindopdracht
- Lijst met vragen voor Les 18
- AI feature in eindproject
- Deployed preview
- AI-FEATURE.md documentatie
---
## Leerdoelen
Na deze les kan de student:
- De eindopdracht requirements begrijpen
- Een realistische planning maken
- Prioriteiten stellen voor afronden
- Eigen voortgang eerlijk inschatten
- Hulp vragen waar nodig
- 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