fix: lessons
This commit is contained in:
@@ -11,8 +11,8 @@
|
||||
|
||||
---
|
||||
|
||||
## Hoofdstuk
|
||||
**Hoofdstuk 1: Fundamentals** (Les 1-3)
|
||||
## Deel
|
||||
**Deel 1 — AI Foundations** (Les 1-3)
|
||||
|
||||
## Beschrijving
|
||||
Kennismaking met AI, LLMs, ChatGPT en de basis van prompt engineering. Praktische workflow van schets op papier naar werkende website met v0.dev.
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
---
|
||||
|
||||
## Hoofdstuk
|
||||
**Deel 1: AI Foundations** (Les 1-4)
|
||||
## Deel
|
||||
**Deel 1 — AI Foundations** (Les 1-3)
|
||||
|
||||
## Beschrijving
|
||||
Introductie tot OpenCode: een open-source AI coding assistant met 60.000+ GitHub stars. Na een korte demo van de terminal versie werken studenten met de **Desktop App** (met ingebouwde terminal). Met OpenCode Zen (gratis, geen API key nodig) leren ze de volledige development workflow: lokaal draaien, uitbreiden met AI, en deployen via git push.
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
|
||||
---
|
||||
|
||||
## Hoofdstuk
|
||||
**Deel 1: AI Foundations** (Les 1-4)
|
||||
## Deel
|
||||
**Deel 1 — AI Foundations** (Les 1-3)
|
||||
|
||||
## Context
|
||||
Oorspronkelijk zou les 3 gaan over AI Ethics, Privacy & Security. Tim heeft besloten om in plaats daarvan een praktische les over Cursor te geven. Dit sluit beter aan bij wat studenten nodig hebben en was een goede keuze — studenten waren enthousiast.
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
---
|
||||
|
||||
## Hoofdstuk
|
||||
**Deel 2: Technical Foundations** (Les 4-9)
|
||||
## Deel
|
||||
**Deel 2 — Technical Foundations** (Les 4-10)
|
||||
|
||||
## Beschrijving
|
||||
Introductie tot TypeScript: waarom het waardevol is, hoe je types schrijft, en de basis die nodig is om straks React/Next.js te typen. Deel 1 van 2 TypeScript-lessen.
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
---
|
||||
|
||||
## Hoofdstuk
|
||||
**Deel 2: Technical Foundations** (Les 4-8)
|
||||
## Deel
|
||||
**Deel 2 — Technical Foundations** (Les 4-10)
|
||||
|
||||
## Beschrijving
|
||||
Introductie Next.js voor React developers. App Router, routing, server/client components, data fetching. Hands-on: QuickPoll app Part 1 (stap 0-3) klassikaal bouwen.
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
---
|
||||
|
||||
## Hoofdstuk
|
||||
**Deel 2: Technical Foundations** (Les 4-8)
|
||||
## Deel
|
||||
**Deel 2 — Technical Foundations** (Les 4-10)
|
||||
|
||||
## Beschrijving
|
||||
Vervolg Next.js: API Routes, Middleware, Deployment. Hands-on: QuickPoll app Part 2 (stap 4-7) klassikaal afbouwen en deployen.
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
---
|
||||
|
||||
## Hoofdstuk
|
||||
**Deel 2: Technical Foundations** (Les 4-9)
|
||||
## Deel
|
||||
**Deel 2 — Technical Foundations** (Les 4-10)
|
||||
|
||||
## Beschrijving
|
||||
Eerste kennismaking met Supabase. Studenten maken hun QuickPoll uit Les 6 af, leren wat een relationele database is via de Supabase GUI (geen SQL nodig), en koppelen voor het eerst een echte database aan hun Next.js app.
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
---
|
||||
|
||||
## Hoofdstuk
|
||||
**Deel 2: Technical Foundations** (Les 4-9)
|
||||
## Deel
|
||||
**Deel 2 — Technical Foundations** (Les 4-10)
|
||||
|
||||
## Beschrijving
|
||||
Vervolg op Les 7. Studenten kregen vorige les niet alles af, dus loopt de docent de Supabase-koppeling rustig opnieuw door — nu in een **self-paced PDF** met copy-paste blokken en TODO-blokken. Daarna bouwen studenten zelfstandig de **/create pagina** (hun eerste INSERT).
|
||||
|
||||
@@ -1,96 +1,77 @@
|
||||
# Les 9: Cursor Deep Dive (Student Plan)
|
||||
# Les 9: Supabase Auth — Eerste Login Flow
|
||||
|
||||
> ✅ **Deze les is volledig uitgewerkt**
|
||||
|
||||
## Lesmateriaal
|
||||
|
||||
- [Slide Overzicht](../Les09-Supabase-Auth/Les09-Slide-Overzicht.md)
|
||||
- [Docenttekst](../Les09-Supabase-Auth/Les09-Docenttekst.md)
|
||||
- [Lesstof](../Les09-Supabase-Auth/Les09-Lesstof.md)
|
||||
- [Lesopdracht](../Les09-Supabase-Auth/Les09-Lesopdracht.md)
|
||||
- [Huiswerk](../Les09-Supabase-Auth/Les09-Huiswerk.md)
|
||||
- [Live Coding Guide](../Les09-Supabase-Auth/Les09-Live-Coding-Guide.md)
|
||||
|
||||
---
|
||||
|
||||
## Hoofdstuk
|
||||
**Deel 2: Technical Foundations** (Les 4-9)
|
||||
## Deel
|
||||
**Deel 2 — Technical Foundations** (Les 4-10)
|
||||
|
||||
## Beschrijving
|
||||
Studenten hebben Cursor met het Student Plan. Tijd voor een deep dive in de 5 professionele workflows: **Rules & Skills, Plan Mode, Agent Mode, Debug Mode, en Code Review & Testing**. We bouwen een nieuwe app from scratch: **LinkVault** (bookmark manager, in-memory, Next.js 16 + TypeScript + Tailwind).
|
||||
Eerste kennismaking met Supabase Auth in de QuickPoll-app: `signUp`, `signIn`, `signOut`, een werkende Navbar met sessie-status en een middleware die routes beschermt. We sluiten af met een eerste blik op Row Level Security (RLS).
|
||||
|
||||
---
|
||||
|
||||
## Lesopbouw (3 uur)
|
||||
## Te Behandelen
|
||||
|
||||
| Tijd | Onderwerp | Vorm |
|
||||
|------|-----------|------|
|
||||
| 09:00–09:10 | Welkom + terugblik | Klassikaal |
|
||||
| 09:10–09:35 | Theorie: Agent Harness, Rules, Plan/Debug/Review Mode | Klassikaal |
|
||||
| 09:35–09:55 | Setup: nieuw project + 3 `.cursor/rules` bestanden | Samen |
|
||||
| 09:55–10:15 | Plan Mode: plan LinkVault → review → Build | Klassikaal |
|
||||
| 10:15–10:30 | Pauze | — |
|
||||
| 10:30–11:05 | Agent Mode: features bouwen | Klassikaal |
|
||||
| 11:05–11:25 | Debug Mode: deterministische bug vinden en fixen | Klassikaal |
|
||||
| 11:25–11:45 | Code Review & Testing + semantic commits + git push | Klassikaal |
|
||||
| 11:45–11:55 | (Optioneel) PR review met Cursor | Klassikaal |
|
||||
| 11:55–12:00 | Afsluiting + huiswerk | Klassikaal |
|
||||
### Theorie
|
||||
- Waarom je auth nooit zelf moet bouwen
|
||||
- Supabase Auth in vogelvlucht (e-mail, magic link, OAuth)
|
||||
- Sessie-cookies en `@supabase/ssr` in Next.js 16
|
||||
- Middleware-patroon voor beschermde routes
|
||||
- Eerste introductie van RLS: "wie mag wat zien?"
|
||||
|
||||
---
|
||||
|
||||
## De 5 Kernvaardigheden
|
||||
|
||||
### 1. Rules & Skills
|
||||
- `.cursor/rules/` directory met `.mdc` bestanden (YAML frontmatter)
|
||||
- 3 bestanden: `project.mdc` (alwaysApply), `components.mdc` (globs: tsx), `styles.mdc` (globs: css/tsx)
|
||||
- Houd rules kort, specifiek, en wijs naar voorbeelden
|
||||
|
||||
### 2. Plan Mode
|
||||
- `Shift+Tab` → agent researcht, stelt vragen, maakt interactief plan
|
||||
- Plan bewerken in markdown → "Build" klikken
|
||||
- Start elke feature met een plan
|
||||
|
||||
### 3. Agent Mode
|
||||
- Agent = uitvoeren (files, terminal, multi-file). Ask = alleen vragen.
|
||||
- Goede context geven: `@file`, `@folder`, `@codebase`, `@docs`
|
||||
- Itereren met screenshots en feedback
|
||||
|
||||
### 4. Debug Mode
|
||||
- Voor complexe bugs: hypotheses → logging → reproduceren → analyseren → fix
|
||||
- Tim introduceert bug handmatig (deterministic) → studenten debuggen
|
||||
|
||||
### 5. Code Review & Testing
|
||||
- "Find Issues" voor self-review
|
||||
- Tests schrijven met Agent Mode
|
||||
- Semantic commits: achteraf changes opdelen in logische groepen
|
||||
- (Optioneel) PR review met Cursor
|
||||
### Live coding
|
||||
- `signUp` + `signIn` server actions
|
||||
- Navbar component met `user`-prop
|
||||
- `signOut` server action + redirect
|
||||
- `middleware.ts` met `updateSession`
|
||||
- RLS-policy voor `polls` tabel
|
||||
|
||||
---
|
||||
|
||||
## Tools
|
||||
- Cursor (Student Plan)
|
||||
- Next.js 16
|
||||
- TypeScript
|
||||
- Tailwind CSS
|
||||
- Supabase (Auth + Postgres + RLS)
|
||||
- Next.js 16 App Router + Server Actions
|
||||
- `@supabase/ssr`
|
||||
- TypeScript + Tailwind CSS
|
||||
|
||||
---
|
||||
|
||||
## Lesmateriaal
|
||||
- `Les09-Slide-Overzicht.md`
|
||||
- `Les09-Docenttekst.md`
|
||||
- `Les09-Huiswerk.md`
|
||||
## Lesopdracht (in-class, 60 min)
|
||||
|
||||
Bouw de signup + login + Navbar in je eigen QuickPoll-fork:
|
||||
- `/signup` en `/login` routes met server actions
|
||||
- Navbar toont "Inloggen" of "Uitloggen" op basis van sessie
|
||||
- `middleware.ts` blokkeert `/create` voor anonieme bezoekers
|
||||
- Werkende redirect na succesvolle login
|
||||
|
||||
**Inleveren:** GitHub repo + screenshot van werkende flow.
|
||||
|
||||
---
|
||||
|
||||
## Huiswerk (take-home)
|
||||
- Voeg een `/profile` pagina toe die alleen ingelogd zichtbaar is
|
||||
- Toon e-mailadres en gebruikers-ID
|
||||
- Schrijf een korte RLS-policy zodat gebruikers alleen hun eigen polls zien
|
||||
- Reflectie van 300 woorden: wat is het verschil tussen authenticatie en autorisatie?
|
||||
|
||||
**Inleveren:** Via Teams/Brightspace.
|
||||
|
||||
---
|
||||
|
||||
## Leerdoelen
|
||||
Na deze les kan de student:
|
||||
- Uitleggen hoe een coding agent werkt (harness: instructions + tools + model)
|
||||
- `.cursor/rules` opzetten met meerdere bestanden (alwaysApply, globs)
|
||||
- Plan Mode gebruiken om een feature te plannen
|
||||
- Agent Mode inzetten voor multi-file feature development
|
||||
- Debug Mode gebruiken voor systematisch debuggen
|
||||
- Code review doen met "Find Issues" en tests schrijven
|
||||
- Semantic commits maken en een PR aanmaken
|
||||
- Een app from scratch bouwen met alle 5 technieken
|
||||
|
||||
---
|
||||
|
||||
## Voorbereiding docent
|
||||
- [ ] `npx create-next-app@latest` getest
|
||||
- [ ] 3 `.cursor/rules` bestanden voorbereid
|
||||
- [ ] Plan Mode demo doorgelopen
|
||||
- [ ] Bug voor Debug Mode voorbereid (tag.toUpperCase() in filter)
|
||||
- [ ] GitHub repo klaar voor push demo
|
||||
|
||||
---
|
||||
|
||||
*Laatste update: april 2026*
|
||||
- Het verschil tussen authenticatie en autorisatie uitleggen
|
||||
- Een werkende signup/login/logout-flow bouwen met Supabase Auth
|
||||
- Een Next.js middleware schrijven die routes beschermt
|
||||
- Een eerste RLS-policy formuleren en activeren
|
||||
|
||||
@@ -1,116 +1,77 @@
|
||||
# Les 10: Styling: Tailwind CSS & shadcn/ui
|
||||
# Les 10: Supabase Auth & Row Level Security — Verdieping
|
||||
|
||||
> ✅ **Deze les is volledig uitgewerkt**
|
||||
|
||||
## Lesmateriaal
|
||||
|
||||
- [Slide Overzicht](../Les10-Supabase-Auth/Les10-Slide-Overzicht.md)
|
||||
- [Docenttekst](../Les10-Supabase-Auth/Les10-Docenttekst.md)
|
||||
- [Lesstof](../Les10-Supabase-Auth/Les10-Lesstof.md)
|
||||
- [Lesopdracht / Hands-on](../Les10-Supabase-Auth/Les10-Lesopdracht.md)
|
||||
- [Huiswerk](../Les10-Supabase-Auth/Les10-Huiswerk.md)
|
||||
|
||||
---
|
||||
|
||||
## Hoofdstuk
|
||||
**Deel 3: Full-Stack Development** (Les 9-12)
|
||||
## Deel
|
||||
**Deel 2 — Technical Foundations** (Les 4-10)
|
||||
|
||||
## Beschrijving
|
||||
Styling je applicatie met Tailwind CSS en modern components met shadcn/ui. Utility-first approach, component libraries, themeing en dark mode implementatie.
|
||||
Vervolg op Les 9: we bouwen de complete auth-flow uit met sessie-management, beschermde routes en gedegen RLS-policies. De QuickPoll-app krijgt een professioneel niveau van autorisatie en is daarmee klaar voor de AI-lessen.
|
||||
|
||||
---
|
||||
|
||||
## Te Behandelen (~45 min)
|
||||
## Te Behandelen
|
||||
|
||||
- Waarom Tailwind? Utility-first CSS approach vs traditioneel CSS
|
||||
- Tailwind in Next.js (meestal al ingesteld)
|
||||
- Core utilities: spacing, colors, flexbox, grid, responsive (mobile-first)
|
||||
- Tailwind components: buttons, cards, forms patterns
|
||||
- Wat is shadcn/ui? Beautifully designed component library
|
||||
- shadcn/ui installatie en configuratie
|
||||
- shadcn/ui components: Button, Card, Input, Dialog, etc.
|
||||
- Custom Tailwind color themes (tailwind.config.ts)
|
||||
- Dark mode implementation met Tailwind
|
||||
- Performance: class optimization, purging unused styles
|
||||
### Theorie
|
||||
- Drie auth-methodes in Supabase (e-mail/password, magic link, OAuth)
|
||||
- Hoe sessies werken (JWT, refresh tokens, cookies)
|
||||
- Server- vs. client-componenten in Next.js voor auth
|
||||
- Row Level Security in detail: `using` vs. `with check`, `auth.uid()`
|
||||
- Beschermde routes via middleware vs. server components
|
||||
|
||||
### Hands-on
|
||||
- Supabase Auth provider configureren in dashboard
|
||||
- Login + registratie pagina's met error handling
|
||||
- Sessie ophalen in server components
|
||||
- Drie RLS-policies: read-eigen, insert-eigen, update-eigen
|
||||
- Test scenario: hoe weet je dat RLS écht werkt?
|
||||
|
||||
---
|
||||
|
||||
## Tools
|
||||
- Tailwind CSS
|
||||
- shadcn/ui
|
||||
- Cursor
|
||||
- TypeScript
|
||||
- Supabase (Auth + RLS)
|
||||
- Next.js 16 App Router
|
||||
- `@supabase/ssr` + `@supabase/supabase-js`
|
||||
- TypeScript + Tailwind CSS
|
||||
|
||||
---
|
||||
|
||||
## Lesopdracht (2 uur, klassikaal)
|
||||
## Lesopdracht (in-class, 60 min)
|
||||
|
||||
### Styling Je Mini-Project
|
||||
Uitbreiding van de QuickPoll-app:
|
||||
- Authenticatie volledig werkend (signup, login, logout, sessie)
|
||||
- Beschermde `/create` en `/my-polls` routes
|
||||
- RLS-policies geactiveerd op `polls` en `options`
|
||||
- "My Polls" pagina toont alleen polls van ingelogde gebruiker
|
||||
|
||||
**Groepsdiscussie (15 min):**
|
||||
Bespreek klassikaal de Full-Stack Mini Project ervaringen uit Les 9 - welke onderdelen werkten goed en waar liepen jullie vast?
|
||||
|
||||
**Deel 1: Tailwind Basics (30 min)**
|
||||
|
||||
1. Open je mini-project uit Les 9
|
||||
2. Refactor bestaande components met Tailwind classes:
|
||||
- Button: `bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded`
|
||||
- Card: `bg-white rounded-lg shadow-lg p-6`
|
||||
- Form inputs: `w-full px-3 py-2 border border-gray-300 rounded-md`
|
||||
3. Voeg spacing, colors, responsive design toe
|
||||
|
||||
**Deel 2: shadcn/ui Setup & Components (45 min)**
|
||||
|
||||
1. Install shadcn/ui: `npx shadcn-ui@latest init`
|
||||
2. Install components: `npx shadcn-ui@latest add button input card dialog`
|
||||
3. Replace je custom components met shadcn versions
|
||||
4. Test styling en interactiviteit
|
||||
|
||||
**Deel 3: Theme & Dark Mode (30 min)**
|
||||
|
||||
1. Customize Tailwind color scheme in `tailwind.config.ts`
|
||||
2. Voeg dark mode toggle toe (localStorage + CSS class toggle)
|
||||
3. Zorg dat je hele app responsive is (mobile-first)
|
||||
|
||||
### Deliverable
|
||||
- Gerestyled mini-project met Tailwind + shadcn/ui
|
||||
- Dark mode toggle werkend
|
||||
- Mobile responsive design
|
||||
- GitHub commit met improvements
|
||||
**Inleveren:** GitHub repo + screen-recording van werkende auth-flow.
|
||||
|
||||
---
|
||||
|
||||
## Huiswerk (2 uur)
|
||||
## Huiswerk (take-home)
|
||||
- Voeg "Edit poll" toe die alleen werkt voor eigenaar (RLS-check)
|
||||
- Voeg "Delete poll" toe met confirm-dialog
|
||||
- Test wat er gebeurt als je de RLS-policy uitzet (security demo)
|
||||
- Reflectie van 500 woorden: waarom is RLS beter dan auth-checks in code?
|
||||
|
||||
### Vervolg Styling & Polish
|
||||
|
||||
**Deel 1: Component Library Uitbreiden (1 uur)**
|
||||
|
||||
Install en integreer meer shadcn/ui components:
|
||||
- Select, Tabs, Modal/Dialog
|
||||
- Forms package voor betere form handling
|
||||
- Toast notifications
|
||||
- Zorg dat je hele app consistent gelayout is
|
||||
|
||||
**Deel 2: Custom Theme (30 min)**
|
||||
|
||||
Maak je eigen color palette in `tailwind.config.ts`:
|
||||
- Primary, secondary, accent colors
|
||||
- Custom spacing, typography
|
||||
- Test in light en dark mode
|
||||
|
||||
**Deel 3: Accessibility & Polish (30 min)**
|
||||
|
||||
1. Voeg alt text toe aan images
|
||||
2. Zorg voor proper heading hierarchy
|
||||
3. Test keyboard navigation
|
||||
4. Fix UI inconsistencies
|
||||
|
||||
### Deliverable
|
||||
- Compleet gestylde mini-project
|
||||
- Alle shadcn/ui components correct geintegreerd
|
||||
- Custom color theme
|
||||
- GitHub commits met styling improvements
|
||||
**Inleveren:** Via Teams/Brightspace.
|
||||
|
||||
---
|
||||
|
||||
## Leerdoelen
|
||||
|
||||
Na deze les kan de student:
|
||||
- Tailwind utility-first approach begrijpen en toepassen
|
||||
- shadcn/ui components installeren en gebruiken
|
||||
- Custom Tailwind themes maken
|
||||
- Dark mode implementeren
|
||||
- Responsive design (mobile-first) toepassen
|
||||
- Professional-looking UI bouwen met componenten
|
||||
- Het verschil tussen styling approaches begrijpen
|
||||
- Een complete auth-flow opzetten in Next.js + Supabase
|
||||
- Sessies veilig beheren via cookies + middleware
|
||||
- Effectieve RLS-policies schrijven met `auth.uid()`
|
||||
- Verschil uitleggen tussen auth in code vs. auth in database
|
||||
- Een poll-app maken die multi-user-veilig is
|
||||
|
||||
@@ -1,233 +1,77 @@
|
||||
# Les 11: Van Idee naar Prototype
|
||||
# Les 11: Vercel AI SDK — Praat met je eigen data
|
||||
|
||||
> ✅ **Deze les is volledig uitgewerkt**
|
||||
|
||||
## Lesmateriaal
|
||||
|
||||
- [Slide Overzicht](../Les11-AI-SDK/Les11-Slide-Overzicht.md)
|
||||
- [Docenttekst](../Les11-AI-SDK/Les11-Docenttekst.md)
|
||||
- [Lesstof](../Les11-AI-SDK/Les11-Lesstof.md)
|
||||
- [Lesopdracht](../Les11-AI-SDK/Les11-Lesopdracht.md)
|
||||
- [Huiswerk](../Les11-AI-SDK/Les11-Huiswerk.md)
|
||||
|
||||
---
|
||||
|
||||
## Hoofdstuk
|
||||
**Deel 3: Full-Stack Development** (Les 9-12)
|
||||
## Deel
|
||||
**Deel 3 — AI Development** (Les 11-16)
|
||||
|
||||
## Beschrijving
|
||||
Proces van vaag idee naar werkend prototype. Feature breakdown, component thinking, MVP planning, user stories, en voorbereiding op eindproject. Kiezen van eindproject idea en architectuur opzetten.
|
||||
Eerste echte AI-les. We bouwen een Next.js-app from scratch, koppelen Supabase, seeden 500 fictieve bands van het "Polderfest 2027" festival en laten studenten met natuurlijke taal vragen stellen aan hun eigen data via de Vercel AI SDK.
|
||||
|
||||
---
|
||||
|
||||
## Te Behandelen (~45 min)
|
||||
## Te Behandelen
|
||||
|
||||
- Hoe ga je van vaag idee naar concrete features?
|
||||
- Feature breakdown method en AI-hulp
|
||||
- Component thinking: UI opdelen in herbruikbare stukken
|
||||
- MVP (Minimum Viable Product) denken
|
||||
- User stories schrijven (As a user I want to...)
|
||||
- Prioritizing features: must-have, nice-to-have, later
|
||||
- Database schema planning voor je idee
|
||||
- Project architecture design
|
||||
- Folder structure planning
|
||||
- Eindproject idee kiezen (vereenvoudigde versie)
|
||||
### Theorie
|
||||
- Waarom een AI SDK i.p.v. de OpenAI API direct
|
||||
- De vier kern-functies: `generateText`, `streamText`, `generateObject`, `streamObject`
|
||||
- Provider-agnostic werken (OpenAI ↔ Anthropic ↔ Google ↔ Groq)
|
||||
- Streaming en de UX-impact
|
||||
- "Praat met je data": pattern voor LLM + database
|
||||
|
||||
---
|
||||
|
||||
### Van Idee naar Feature Breakdown
|
||||
|
||||
**Stap 1: Beschrijf je idee in 1 zin**
|
||||
```
|
||||
"Ik wil een app waar je recepten kan zoeken op basis van ingrediënten die je hebt"
|
||||
```
|
||||
|
||||
**Stap 2: Werk uit wat gebruikers willen**
|
||||
```
|
||||
User stories:
|
||||
- Als gebruiker wil ik ingrediënten kunnen invoeren
|
||||
- Als gebruiker wil ik recepten suggesties krijgen
|
||||
- Als gebruiker wil ik recepten kunnen opslaan
|
||||
```
|
||||
|
||||
**Stap 3: Break down in features**
|
||||
```
|
||||
Core Features:
|
||||
- Ingredient input form
|
||||
- Recipe search/filter
|
||||
- Save favorites
|
||||
- View saved recipes
|
||||
|
||||
Nice-to-have:
|
||||
- Meal planning
|
||||
- Shopping list generator
|
||||
- Nutritional info
|
||||
- Export recipes
|
||||
```
|
||||
|
||||
**Stap 4: Prioriteer (MVP)**
|
||||
- ✅ Input form + recipe search
|
||||
- ✅ Display results
|
||||
- ✅ Save/favorites
|
||||
- ❌ Shopping list (later)
|
||||
- ❌ Meal planning (later)
|
||||
|
||||
---
|
||||
|
||||
### Component Thinking
|
||||
|
||||
**Visualiseer je app:**
|
||||
```
|
||||
App
|
||||
├── Header
|
||||
├── SearchForm (input + submit)
|
||||
├── RecipeList
|
||||
│ └── RecipeCard (repeated)
|
||||
│ ├── Title
|
||||
│ ├── Ingredients
|
||||
│ ├── Favorite button
|
||||
│ └── View details
|
||||
└── Footer
|
||||
```
|
||||
|
||||
**Questions to ask:**
|
||||
- Welke componenten worden herhaald?
|
||||
- Welke componenten zijn child components?
|
||||
- Welke componenten hebben state?
|
||||
- Waar gaat data vandaan?
|
||||
|
||||
---
|
||||
|
||||
### MVP Denken
|
||||
|
||||
**MVP = Minimum Viable Product**
|
||||
|
||||
Het eenvoudigst mogelijke product dat nog steeds waarde levert.
|
||||
|
||||
**❌ Niet MVP:**
|
||||
- Alle features tegelijk
|
||||
- Perfect design met animaties
|
||||
- Geavanceerde filters
|
||||
- Social features
|
||||
|
||||
**✅ Wel MVP:**
|
||||
- Core functionaliteit werkt
|
||||
- Basis styling (Tailwind)
|
||||
- Happy path werkt
|
||||
- Data persists (database)
|
||||
|
||||
---
|
||||
|
||||
### Database Planning
|
||||
|
||||
**Voor recipe app:**
|
||||
```
|
||||
users table:
|
||||
- id, email, password_hash, created_at
|
||||
|
||||
recipes table:
|
||||
- id, title, ingredients, instructions, created_at
|
||||
|
||||
favorites table:
|
||||
- id, user_id, recipe_id, created_at
|
||||
```
|
||||
|
||||
**Relations:**
|
||||
- users → favorites (one-to-many)
|
||||
- users → saved_recipes (one-to-many)
|
||||
- recipes → favorites (one-to-many)
|
||||
### Live demo's (klassikaal)
|
||||
1. Next.js scaffold + Supabase koppelen
|
||||
2. Seed-script met 500 fictieve bands
|
||||
3. AI SDK installeren + eerste chat-route met `streamText`
|
||||
4. `useChat` hook + vragen stellen aan de data
|
||||
|
||||
---
|
||||
|
||||
## Tools
|
||||
- Cursor
|
||||
- ChatGPT (voor planning)
|
||||
- Pen & papier (voor sketches)
|
||||
- Vercel AI SDK v6
|
||||
- Next.js 16 + Server Actions
|
||||
- Supabase (Postgres + seed-script)
|
||||
- OpenAI / Anthropic providers
|
||||
- Polderfest-demo (in repo: `Les11-AI-SDK/polderfest-demo`)
|
||||
|
||||
---
|
||||
|
||||
## Lesopdracht (2 uur, klassikaal)
|
||||
## Lesopdracht (in-class, 60 min)
|
||||
|
||||
### Kies je Eindproject & Plan Architectuur
|
||||
Studenten kijken klassikaal mee tijdens de demo's. In-class oefening:
|
||||
- Maak een eigen API key bij OpenAI of Groq
|
||||
- Test de demo lokaal: kun je vragen stellen aan de Polderfest-data?
|
||||
- Wijzig de system prompt: laat de AI antwoorden als een festival-roadie
|
||||
|
||||
**Groepsdiscussie (15 min):**
|
||||
Bespreek klassikaal de styling ervaringen uit Les 10 - welke Tailwind en shadcn/ui patterns werkten goed?
|
||||
|
||||
**Deel 1: Idee Kiezen (30 min)**
|
||||
|
||||
Kies één van deze projecten OF je eigen idee (met goedkeuring docent):
|
||||
- **AI Recipe Generator** - Input: ingredients, Output: recipe suggestions + cooking tips
|
||||
- **Smart Budget Buddy** - Track expenses, AI insights on spending patterns
|
||||
- **Travel Planner AI** - Generate itineraries based on preferences
|
||||
- **Study Buddy AI** - Quiz generation, note-taking, Q&A helper
|
||||
- **Jouw eigen idee**
|
||||
|
||||
**Deel 2: Feature Breakdown (30 min)**
|
||||
|
||||
Voor je gekozen project:
|
||||
1. Schrijf project description (2-3 zinnen)
|
||||
2. Maak 3-5 user stories
|
||||
3. Break down in core vs nice-to-have features
|
||||
4. Selecteer MVP (wat is essentieel?)
|
||||
|
||||
**Deel 3: Architecture Planning (45 min)**
|
||||
|
||||
1. Schets database schema
|
||||
2. List de main components
|
||||
3. Plan folder structure
|
||||
4. Identify donde AI integreert (tool calling? Chat? Completion?)
|
||||
|
||||
**Deel 4: Start Codebase (15 min)**
|
||||
|
||||
1. Maak GitHub repo
|
||||
2. Create-next-app setup
|
||||
3. Push initial commit
|
||||
|
||||
### Deliverable
|
||||
- Project description document
|
||||
- Feature breakdown met user stories
|
||||
- Database schema diagram (hand-drawn ok)
|
||||
- Component tree visualization
|
||||
- GitHub repo met initial setup
|
||||
**Inleveren:** Screenshot van werkende lokale demo.
|
||||
|
||||
---
|
||||
|
||||
## Huiswerk (2 uur)
|
||||
## Huiswerk (take-home)
|
||||
|
||||
### Bouw Basis Architecture
|
||||
Bouw een eigen "praat met je data" mini-app:
|
||||
- Eigen dataset (eigen interesse, min. 50 records)
|
||||
- Werkende chat-UI via AI SDK
|
||||
- Deploy naar Vercel
|
||||
- README met setup-stappen
|
||||
|
||||
**Deel 1: Folder Structure (30 min)**
|
||||
|
||||
Create proper folder structure:
|
||||
- src/components/ui/
|
||||
- src/components/features/
|
||||
- src/lib/
|
||||
- src/hooks/
|
||||
- src/types/
|
||||
- docs/
|
||||
|
||||
**Deel 2: Type Definitions (30 min)**
|
||||
|
||||
Schrijf TypeScript types voor je project:
|
||||
- User type
|
||||
- Main data types
|
||||
- API response types
|
||||
|
||||
**Deel 3: Component Skeleton (1 uur)**
|
||||
|
||||
Maak skeleton components:
|
||||
- Main layout
|
||||
- 3-4 main feature components (without logic)
|
||||
- Proper props interfaces
|
||||
- Basic Tailwind styling
|
||||
|
||||
### Deliverable
|
||||
- GitHub commits met folder structure
|
||||
- types/ folder met je data types
|
||||
- Skeleton components
|
||||
- README.md met project description
|
||||
**Inleveren:** GitHub URL + Vercel URL via Teams.
|
||||
|
||||
---
|
||||
|
||||
## Leerdoelen
|
||||
|
||||
Na deze les kan de student:
|
||||
- Een project idee van vaag naar concreet uitwerken
|
||||
- User stories schrijven
|
||||
- Feature breakdown maken
|
||||
- MVP bepalen
|
||||
- Database schema ontwerpen
|
||||
- Component architecture plannen
|
||||
- Project codebase opzetten
|
||||
- TypeScript types structureren
|
||||
- Voorbereiding maken op verdere implementatie
|
||||
- Een Next.js-app koppelen aan Supabase + AI SDK
|
||||
- Streaming chat implementeren met `streamText` + `useChat`
|
||||
- Een eigen dataset seeden en die met een LLM bevragen
|
||||
- Het verschil uitleggen tussen direct OpenAI calls en de AI SDK
|
||||
|
||||
@@ -1,157 +1,77 @@
|
||||
# Les 12: Project Setup & AI Config (.cursorrules, claude.md)
|
||||
# Les 12: Tool Calling — Laat AI zelf functies kiezen
|
||||
|
||||
> ✅ **Deze les is volledig uitgewerkt**
|
||||
|
||||
## Lesmateriaal
|
||||
|
||||
- [Slide Overzicht](../Les12-Tool-Calling/Les12-Slide-Overzicht.md)
|
||||
- [Docenttekst](../Les12-Tool-Calling/Les12-Docenttekst.md)
|
||||
- [Lesstof](../Les12-Tool-Calling/Les12-Lesstof.md)
|
||||
- [Lesopdracht](../Les12-Tool-Calling/Les12-Lesopdracht.md)
|
||||
- [Huiswerk](../Les12-Tool-Calling/Les12-Huiswerk.md)
|
||||
|
||||
---
|
||||
|
||||
## Hoofdstuk
|
||||
**Deel 3: Full-Stack Development** (Les 9-12)
|
||||
## Deel
|
||||
**Deel 3 — AI Development** (Les 11-16)
|
||||
|
||||
## Beschrijving
|
||||
Professional project setup en AI configuration voor optimal developer experience. Setup .cursorrules, claude.md, docs/ folder, folder structure optimalisatie en git best practices.
|
||||
Vervolg op Les 11. We lossen het schaalprobleem op: niet alles in de context proppen, maar de AI laten kiezen welke tool (functie) hij nodig heeft. We bouwen 6 tools voor de Polderfest-app: search, stats, schedule, favorites en meer.
|
||||
|
||||
---
|
||||
|
||||
## Te Behandelen (~45 min)
|
||||
## Te Behandelen
|
||||
|
||||
- Waarom goede project structuur cruciaal is voor AI tools
|
||||
- De ideale folder structuur voor Next.js + AI collaboration
|
||||
- .cursorrules file: syntax, best practices, examples
|
||||
- claude.md: project documentation voor Claude
|
||||
- docs/ folder organization: AI-DECISIONS.md, ARCHITECTURE.md, PROMPT-LOG.md
|
||||
- .env.local vs .env.example configuratie
|
||||
- .gitignore en .cursorignore voor AI tools
|
||||
- .git best practices: meaningful commits, proper history
|
||||
- README setup met project info
|
||||
- TypeScript configuration optimization
|
||||
### Theorie
|
||||
- Wat is Tool Calling? (vergelijking met traditionele API-call)
|
||||
- Het schaalprobleem: 30.000 tokens per call werkt niet voor 50.000 records
|
||||
- `tool({ description, inputSchema, execute })` met Zod
|
||||
- `stopWhen: stepCountIs(5)` — multi-step reasoning
|
||||
- Wanneer tool calling NIET de oplossing is
|
||||
|
||||
### Live demo's
|
||||
1. Eerste tool: `searchBands` met Zod-schema
|
||||
2. Multi-step setup + extra tools (stats, schedule)
|
||||
3. Streaming + tool-results renderen in de UI
|
||||
4. Debug-view: zien welke tools de AI kiest
|
||||
|
||||
---
|
||||
|
||||
## Tools
|
||||
- Cursor
|
||||
- Git
|
||||
- GitHub
|
||||
- Vercel AI SDK v6 (`tool`, `stepCountIs`)
|
||||
- Zod voor input-validatie
|
||||
- Supabase queries vanuit tools
|
||||
- Polderfest-demo (in repo: `Les12-Tool-Calling/polderfest-demo`)
|
||||
|
||||
---
|
||||
|
||||
## Lesopdracht (2 uur, klassikaal)
|
||||
## Lesopdracht (in-class, 60 min)
|
||||
|
||||
### Setup Je Eindproject Proper
|
||||
Studenten kijken klassikaal mee. In-class oefening:
|
||||
- Voeg een eigen tool toe aan de Polderfest-app (bv. `getBandsByGenre`)
|
||||
- Test of de AI je tool spontaan gebruikt
|
||||
- Check de debug-view: hoeveel stappen nam de chain?
|
||||
|
||||
**Groepsdiscussie (15 min):**
|
||||
Bespreek klassikaal de architecture planning uit Les 11 - welke design patterns voelen goed voor jullie eindproject?
|
||||
|
||||
**Deel 1: Folder Structure (30 min)**
|
||||
|
||||
Zorg dat je project er zo uitziet:
|
||||
```
|
||||
project/
|
||||
├── src/
|
||||
│ ├── app/
|
||||
│ ├── components/
|
||||
│ │ ├── ui/
|
||||
│ │ ├── layout/
|
||||
│ │ └── features/
|
||||
│ ├── lib/
|
||||
│ ├── hooks/
|
||||
│ └── types/
|
||||
├── docs/
|
||||
├── public/
|
||||
├── .cursorrules
|
||||
├── .env.local
|
||||
├── .env.example
|
||||
├── .gitignore
|
||||
├── README.md
|
||||
└── claude.md
|
||||
```
|
||||
|
||||
**Deel 2: .cursorrules Writing (30 min)**
|
||||
|
||||
Maak comprehensive `.cursorrules`:
|
||||
1. Project naam + beschrijving
|
||||
2. Tech stack (Next.js 14, TypeScript, Tailwind, Supabase)
|
||||
3. File structure conventions
|
||||
4. Code conventions (naming, styling, error handling)
|
||||
5. TypeScript strict rules
|
||||
6. DO's en DON'Ts specifiek voor je project
|
||||
|
||||
Example snippets:
|
||||
- "Named exports only, no default exports"
|
||||
- "All components are functional with TypeScript"
|
||||
- "Use Tailwind classes, no inline styles"
|
||||
|
||||
**Deel 3: Documentation Files (30 min)**
|
||||
|
||||
Maak in docs/ folder:
|
||||
- `PROJECT-BRIEF.md` - Project overview, features
|
||||
- `ARCHITECTURE.md` - Component structure, data flow
|
||||
- `AI-DECISIONS.md` - Start document met AI choices
|
||||
- `PROMPT-LOG.md` - Template voor prompts die je gebruikt
|
||||
|
||||
**Deel 4: Git Setup (20 min)**
|
||||
|
||||
1. Review `.gitignore` (include `.env.local`)
|
||||
2. Make initial commit: "Initial project setup"
|
||||
3. Push naar GitHub
|
||||
4. Verify: `.env.local` NOT in git history
|
||||
|
||||
### Deliverable
|
||||
- Complete folder structure
|
||||
- Comprehensive .cursorrules file
|
||||
- Documentation files in docs/
|
||||
- GitHub repo met clean initial commit
|
||||
- README.md with project info
|
||||
**Inleveren:** Screenshot van debug-view met meerdere tool-calls.
|
||||
|
||||
---
|
||||
|
||||
## Huiswerk (2 uur)
|
||||
## Huiswerk (take-home)
|
||||
|
||||
### Optimize Configuration & Start Building
|
||||
Bouw vanuit je eigen Les 11-project:
|
||||
- Minimaal 3 tools met Zod-schemas
|
||||
- Multi-step setup (max 5 stappen)
|
||||
- README documenteert elk tool: doel + voorbeeld-prompt
|
||||
- Reflectie 300 woorden: wanneer kies je tool calling vs. all-in-context?
|
||||
|
||||
**Deel 1: tsconfig.json Optimization (30 min)**
|
||||
|
||||
1. Enable strict mode in TypeScript
|
||||
2. Configure path aliases for cleaner imports:
|
||||
```json
|
||||
"@/*": ["./src/*"]
|
||||
```
|
||||
3. Set proper include/exclude
|
||||
|
||||
**Deel 2: Tailwind & Component Setup (45 min)**
|
||||
|
||||
1. Customize `tailwind.config.ts` with your colors
|
||||
2. Setup `globals.css` properly
|
||||
3. Create 5 base UI components:
|
||||
- Button.tsx
|
||||
- Input.tsx
|
||||
- Card.tsx
|
||||
- Layout.tsx
|
||||
- Navigation.tsx
|
||||
|
||||
**Deel 3: Lib Setup (30 min)**
|
||||
|
||||
Create essential lib files:
|
||||
- `lib/supabase.ts` - Initialize Supabase client
|
||||
- `lib/utils.ts` - Utility functions
|
||||
- `lib/constants.ts` - App constants
|
||||
- `types/database.ts` - Database types
|
||||
|
||||
### Deliverable
|
||||
- Optimized TypeScript config with path aliases
|
||||
- Base UI components created
|
||||
- Lib utilities setup
|
||||
- Documentation updated with decisions
|
||||
- GitHub commits with setup progress
|
||||
**Inleveren:** GitHub URL via Teams.
|
||||
|
||||
---
|
||||
|
||||
## Leerdoelen
|
||||
|
||||
Na deze les kan de student:
|
||||
- Een professional project structure opzetten
|
||||
- Een effectieve .cursorrules file schrijven
|
||||
- claude.md projectdocumentatie maken
|
||||
- AI-DECISIONS.md beginnen en onderhouden
|
||||
- Git best practices volgen
|
||||
- TypeScript strict mode configureren
|
||||
- Path aliases voor cleaner imports opzetten
|
||||
- Base components en utilities creëren
|
||||
- Voorbereiding maken op Deel 4 (Advanced AI)
|
||||
- Een Tool definiëren met `tool()` en Zod-schema
|
||||
- Multi-step tool calling configureren met `stopWhen`
|
||||
- Een Supabase-query als tool blootstellen aan de LLM
|
||||
- Bepalen wanneer tool calling de juiste oplossing is
|
||||
- Tool-calls debuggen via de AI SDK debug-output
|
||||
|
||||
@@ -1,298 +1,80 @@
|
||||
# Les 13: Vercel AI SDK, Tool Calling & Agents
|
||||
# Les 13: Externe APIs + Cursor agents + Vercel deploy
|
||||
|
||||
> ✅ **Deze les is volledig uitgewerkt**
|
||||
|
||||
## Lesmateriaal
|
||||
|
||||
- [Slide Overzicht](../Les13-Cursor-Vercel-Deploy/Les13-Slide-Overzicht.md)
|
||||
- [Docenttekst](../Les13-Cursor-Vercel-Deploy/Les13-Docenttekst.md)
|
||||
- [Lesstof](../Les13-Cursor-Vercel-Deploy/Les13-Lesstof.md)
|
||||
- [Lesopdracht](../Les13-Cursor-Vercel-Deploy/Les13-Lesopdracht.md)
|
||||
- [Huiswerk](../Les13-Cursor-Vercel-Deploy/Les13-Huiswerk.md)
|
||||
|
||||
---
|
||||
|
||||
## Hoofdstuk
|
||||
**Deel 4: Advanced AI & Deployment** (Les 13-18)
|
||||
## Deel
|
||||
**Deel 3 — AI Development** (Les 11-16)
|
||||
|
||||
## Beschrijving
|
||||
Vercel AI SDK fundamentals voor het bouwen van AI-powered features. Stream responses, tool calling, Zod schemas, system prompts, agents met autonome actie. Integreer LLM capabilities in je app.
|
||||
We verlaten `localhost:3000`. We bouwen een kleine Pokédex die de PokéAPI gebruikt (geen LLM nodig), zetten Cursor's Composer + Background Agent in voor feature branches, en deployen naar Vercel met preview deployments + GitHub Actions CI.
|
||||
|
||||
---
|
||||
|
||||
## Te Behandelen (~45 min)
|
||||
## Te Behandelen
|
||||
|
||||
- Vercel AI SDK: wat is het en waarom gebruiken?
|
||||
- Installation en basic setup
|
||||
- useChat hook voor chat UI state management
|
||||
- Streaming responses van API
|
||||
- Tool calling: laat AI externe APIs aanroepen
|
||||
- Zod schemas voor tool parameters validation
|
||||
- System prompts schrijven voor AI behavior
|
||||
- Agent patterns: maxSteps, autonomous execution
|
||||
- Error handling en edge cases
|
||||
- Model selection: OpenAI, Claude, Gemini, etc.
|
||||
### Theorie
|
||||
- Externe APIs in Next.js (server-side fetch, caching)
|
||||
- Cursor Composer vs. Background Agent — wanneer welke?
|
||||
- Vercel preview deployments per branch
|
||||
- GitHub Actions CI (lint + build per PR)
|
||||
- Environment variables: lokaal vs. Vercel
|
||||
|
||||
---
|
||||
|
||||
### Vercel AI SDK Basics
|
||||
|
||||
**Wat is het?**
|
||||
- React library van Vercel voor AI integration
|
||||
- Streaming responses van LLMs
|
||||
- Server-side tool calling
|
||||
- Multi-turn conversations
|
||||
- Gratis, open-source
|
||||
|
||||
**Installation:**
|
||||
```bash
|
||||
npm install ai zod openai
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### useChat Hook
|
||||
|
||||
**Client-side chat state management:**
|
||||
|
||||
```typescript
|
||||
'use client'
|
||||
import { useChat } from 'ai/react'
|
||||
|
||||
export function ChatComponent() {
|
||||
const { messages, input, handleInputChange, handleSubmit } = useChat({
|
||||
api: '/api/chat',
|
||||
})
|
||||
|
||||
return (
|
||||
<div>
|
||||
{messages.map((msg) => (
|
||||
<div key={msg.id}>
|
||||
<strong>{msg.role}:</strong> {msg.content}
|
||||
</div>
|
||||
))}
|
||||
<form onSubmit={handleSubmit}>
|
||||
<input
|
||||
value={input}
|
||||
onChange={handleInputChange}
|
||||
placeholder="Type message..."
|
||||
/>
|
||||
<button type="submit">Send</button>
|
||||
</form>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Streaming Responses
|
||||
|
||||
**API Route met streaming:**
|
||||
|
||||
```typescript
|
||||
import { generateText, streamText } from 'ai'
|
||||
import { openai } from '@ai-sdk/openai'
|
||||
|
||||
export async function POST(req: Request) {
|
||||
const { messages } = await req.json()
|
||||
|
||||
const result = await streamText({
|
||||
model: openai('gpt-4'),
|
||||
system: 'You are a helpful assistant',
|
||||
messages,
|
||||
})
|
||||
|
||||
return result.toAIStreamResponse()
|
||||
}
|
||||
```
|
||||
|
||||
**Waarom streaming?**
|
||||
- Responses verschijnen real-time (beter UX)
|
||||
- Bespaar tokens vs waiting for full response
|
||||
|
||||
---
|
||||
|
||||
### Tool Calling
|
||||
|
||||
**Laat AI externe APIs aanroepen:**
|
||||
|
||||
```typescript
|
||||
import { generateText } from 'ai'
|
||||
import { openai } from '@ai-sdk/openai'
|
||||
import { z } from 'zod'
|
||||
|
||||
const tools = {
|
||||
getWeather: {
|
||||
description: 'Get weather for a city',
|
||||
parameters: z.object({
|
||||
city: z.string(),
|
||||
}),
|
||||
execute: async ({ city }: { city: string }) => {
|
||||
// Call external API
|
||||
const response = await fetch(`https://api.weather.com?city=${city}`)
|
||||
return response.json()
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
const result = await generateText({
|
||||
model: openai('gpt-4'),
|
||||
tools,
|
||||
prompt: 'What is the weather in Amsterdam?',
|
||||
})
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Zod Schemas
|
||||
|
||||
**Type-safe tool parameters:**
|
||||
|
||||
```typescript
|
||||
import { z } from 'zod'
|
||||
|
||||
const SearchProductsSchema = z.object({
|
||||
query: z.string().describe('Search query'),
|
||||
limit: z.number().optional().describe('Max results'),
|
||||
sortBy: z.enum(['price', 'rating']).optional(),
|
||||
})
|
||||
|
||||
type SearchProductsInput = z.infer<typeof SearchProductsSchema>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### System Prompts
|
||||
|
||||
**Stuur AI behavior:**
|
||||
|
||||
```typescript
|
||||
const systemPrompt = `You are a helpful recipe assistant.
|
||||
Your role is to:
|
||||
1. Suggest recipes based on ingredients
|
||||
2. Provide cooking instructions
|
||||
3. Estimate cooking time
|
||||
|
||||
Always be friendly and encouraging.`
|
||||
|
||||
const result = await generateText({
|
||||
model: openai('gpt-4'),
|
||||
system: systemPrompt,
|
||||
prompt: userMessage,
|
||||
})
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Agent Patterns
|
||||
|
||||
**Multi-step autonomous execution:**
|
||||
|
||||
```typescript
|
||||
const result = await generateText({
|
||||
model: openai('gpt-4'),
|
||||
tools: { getWeather, getFlights },
|
||||
maxSteps: 3, // Maximum iterations
|
||||
prompt: 'Plan a trip to Paris next week',
|
||||
})
|
||||
```
|
||||
|
||||
**Hoe het werkt:**
|
||||
1. AI bepaalt welke tool nodig is
|
||||
2. Tool wordt uitgevoerd
|
||||
3. Result teruggestuurd naar AI
|
||||
4. AI beslist next stap (repeat tot maxSteps of done)
|
||||
### Live demo's
|
||||
1. Nieuwe Pokédex-app — PokéAPI integreren
|
||||
2. Feature branch via Cursor Composer
|
||||
3. Background Agent: PR + diff review
|
||||
4. Vercel deploy + preview URL per PR
|
||||
5. GH Actions workflow voor lint + typecheck
|
||||
|
||||
---
|
||||
|
||||
## Tools
|
||||
- Vercel AI SDK
|
||||
- Zod
|
||||
- OpenAI API (of andere LLM provider)
|
||||
- Cursor
|
||||
- Next.js 16
|
||||
- Cursor (Composer + Background Agent)
|
||||
- Vercel (productie + previews)
|
||||
- GitHub Actions
|
||||
- PokéAPI (geen key nodig)
|
||||
|
||||
---
|
||||
|
||||
## Lesopdracht (2 uur, klassikaal)
|
||||
## Lesopdracht (in-class, 60 min)
|
||||
|
||||
### Bouw Chat Interface met Streaming
|
||||
Studenten kijken mee. In-class oefening:
|
||||
- Clone de Pokédex-starter
|
||||
- Maak een feature branch via Cursor Composer ("voeg type-filter toe")
|
||||
- Push naar GitHub en bekijk je Vercel preview URL
|
||||
- Merge de PR — zie GH Actions runnen
|
||||
|
||||
**Groepsdiscussie (15 min):**
|
||||
Bespreek klassikaal de project setup ervaringen uit Les 12 - hoe goed werken jullie .cursorrules en configuration?
|
||||
|
||||
**Deel 1: Installation & Setup (30 min)**
|
||||
|
||||
```bash
|
||||
npm install ai zod openai
|
||||
```
|
||||
|
||||
Create `app/api/chat/route.ts`:
|
||||
- Setup Vercel AI SDK
|
||||
- Configure OpenAI model
|
||||
- Add system prompt
|
||||
|
||||
**Deel 2: Chat Component (45 min)**
|
||||
|
||||
Build `app/page.tsx`:
|
||||
1. Use useChat hook
|
||||
2. Render messages list
|
||||
3. Input form for user messages
|
||||
4. Display streaming responses
|
||||
|
||||
**Deel 3: Tool Calling (30 min)**
|
||||
|
||||
Add 2 simple tools:
|
||||
- getTime: return current time
|
||||
- getRandomNumber: return random number
|
||||
|
||||
Update API route to handle tools with Zod schemas.
|
||||
|
||||
**Deel 4: Testing (15 min)**
|
||||
|
||||
Test chat locally with different prompts that trigger tools.
|
||||
|
||||
### Deliverable
|
||||
- Werkende chat interface with streaming
|
||||
- 2 integrated tools
|
||||
- GitHub commit with AI chat feature
|
||||
**Inleveren:** Screenshot van werkende preview URL.
|
||||
|
||||
---
|
||||
|
||||
## Huiswerk (2 uur)
|
||||
## Huiswerk (take-home)
|
||||
|
||||
### Integreer AI in Eindproject
|
||||
Neem je AI SDK-project uit Les 11/12:
|
||||
- Deploy naar Vercel
|
||||
- Voeg minimaal 1 externe API toe (geen LLM)
|
||||
- Configureer GH Actions CI (lint + build)
|
||||
- README beschrijft hoe lokaal + hoe productie
|
||||
|
||||
**Deel 1: Project-Specific Tools (1 uur)**
|
||||
|
||||
Add 2-3 tools relevant to your project:
|
||||
- Recipe Generator: tool to search recipes API
|
||||
- Budget App: tool to calculate expenses
|
||||
- Travel Planner: tool to search destinations
|
||||
|
||||
Define with Zod schemas and execute functions.
|
||||
|
||||
**Deel 2: System Prompt Tuning (30 min)**
|
||||
|
||||
Write a custom system prompt for your AI:
|
||||
- Define personality
|
||||
- Set constraints
|
||||
- Add context about your app
|
||||
|
||||
**Deel 3: Integration (30 min)**
|
||||
|
||||
Connect AI chat to your main app:
|
||||
- Add chat page/component
|
||||
- Integrate with Supabase auth (if needed)
|
||||
- Test end-to-end
|
||||
|
||||
### Deliverable
|
||||
- AI feature integrated in project
|
||||
- Custom tools defined
|
||||
- docs/AI-DECISIONS.md updated with choices
|
||||
- GitHub commits with AI integration
|
||||
**Inleveren:** GitHub + Vercel URL via Teams.
|
||||
|
||||
---
|
||||
|
||||
## Leerdoelen
|
||||
|
||||
Na deze les kan de student:
|
||||
- Vercel AI SDK installeren en configureren
|
||||
- useChat hook gebruiken voor chat UI
|
||||
- Streaming responses implementeren
|
||||
- Tool calling setup met Zod schemas
|
||||
- Externe APIs aanroepen via tools
|
||||
- System prompts schrijven voor AI behavior
|
||||
- Agent patterns verstaan (maxSteps)
|
||||
- AI features in een Next.js app integreren
|
||||
- Tool parameters valideren met Zod
|
||||
- Externe APIs aanroepen vanuit een Next.js server route
|
||||
- Het verschil uitleggen tussen Cursor Composer en Background Agent
|
||||
- Een feature branch + preview deployment opzetten
|
||||
- GitHub Actions CI configureren voor een Next.js project
|
||||
- Environment variables veilig beheren tussen lokaal en Vercel
|
||||
|
||||
@@ -1,330 +1,77 @@
|
||||
# Les 14: AI Chat Interface & Streaming
|
||||
# Les 14: Agents — LLM in een loop met tools
|
||||
|
||||
> ✅ **Deze les is volledig uitgewerkt**
|
||||
|
||||
## Lesmateriaal
|
||||
|
||||
- [Slide Overzicht](../Les14-Agents/Les14-Slide-Overzicht.md)
|
||||
- [Docenttekst](../Les14-Agents/Les14-Docenttekst.md)
|
||||
- [Lesstof](../Les14-Agents/Les14-Lesstof.md)
|
||||
- [Lesopdracht](../Les14-Agents/Les14-Lesopdracht.md)
|
||||
- [Huiswerk](../Les14-Agents/Les14-Huiswerk.md)
|
||||
|
||||
---
|
||||
|
||||
## Hoofdstuk
|
||||
**Deel 4: Advanced AI & Deployment** (Les 13-18)
|
||||
## Deel
|
||||
**Deel 3 — AI Development** (Les 11-16)
|
||||
|
||||
## Beschrijving
|
||||
Bouwen van professionele chat interfaces met streaming responses. Message rendering, markdown support, error handling, loading states, en UX patterns voor AI-powered features.
|
||||
We gaan een stap verder dan multi-step tool calling. Een agent kan 20-50 stappen autonoom uitvoeren, eigen plannen maken en dynamisch bijsturen. We bouwen een research-agent from scratch met `ToolLoopAgent`, `stopWhen` en `prepareStep`.
|
||||
|
||||
---
|
||||
|
||||
## Te Behandelen (~45 min)
|
||||
## Te Behandelen
|
||||
|
||||
- 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
|
||||
### Theorie
|
||||
- Wat is een agent eigenlijk? (LLM + loop + tools + stopconditie)
|
||||
- Wanneer wel/niet een agent gebruiken
|
||||
- AI SDK v6 agent-primitives: `ToolLoopAgent`, `stopWhen`, `prepareStep`
|
||||
- `prepareStep`: dynamisch model + tools per stap wisselen
|
||||
- Cost & latency van agents — wat moet je weten?
|
||||
|
||||
---
|
||||
|
||||
### 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,
|
||||
}),
|
||||
})
|
||||
}
|
||||
```
|
||||
### Live demo's
|
||||
1. Setup nieuwe research-agent (los project)
|
||||
2. Tools: webSearch, fetchPage, summarize, writeReport
|
||||
3. `stopWhen: stepCountIs(20)` + `hasToolCall("writeReport")`
|
||||
4. `prepareStep` om Sonnet te gebruiken voor summarize, Haiku voor search
|
||||
5. Live: vraag de agent een onderwerp te onderzoeken
|
||||
|
||||
---
|
||||
|
||||
## Tools
|
||||
- Vercel AI SDK
|
||||
- React Markdown
|
||||
- Cursor
|
||||
- TypeScript
|
||||
- Vercel AI SDK v6 (`ToolLoopAgent`, `stopWhen`, `prepareStep`)
|
||||
- Tavily of Exa API voor web search
|
||||
- Anthropic + OpenAI providers
|
||||
|
||||
---
|
||||
|
||||
## Lesopdracht (2 uur, klassikaal)
|
||||
## Lesopdracht (in-class, 60 min)
|
||||
|
||||
### Build Professional Chat Interface
|
||||
Studenten kijken mee. In-class oefening:
|
||||
- Voeg een eigen tool toe aan de research-agent
|
||||
- Tweak de stopconditie: laat de agent na 5 minuten stoppen
|
||||
- Bekijk de trace: welke stappen koos de agent?
|
||||
|
||||
**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
|
||||
**Inleveren:** Screenshot van werkende agent-loop.
|
||||
|
||||
---
|
||||
|
||||
## Huiswerk (2 uur)
|
||||
## Huiswerk (take-home)
|
||||
|
||||
### Integrate Chat into Your Project
|
||||
Bouw je eigen agent voor een eigen use-case:
|
||||
- Minimaal 3 tools
|
||||
- Slimme stop-conditie
|
||||
- `prepareStep` voor model-routing
|
||||
- Reflectie 500 woorden: kan dit ook met gewone tool calling?
|
||||
|
||||
**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
|
||||
**Inleveren:** GitHub URL via Teams.
|
||||
|
||||
---
|
||||
|
||||
## 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
|
||||
- Het verschil uitleggen tussen tool calling en een agent
|
||||
- Een agent opzetten met `ToolLoopAgent` en custom tools
|
||||
- Een doordachte stopconditie schrijven met `stopWhen`
|
||||
- Modellen dynamisch routen per stap via `prepareStep`
|
||||
- Inschatten wanneer een agent de juiste oplossing is
|
||||
|
||||
@@ -1,130 +1,79 @@
|
||||
# Les 15: Eindproject Werkdag 1
|
||||
# Les 15: RAG + Embeddings — Praat met je documenten
|
||||
|
||||
> ✅ **Deze les is volledig uitgewerkt**
|
||||
|
||||
## Lesmateriaal
|
||||
|
||||
- [Slide Overzicht](../Les15-RAG-Embeddings/Les15-Slide-Overzicht.md)
|
||||
- [Docenttekst](../Les15-RAG-Embeddings/Les15-Docenttekst.md)
|
||||
- [Lesstof](../Les15-RAG-Embeddings/Les15-Lesstof.md)
|
||||
- [Lesopdracht](../Les15-RAG-Embeddings/Les15-Lesopdracht.md)
|
||||
- [Huiswerk](../Les15-RAG-Embeddings/Les15-Huiswerk.md)
|
||||
|
||||
---
|
||||
|
||||
## Hoofdstuk
|
||||
**Deel 4: Advanced AI & Deployment** (Les 13-18)
|
||||
## Deel
|
||||
**Deel 3 — AI Development** (Les 11-16)
|
||||
|
||||
## Beschrijving
|
||||
Eerste intensieve werkdag aan je eindproject. Focus op core features bouwen, Q&A sessions, individuele hulp, en probleemoplossing. Docent beschikbaar voor guidance en klassikale sparring.
|
||||
Hoe laat je een LLM antwoorden op basis van documenten die hij nooit heeft gezien? Antwoord: Retrieval-Augmented Generation (RAG). We bouwen een PDF Q&A-app from scratch met embeddings, vector search (pgvector) en context-injectie.
|
||||
|
||||
---
|
||||
|
||||
## Te Behandelen (~45 min guidance + 120 min work)
|
||||
## Te Behandelen
|
||||
|
||||
- Q&A session: wat loop je tegen aan?
|
||||
- Cursor tips & tricks review
|
||||
- Debugging strategies en common patterns
|
||||
- Performance optimization basics
|
||||
- Deployment troubleshooting preview
|
||||
- Hands-on assistance beschikbaar
|
||||
- Code review feedback
|
||||
- Feature planning discussion
|
||||
### Theorie
|
||||
- Het probleem: LLM kent jouw documenten niet
|
||||
- Twee oplossingen: alles meesturen vs. RAG
|
||||
- Wat zijn embeddings? (vectoren, semantische gelijkenis)
|
||||
- pgvector in Supabase: tabel-setup + index
|
||||
- De RAG-loop: chunk → embed → store → query → retrieve → answer
|
||||
- Limieten en valkuilen (chunking, recall vs. precision)
|
||||
|
||||
---
|
||||
|
||||
## Doel van deze Werkdag
|
||||
|
||||
- Core features van je eindproject afmaken
|
||||
- Architecture validatie (is je setup goed?)
|
||||
- Database integratie testen
|
||||
- Auth flows uitwerken
|
||||
- First AI feature implementeren
|
||||
- Testing en bug fixes
|
||||
|
||||
---
|
||||
|
||||
### Checklist voor deze Sessie
|
||||
|
||||
**Code Quality:**
|
||||
- [ ] TypeScript geen errors
|
||||
- [ ] No console.logs in production code
|
||||
- [ ] Proper error handling
|
||||
- [ ] Component props typed
|
||||
|
||||
**Features:**
|
||||
- [ ] Core feature 1 werkend
|
||||
- [ ] Core feature 2 werkend
|
||||
- [ ] Data persistence (Supabase)
|
||||
- [ ] Loading states visible
|
||||
- [ ] Error states handled
|
||||
|
||||
**Setup:**
|
||||
- [ ] Project structure clean
|
||||
- [ ] .cursorrules up-to-date
|
||||
- [ ] Environment variables configured
|
||||
- [ ] Git history clean
|
||||
### Live demo's
|
||||
1. Nieuwe Next.js-app + Supabase met pgvector
|
||||
2. PDF parsen + chunking strategie
|
||||
3. Embeddings genereren via OpenAI `text-embedding-3-small`
|
||||
4. Vector-search route + top-K retrieval
|
||||
5. Chat-interface met context-injectie
|
||||
|
||||
---
|
||||
|
||||
## Tools
|
||||
- Cursor
|
||||
- Chrome DevTools
|
||||
- Supabase Dashboard
|
||||
- GitHub
|
||||
- Vercel (optional preview)
|
||||
- Vercel AI SDK v6
|
||||
- Supabase + pgvector extension
|
||||
- OpenAI embeddings API
|
||||
- pdf-parse / unpdf voor PDF-extractie
|
||||
|
||||
---
|
||||
|
||||
## Lesopdracht (4 uur, hands-on werk)
|
||||
## Lesopdracht (in-class, 60 min)
|
||||
|
||||
### Intensive Development Session
|
||||
Studenten kijken klassikaal mee. In-class oefening:
|
||||
- Upload een eigen PDF in de demo-app
|
||||
- Stel 5 vragen — beoordeel de antwoorden
|
||||
- Probeer een vraag die NIET in de PDF staat: wat gebeurt er?
|
||||
|
||||
**Hou je voortgang bij:**
|
||||
|
||||
**Eerste uur (0-60 min):**
|
||||
- [ ] Maak prioriteiten list van features
|
||||
- [ ] Fix top 3 bugs van vorige sessies
|
||||
- [ ] Test alles lokaal
|
||||
- [ ] Ask docent for guidance if stuck
|
||||
|
||||
**Twee uur (60-120 min):**
|
||||
- [ ] Implementeer core feature 1 (CRUD)
|
||||
- [ ] Implementeer core feature 2
|
||||
- [ ] Add loading/error states
|
||||
- [ ] Styling pass 1
|
||||
|
||||
**Drie uur (120-180 min):**
|
||||
- [ ] Implementeer AI feature (tool calling)
|
||||
- [ ] Test end-to-end flows
|
||||
- [ ] Fix bugs found
|
||||
- [ ] Performance check
|
||||
|
||||
**Vier uur (180-240 min):**
|
||||
- [ ] Polish UI
|
||||
- [ ] Code cleanup
|
||||
- [ ] Document decisions
|
||||
- [ ] Commit and push
|
||||
|
||||
### Deliverable
|
||||
- Werkende core features
|
||||
- Updated PROMPT-LOG.md (add entries)
|
||||
- Updated AI-DECISIONS.md
|
||||
- GitHub commits with progress
|
||||
- Screenshot of working features
|
||||
**Inleveren:** Screenshot van Q&A-sessie + reflectie 1 alinea.
|
||||
|
||||
---
|
||||
|
||||
## Huiswerk
|
||||
## Huiswerk (take-home)
|
||||
|
||||
Continue building your project for next session.
|
||||
Bouw een eigen RAG-app:
|
||||
- Eigen dataset (handleidingen, notities, eigen blog)
|
||||
- Werkende vector-search met pgvector
|
||||
- Chat-UI met source-attribution (welke chunks gebruikt?)
|
||||
- Deploy naar Vercel
|
||||
|
||||
**Checklist:**
|
||||
- [ ] Core features complete
|
||||
- [ ] All changes pushed to GitHub
|
||||
- [ ] PROMPT-LOG.md updated with prompts used
|
||||
- [ ] AI-DECISIONS.md updated with choices made
|
||||
- [ ] Ready for next workday session
|
||||
**Inleveren:** GitHub + Vercel URL.
|
||||
|
||||
---
|
||||
|
||||
## Leerdoelen
|
||||
|
||||
Na deze les kan de student:
|
||||
- Zelfstandig problemen identificeren en fixen
|
||||
- Cursor effectief gebruiken voor rapid development
|
||||
- Architectuur decisions valideren en aanpassen
|
||||
- Debugging strategieën toepassen
|
||||
- Features end-to-end implementeren
|
||||
- Development workflows versnellen
|
||||
- Documentatie up-to-date houden
|
||||
- Het RAG-pattern uitleggen aan een collega
|
||||
- pgvector configureren in Supabase
|
||||
- PDF-content chunken en embedden
|
||||
- Een werkende vector-search query schrijven
|
||||
- Bepalen wanneer RAG vs. alles-meesturen vs. fine-tuning past
|
||||
|
||||
@@ -1,122 +1,80 @@
|
||||
# Les 16: Eindproject Werkdag 2
|
||||
# Les 16: Model Context Protocol — Bouw je eigen MCP-server
|
||||
|
||||
> ✅ **Deze les is volledig uitgewerkt**
|
||||
|
||||
## Lesmateriaal
|
||||
|
||||
- [Slide Overzicht](../Les16-MCP/Les16-Slide-Overzicht.md)
|
||||
- [Docenttekst](../Les16-MCP/Les16-Docenttekst.md)
|
||||
- [Lesstof](../Les16-MCP/Les16-Lesstof.md)
|
||||
- [Lesopdracht](../Les16-MCP/Les16-Lesopdracht.md)
|
||||
- [Huiswerk](../Les16-MCP/Les16-Huiswerk.md)
|
||||
|
||||
---
|
||||
|
||||
## Hoofdstuk
|
||||
**Deel 4: Advanced AI & Deployment** (Les 13-18)
|
||||
## Deel
|
||||
**Deel 3 — AI Development** (Les 11-16)
|
||||
|
||||
## Beschrijving
|
||||
Verlengde werksessie voor je eindproject. Continue Development Day waar je intensief aan je AI-powered applicatie werkt met begeleiding en feedback van de docent.
|
||||
MCP (Model Context Protocol) is de open standaard waarmee Anthropic, OpenAI en de community AI-clients koppelen aan tools en data. We bouwen een eigen MCP-server voor Polderfest-data en laden hem in Cursor én Claude Desktop.
|
||||
|
||||
---
|
||||
|
||||
## Te Behandelen
|
||||
|
||||
### Groepsdiscussie (15 min)
|
||||
Bespreek klassikaal de deployment ervaringen uit Les 15 - welke problemen kwamen jullie tegen en hoe losten jullie die op?
|
||||
### Theorie
|
||||
- Wat is MCP en waarom bestaat het?
|
||||
- Het probleem: tools zitten nu vast aan één app
|
||||
- MCP-architectuur: server, client, transport (stdio, HTTP)
|
||||
- Tools vs. Resources vs. Prompts
|
||||
- Bestaande MCP-ecosysteem (filesystem, git, Slack, GitHub)
|
||||
- MCP vs. Tool Calling — wanneer welke?
|
||||
|
||||
### Doel van deze werkdag
|
||||
|
||||
Deze les is puur praktisch werken:
|
||||
- Bugs fixen die je bent tegengekomen
|
||||
- Features afmaken die nog niet klaar zijn
|
||||
- Code cleanup en optimalisatie
|
||||
- Performance verbeteren
|
||||
- Documentatie aanpassen
|
||||
- Testen in productie
|
||||
|
||||
---
|
||||
|
||||
### Checklist voor deze sessie
|
||||
|
||||
**Code Quality:**
|
||||
- [ ] TypeScript geen errors
|
||||
- [ ] ESLint check passed
|
||||
- [ ] Geen unused imports/variables
|
||||
- [ ] Proper error handling overal
|
||||
|
||||
**Features:**
|
||||
- [ ] Alle core features werken
|
||||
- [ ] AI feature functionaliteit compleet
|
||||
- [ ] Edge cases afgehandeld
|
||||
- [ ] Loading states geimplementeerd
|
||||
- [ ] Error states geimplementeerd
|
||||
|
||||
**Performance:**
|
||||
- [ ] Lighthouse score > 80
|
||||
- [ ] Images optimized
|
||||
- [ ] Lazy loading waar nodig
|
||||
- [ ] Bundle size reasonable
|
||||
|
||||
**Deployment:**
|
||||
- [ ] Builds succesvol lokaal
|
||||
- [ ] Alle env vars in Vercel
|
||||
- [ ] Works in production
|
||||
- [ ] Supabase redirects configured
|
||||
### Live demo's
|
||||
1. MCP SDK installeren + eerste server met 1 tool
|
||||
2. Server laden in Cursor + in Claude Desktop
|
||||
3. Eigen Polderfest MCP-server (search, stats, schedule)
|
||||
4. Resources en Prompts toevoegen
|
||||
5. Server publiceren op npm
|
||||
|
||||
---
|
||||
|
||||
## Tools
|
||||
- Cursor
|
||||
- Chrome DevTools
|
||||
- Vercel Dashboard
|
||||
- Supabase Dashboard
|
||||
- GitHub
|
||||
- `@modelcontextprotocol/sdk` (TypeScript)
|
||||
- Cursor (`.cursor/mcp.json`)
|
||||
- Claude Desktop (`claude_desktop_config.json`)
|
||||
- Node.js + TypeScript
|
||||
|
||||
---
|
||||
|
||||
## Lesopdracht (4 uur)
|
||||
## Lesopdracht (in-class, 60 min)
|
||||
|
||||
### Intensive Development Session
|
||||
Studenten kijken mee. In-class oefening:
|
||||
- Clone de Polderfest MCP-starter
|
||||
- Voeg een eigen tool toe (`getBandByCountry`)
|
||||
- Laad de server in Cursor of Claude Desktop
|
||||
- Test of de AI je tool vindt en gebruikt
|
||||
|
||||
**Hou je voortgang bij:**
|
||||
|
||||
**Eerste uur:**
|
||||
- [ ] Maak prioriteiten list
|
||||
- [ ] Fix top 3 bugs
|
||||
- [ ] Test alles lokaal
|
||||
|
||||
**Twee uur:**
|
||||
- [ ] Implementeer ontbrekende features
|
||||
- [ ] Add missing error handling
|
||||
- [ ] Improve styling/UX
|
||||
|
||||
**Drie uur:**
|
||||
- [ ] Code cleanup
|
||||
- [ ] Performance optimization
|
||||
- [ ] Redeploy
|
||||
|
||||
**Vier uur:**
|
||||
- [ ] Final testing in production
|
||||
- [ ] Screenshot taken
|
||||
- [ ] Docs updated
|
||||
|
||||
### Deliverable
|
||||
- Werkende app (lokaal en productie)
|
||||
- Updated PROMPT-LOG.md
|
||||
- Updated AI-DECISIONS.md
|
||||
- Screenshot van werkende app
|
||||
**Inleveren:** Screenshot van werkende MCP-tool in Cursor/Claude.
|
||||
|
||||
---
|
||||
|
||||
## Huiswerk
|
||||
## Huiswerk (take-home)
|
||||
|
||||
Continue working on your end project for next session. Make sure to:
|
||||
- Push all changes to GitHub
|
||||
- Document what you've done
|
||||
- List remaining work for next session
|
||||
Bouw een MCP-server voor je eigen domein:
|
||||
- Minimaal 3 tools
|
||||
- 1 resource (bijv. een doc-bestand)
|
||||
- 1 prompt-template
|
||||
- README met installatie-instructies voor Cursor
|
||||
|
||||
### Deliverable
|
||||
- All work committed and pushed
|
||||
- Documentation current
|
||||
- Task list for Les 17
|
||||
**Inleveren:** GitHub URL via Teams.
|
||||
|
||||
---
|
||||
|
||||
## Leerdoelen
|
||||
Na deze les kan de student:
|
||||
- Zelfstandig bugs identificeren en fixen
|
||||
- Code quality verbeteren
|
||||
- Performance optimisatie toepassen
|
||||
- Productie deployment testen en valideren
|
||||
- Documentatie up-to-date houden
|
||||
- MCP uitleggen aan een collega (waarom + hoe)
|
||||
- Een eigen MCP-server opzetten met de TypeScript SDK
|
||||
- Een server laden in Cursor en/of Claude Desktop
|
||||
- Het verschil tussen Tool, Resource en Prompt benoemen
|
||||
- Bepalen wanneer een MCP-server vs. inline tool calling past
|
||||
|
||||
@@ -1,207 +1,77 @@
|
||||
# Les 17: Eindproject Polish & Code Review
|
||||
# Les 17: AI Production Polish — Observability, Evals, Security, Cost
|
||||
|
||||
> ✅ **Deze les is volledig uitgewerkt**
|
||||
|
||||
## Lesmateriaal
|
||||
|
||||
- [Slide Overzicht](../Les17-Production-Polish/Les17-Slide-Overzicht.md)
|
||||
- [Docenttekst](../Les17-Production-Polish/Les17-Docenttekst.md)
|
||||
- [Lesstof](../Les17-Production-Polish/Les17-Lesstof.md)
|
||||
- [Lesopdracht](../Les17-Production-Polish/Les17-Lesopdracht.md)
|
||||
- [Huiswerk](../Les17-Production-Polish/Les17-Huiswerk.md)
|
||||
|
||||
---
|
||||
|
||||
## Hoofdstuk
|
||||
**Deel 4: Advanced AI & Deployment** (Les 13-18)
|
||||
## Deel
|
||||
**Deel 4 — Production & Advanced** (Les 17-18)
|
||||
|
||||
## Beschrijving
|
||||
Finale polish fase van je eindproject. Focus op code review, peer feedback, en laatste verbeteringen voor inlevering. Voorbereiding op presentatie.
|
||||
Van "het werkt op mijn laptop" naar productie-klaar. We behandelen de vier pillaren: observability (Langfuse), evals (LLM-as-judge), security (prompt injection + guardrails) en cost (monitoring + model routing).
|
||||
|
||||
---
|
||||
|
||||
## Te Behandelen
|
||||
|
||||
### Groepsdiscussie (15 min)
|
||||
Bespreek klassikaal de werkdag voortgang uit Les 16 - wat hebben jullie afgekregen, wat bleek moeilijker dan verwacht?
|
||||
### Theorie
|
||||
- De vier pillaren: observability, evals, security, cost
|
||||
- Waarom logs alleen niet genoeg zijn voor AI
|
||||
- Evals als unit tests voor LLM-output
|
||||
- Prompt injection — een echte demo
|
||||
- Cost-monitoring: per user, per route, per model
|
||||
|
||||
### Code Review Checklist
|
||||
|
||||
**TypeScript & Code Quality:**
|
||||
- [ ] No TypeScript errors
|
||||
- [ ] No `any` types
|
||||
- [ ] Props properly typed
|
||||
- [ ] Error handling complete
|
||||
- [ ] No console.logs in production
|
||||
|
||||
**React Best Practices:**
|
||||
- [ ] No unnecessary re-renders
|
||||
- [ ] Keys properly set in lists
|
||||
- [ ] Hooks rules followed
|
||||
- [ ] Components split logically
|
||||
- [ ] Prop drilling minimized
|
||||
|
||||
**Styling & UX:**
|
||||
- [ ] Responsive design working
|
||||
- [ ] Mobile friendly
|
||||
- [ ] Consistent styling
|
||||
- [ ] Accessible (alt text, labels, etc.)
|
||||
- [ ] No visual bugs
|
||||
|
||||
**Performance:**
|
||||
- [ ] Lighthouse > 80
|
||||
- [ ] Lazy load images
|
||||
- [ ] Optimize bundles
|
||||
- [ ] Fast interactions
|
||||
- [ ] Minimal flickering
|
||||
|
||||
---
|
||||
|
||||
### Peer Review Process
|
||||
|
||||
**Hoe peer review doen:**
|
||||
|
||||
1. **Voorbereiding (10 min)**
|
||||
- Share productie URL of GitHub link
|
||||
- List main features
|
||||
- Highlight AI features
|
||||
|
||||
2. **Review (15 min)**
|
||||
- Reviewer tests alle features
|
||||
- Takes notes
|
||||
- Looks at code (if applicable)
|
||||
|
||||
3. **Feedback (10 min)**
|
||||
- ✅ Wat werkt goed
|
||||
- ⚠️ What could improve
|
||||
- ❌ Any bugs found
|
||||
|
||||
4. **Discussion (5 min)**
|
||||
- Q&A
|
||||
- Discuss suggestions
|
||||
- Agree on priorities
|
||||
|
||||
---
|
||||
|
||||
### Final Checklist for Submission
|
||||
|
||||
**Functionality:**
|
||||
- [ ] All features work in production
|
||||
- [ ] Auth flows complete
|
||||
- [ ] CRUD operations complete
|
||||
- [ ] AI feature functional
|
||||
- [ ] No console errors
|
||||
|
||||
**Documentation:**
|
||||
- [ ] README.md complete
|
||||
- [ ] PROMPT-LOG.md has 10+ entries
|
||||
- [ ] AI-DECISIONS.md has 5+ entries
|
||||
- [ ] .env.example up to date
|
||||
- [ ] Setup instructions clear
|
||||
|
||||
**Code Quality:**
|
||||
- [ ] Code is clean and organized
|
||||
- [ ] Comments where needed
|
||||
- [ ] Consistent naming
|
||||
- [ ] No dead code
|
||||
- [ ] .cursorrules present
|
||||
|
||||
**Performance & UX:**
|
||||
- [ ] Lighthouse score > 80
|
||||
- [ ] Loading states visible
|
||||
- [ ] Error states handled
|
||||
- [ ] Mobile responsive
|
||||
- [ ] Fast load times
|
||||
|
||||
**Deployment:**
|
||||
- [ ] Deployed on Vercel
|
||||
- [ ] Working on production URL
|
||||
- [ ] Supabase configured
|
||||
- [ ] Environment variables secure
|
||||
- [ ] No errors in production
|
||||
### Live demo's
|
||||
1. Langfuse trace-integratie in Polderfest-chat
|
||||
2. Eval-suite met LLM-as-judge (Vitest + AI SDK)
|
||||
3. Prompt injection: aanvallen + guardrails (Lakera-style)
|
||||
4. Cost-tracking middleware + automatic model routing
|
||||
|
||||
---
|
||||
|
||||
## Tools
|
||||
- GitHub
|
||||
- Vercel
|
||||
- Chrome DevTools
|
||||
- Cursor
|
||||
- Peer reviewers
|
||||
- Langfuse (self-hosted of cloud)
|
||||
- Vitest voor evals
|
||||
- Vercel AI SDK middleware
|
||||
- Lakera AI / prompt-shield patterns
|
||||
|
||||
---
|
||||
|
||||
## Lesopdracht (3 uur)
|
||||
## Lesopdracht (in-class, 30 min)
|
||||
|
||||
### Code Review & Polish Session
|
||||
Studenten kijken klassikaal mee. In-class oefening:
|
||||
- Activeer Langfuse-tracing in je eigen Polderfest-fork
|
||||
- Bekijk je eerste trace
|
||||
- Voeg één eval-test toe en run hem
|
||||
|
||||
**Deel 1: Peer Review (1 uur)**
|
||||
|
||||
Work in pairs or small groups:
|
||||
1. Exchange project URLs/repos
|
||||
2. Each person reviews another's work
|
||||
3. Take detailed notes
|
||||
4. Provide constructive feedback
|
||||
5. Discuss improvements
|
||||
|
||||
**Deel 2: Final Polish (1.5 uur)**
|
||||
|
||||
Based on feedback:
|
||||
1. Fix identified bugs
|
||||
2. Implement suggested improvements
|
||||
3. Code cleanup
|
||||
4. Update documentation
|
||||
5. Final test in production
|
||||
|
||||
**Deel 3: Final Checks (30 min)**
|
||||
|
||||
Go through the submission checklist:
|
||||
1. Verify all items are done
|
||||
2. Test everything once more
|
||||
3. Make final commits
|
||||
4. Push to GitHub
|
||||
5. Screenshot for documentation
|
||||
|
||||
### Deliverable
|
||||
- Peer review feedback received
|
||||
- All feedback items addressed
|
||||
- Final production-ready code
|
||||
- Complete documentation
|
||||
- Screenshot of final app
|
||||
**Inleveren:** Screenshot Langfuse-trace + 1 passing eval.
|
||||
|
||||
---
|
||||
|
||||
## Huiswerk
|
||||
## Huiswerk (take-home)
|
||||
|
||||
**Final submission preparation:**
|
||||
In je eigen project uit Les 11-15:
|
||||
- Volledige eval-suite (min. 5 tests)
|
||||
- Security-laag tegen prompt injection
|
||||
- Cost-dashboard (Langfuse of eigen middleware)
|
||||
- `POLISH.md` in repo-root: wat heb je toegevoegd en waarom?
|
||||
|
||||
1. **Complete ALL documentation:**
|
||||
- README with features and setup
|
||||
- PROMPT-LOG.md with 10+ prompts
|
||||
- AI-DECISIONS.md with 5+ decisions
|
||||
- Project state documented
|
||||
|
||||
2. **Final testing:**
|
||||
- Test all features in production
|
||||
- Check Lighthouse score
|
||||
- Verify mobile responsiveness
|
||||
- Check load times
|
||||
|
||||
3. **Code review:**
|
||||
- Ask classmates to review code
|
||||
- Ask docent for feedback
|
||||
- Fix any issues found
|
||||
- Final cleanup
|
||||
|
||||
4. **Prepare for submission:**
|
||||
- Ensure Git history is clean
|
||||
- All commits have good messages
|
||||
- GitHub repo is public/accessible
|
||||
- Production URL is stable
|
||||
|
||||
### Deliverable
|
||||
- Final, polished application
|
||||
- All documentation complete
|
||||
- Code review completed
|
||||
- Ready for submission
|
||||
**Inleveren:** GitHub URL via Teams.
|
||||
|
||||
---
|
||||
|
||||
## Leerdoelen
|
||||
Na deze les kan de student:
|
||||
- Code review uitvoeren volgens best practices
|
||||
- Peer feedback ontvangen en implementeren
|
||||
- Final polish toepassen op projecten
|
||||
- Production checklist doorlopen
|
||||
- Professional quality deliverables opleveren
|
||||
- Zelfstandig werk evalueren en verbeteren
|
||||
- De vier productie-pillaren benoemen en uitleggen
|
||||
- Een AI-app instrumenteren met Langfuse-traces
|
||||
- Een LLM-as-judge eval-suite opzetten met Vitest
|
||||
- Een prompt injection herkennen en bescherming inbouwen
|
||||
- Cost-per-user meten en model-routing inrichten
|
||||
|
||||
@@ -1,308 +1,90 @@
|
||||
# Les 18: Deployment & Production + Eindopdracht
|
||||
# Les 18: Advanced AI Toolbox — Voice, Vision, Image, Local, Edge
|
||||
|
||||
> ✅ **Deze les is volledig uitgewerkt — laatste les**
|
||||
|
||||
## Lesmateriaal
|
||||
|
||||
- [Slide Overzicht](../Les18-AI-Toolbox-Next/Les18-Slide-Overzicht.md)
|
||||
- [Docenttekst](../Les18-AI-Toolbox-Next/Les18-Docenttekst.md)
|
||||
- [Lesstof](../Les18-AI-Toolbox-Next/Les18-Lesstof.md)
|
||||
- [Lesopdracht](../Les18-AI-Toolbox-Next/Les18-Lesopdracht.md)
|
||||
- [Huiswerk](../Les18-AI-Toolbox-Next/Les18-Huiswerk.md)
|
||||
|
||||
---
|
||||
|
||||
## Hoofdstuk
|
||||
**Deel 4: Advanced AI & Deployment** (Les 13-18)
|
||||
## Deel
|
||||
**Deel 4 — Production & Advanced** (Les 17-18)
|
||||
|
||||
## Beschrijving
|
||||
Deploy je eindproject naar productie. Leer environment variables, Vercel deployment, en basis performance optimalisatie. Bespreking van de eindopdracht requirements en afrondende werksessie.
|
||||
Laatste les. Vijf korte demo's van alle modaliteiten die we nog NIET hebben gezien: voice (Whisper + TTS), vision (GPT-4o), image generation (Flux), local LLMs (Ollama) en edge AI (Vercel AI Gateway). Wrap-up van alle 18 lessen + vooruitblik eindopdracht.
|
||||
|
||||
---
|
||||
|
||||
## Te Behandelen
|
||||
|
||||
### Groepsdiscussie (15 min)
|
||||
Bespreek klassikaal de AI feature ervaringen uit Les 17 - welke system prompts werkten goed en welke challenges kwamen jullie tegen?
|
||||
### Theorie
|
||||
- Het AI-landschap eind 2026 (providers + modi)
|
||||
- Per feature: welke modaliteit past?
|
||||
- Open-source vs. cloud — privacy, cost, latency
|
||||
- Resources & community om bij te blijven
|
||||
|
||||
### Vercel Deployment Flow
|
||||
|
||||
**Hoe Vercel werkt:**
|
||||
1. Connect GitHub repository
|
||||
2. Push naar main → automatische deploy
|
||||
3. Push naar andere branch → preview URL
|
||||
4. Alles automatisch (build, SSL, CDN)
|
||||
|
||||
**Waarom Vercel voor Next.js:**
|
||||
- Gemaakt door dezelfde makers
|
||||
- Zero-config deployment
|
||||
- Gratis tier ruim voldoende
|
||||
- Automatische HTTPS
|
||||
- Global CDN
|
||||
|
||||
---
|
||||
|
||||
### Environment Variables in Vercel
|
||||
|
||||
**Lokaal (.env.local) vs Productie (Vercel Dashboard):**
|
||||
|
||||
| Waar | Bestand/Locatie | Voorbeeld |
|
||||
|------|-----------------|-----------|
|
||||
| Lokaal | `.env.local` | Development |
|
||||
| Vercel | Dashboard → Settings → Env Vars | Production |
|
||||
|
||||
**Stap voor stap:**
|
||||
1. Ga naar je Vercel project
|
||||
2. Settings → Environment Variables
|
||||
3. Voeg toe:
|
||||
- `NEXT_PUBLIC_SUPABASE_URL`
|
||||
- `NEXT_PUBLIC_SUPABASE_ANON_KEY`
|
||||
- `OPENAI_API_KEY`
|
||||
4. Selecteer environment (Production, Preview, Development)
|
||||
5. Save & Redeploy
|
||||
|
||||
**Let op:**
|
||||
- `NEXT_PUBLIC_` prefix = zichtbaar in browser
|
||||
- Zonder prefix = alleen server-side (API routes)
|
||||
|
||||
---
|
||||
|
||||
### Supabase Productie Setup
|
||||
|
||||
**Redirect URLs configureren:**
|
||||
1. Ga naar Supabase → Authentication → URL Configuration
|
||||
2. Voeg toe bij "Redirect URLs":
|
||||
- `https://jouw-app.vercel.app/**`
|
||||
- `https://jouw-app.vercel.app`
|
||||
|
||||
**Waarom:**
|
||||
- Auth redirects werken alleen naar toegestane URLs
|
||||
- Wildcards (`**`) voor sub-routes
|
||||
|
||||
---
|
||||
|
||||
### Deployment Checklist
|
||||
|
||||
**Voor deployment:**
|
||||
- [ ] `npm run build` werkt lokaal
|
||||
- [ ] Geen TypeScript errors
|
||||
- [ ] Environment variables gedocumenteerd in `.env.example`
|
||||
- [ ] `.gitignore` bevat `.env*.local`
|
||||
- [ ] README up-to-date
|
||||
|
||||
**Na deployment:**
|
||||
- [ ] App laadt correct
|
||||
- [ ] Auth werkt (login/logout)
|
||||
- [ ] Data wordt opgehaald uit Supabase
|
||||
- [ ] AI features werken (indien van toepassing)
|
||||
- [ ] Geen console errors
|
||||
|
||||
---
|
||||
|
||||
### Performance Basics
|
||||
|
||||
**Lighthouse Audit:**
|
||||
1. Open Chrome DevTools
|
||||
2. Tab "Lighthouse"
|
||||
3. Klik "Analyze page load"
|
||||
4. Aim for score >80 in elke categorie
|
||||
|
||||
**Quick wins:**
|
||||
- Gebruik Next.js `Image` component (niet `<img>`)
|
||||
- Lazy load components die niet direct nodig zijn
|
||||
- Verwijder ongebruikte dependencies
|
||||
|
||||
---
|
||||
|
||||
### Security Checklist
|
||||
|
||||
**Belangrijk voor productie:**
|
||||
- [ ] API keys nooit in client-side code
|
||||
- [ ] Supabase RLS enabled (Row Level Security)
|
||||
- [ ] Error messages geven geen gevoelige info
|
||||
- [ ] HTTPS (automatisch via Vercel)
|
||||
|
||||
---
|
||||
|
||||
## Eindopdracht Overview
|
||||
|
||||
### Wat is de eindopdracht?
|
||||
- Bouw een AI-powered web applicatie
|
||||
- Gebruik alle tools die je hebt geleerd
|
||||
- Vrije keuze in implementatie
|
||||
|
||||
**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
|
||||
|
||||
**Of:** Eigen idee (met goedkeuring docent)
|
||||
|
||||
---
|
||||
|
||||
### Technische Vereisten
|
||||
|
||||
**Stack:**
|
||||
- Next.js 14 met App Router
|
||||
- TypeScript
|
||||
- Tailwind CSS
|
||||
- Supabase (database + auth)
|
||||
- Vercel AI SDK (chat of completion feature)
|
||||
- Deployed op Vercel
|
||||
|
||||
**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
|
||||
|
||||
---
|
||||
|
||||
### Beoordelingscriteria
|
||||
|
||||
| Criterium | Weging |
|
||||
|-----------|--------|
|
||||
| Technische uitvoering | 40% |
|
||||
| AI integratie | 25% |
|
||||
| Documentatie (PROMPT-LOG, AI-DECISIONS) | 20% |
|
||||
| Code kwaliteit & organisatie | 15% |
|
||||
|
||||
**Minimale vereisten:**
|
||||
- App werkt in productie
|
||||
- Auth + CRUD werkt
|
||||
- AI feature werkt
|
||||
- Documentatie compleet
|
||||
|
||||
---
|
||||
|
||||
### Veelvoorkomende Problemen
|
||||
|
||||
**AI Chat Werkt Niet:**
|
||||
1. API key correct in `.env.local`?
|
||||
2. API key ook in Vercel env vars?
|
||||
3. Correct model gekozen?
|
||||
4. API route syntax correct?
|
||||
|
||||
**Auth Werkt Niet in Productie:**
|
||||
1. Redirect URLs in Supabase toegevoegd?
|
||||
2. Beide URLs: met en zonder trailing slash?
|
||||
3. Wildcard (`**`) voor sub-routes?
|
||||
|
||||
**Deployment Faalt:**
|
||||
1. `npm run build` lokaal succesvol?
|
||||
2. Alle TypeScript errors gefixed?
|
||||
3. Alle env vars in Vercel?
|
||||
### Live demo's
|
||||
1. **Voice** — Whisper transcribe + TTS via ElevenLabs
|
||||
2. **Vision** — GPT-4o foto-analyse (defect detection, OCR, receipts)
|
||||
3. **Image gen** — Flux via Fal.ai (festival-poster prompt)
|
||||
4. **Local LLM** — Ollama + llama4:8b offline
|
||||
5. **Edge AI** — Vercel AI Gateway met automatic fallback
|
||||
|
||||
---
|
||||
|
||||
## Tools
|
||||
- Vercel
|
||||
- GitHub
|
||||
- Supabase
|
||||
- Chrome DevTools (Lighthouse)
|
||||
- Cursor
|
||||
- OpenAI Whisper + GPT-4o + DALL-E
|
||||
- ElevenLabs TTS
|
||||
- Fal.ai (Flux image generation)
|
||||
- Ollama + llama4 (lokaal)
|
||||
- Vercel AI Gateway
|
||||
- Cloudflare Workers AI
|
||||
|
||||
---
|
||||
|
||||
## Lesopdracht (2 uur)
|
||||
## Lesopdracht (in-class, 30 min)
|
||||
|
||||
### Deploy Je Eindproject
|
||||
Studenten kijken klassikaal mee tijdens de 5 demo's. In-class oefening:
|
||||
- Kies één modaliteit die je het interessantst vindt
|
||||
- Schets in 5 zinnen een feature voor je eindopdracht die deze modaliteit gebruikt
|
||||
|
||||
**Deel 1: Pre-Deployment Check (30 min)**
|
||||
|
||||
Run door de checklist:
|
||||
1. `npm run build` - fix eventuele errors
|
||||
2. Check TypeScript errors
|
||||
3. Maak/update `.env.example`
|
||||
4. Update README met project info
|
||||
|
||||
**Deel 2: Vercel Deployment (30 min)**
|
||||
|
||||
1. Ga naar [vercel.com](https://vercel.com)
|
||||
2. "Add New Project"
|
||||
3. Import je GitHub repository
|
||||
4. Voeg environment variables toe
|
||||
5. Deploy!
|
||||
|
||||
**Deel 3: Supabase Config (20 min)**
|
||||
|
||||
1. Voeg Vercel URL toe aan Supabase redirect URLs
|
||||
2. Test auth in productie
|
||||
3. Verifieer data access
|
||||
|
||||
**Deel 4: Testing & Lighthouse (40 min)**
|
||||
|
||||
1. Test alle features in productie:
|
||||
- Login/logout
|
||||
- CRUD operaties
|
||||
- AI chat (indien aanwezig)
|
||||
2. Run Lighthouse audit
|
||||
3. Fix issues tot score >80
|
||||
4. Screenshot resultaat
|
||||
|
||||
### Deliverable
|
||||
- Werkende productie URL
|
||||
- Lighthouse screenshot (score >80)
|
||||
- Test rapport: wat werkt, wat niet
|
||||
**Inleveren:** Schets via Teams chat.
|
||||
|
||||
---
|
||||
|
||||
## Huiswerk (Eindopdracht Afronden)
|
||||
## Huiswerk (take-home)
|
||||
|
||||
### Rond Je Eindproject Af
|
||||
Bouw één gekozen modaliteit naar productie:
|
||||
- Werkend op Vercel
|
||||
- Cost-monitoring actief (Les 17)
|
||||
- README + 200-woord reflectie: cost, latency, privacy
|
||||
|
||||
**Dit is de laatste les. Gebruik deze tijd om je eindopdracht af te ronden.**
|
||||
**Inleveren:** GitHub + Vercel URL via Teams + Brightspace.
|
||||
|
||||
**Deel 1: Bug Fixes (1 uur)**
|
||||
---
|
||||
|
||||
1. Test je app grondig in productie
|
||||
2. Fix gevonden bugs
|
||||
3. Test edge cases:
|
||||
- Lege states
|
||||
- Error states
|
||||
- Loading states
|
||||
4. Redeploy
|
||||
|
||||
**Deel 2: Performance Optimization (30 min)**
|
||||
|
||||
1. Run Lighthouse opnieuw
|
||||
2. Fix top 3 performance issues
|
||||
3. Document wat je hebt verbeterd
|
||||
|
||||
**Deel 3: Documentatie Afronden (30 min)**
|
||||
|
||||
Update je `README.md`:
|
||||
- Werkende productie URL
|
||||
- Features lijst
|
||||
- Tech stack
|
||||
- Setup instructies
|
||||
- Screenshots
|
||||
|
||||
Complete `docs/`:
|
||||
- PROMPT-LOG.md (minimaal 10 entries)
|
||||
- AI-DECISIONS.md (minimaal 5 entries)
|
||||
|
||||
**Checklist voor inleveren:**
|
||||
- [ ] App werkt op productie URL
|
||||
- [ ] Login/logout werkt
|
||||
- [ ] CRUD operaties werken
|
||||
- [ ] AI feature werkt
|
||||
- [ ] PROMPT-LOG.md heeft 10+ entries
|
||||
- [ ] AI-DECISIONS.md heeft 5+ entries
|
||||
- [ ] README is compleet
|
||||
- [ ] Code is opgeruimd
|
||||
|
||||
**Tips:**
|
||||
- Test alles als "nieuwe gebruiker"
|
||||
- Vraag iemand anders om te testen
|
||||
- Check of alles in productie werkt (niet alleen lokaal)
|
||||
|
||||
### Deliverable
|
||||
- Complete eindopdracht
|
||||
- Deployed en werkend
|
||||
- Alle documentatie compleet
|
||||
- Ingeleverd voor deadline
|
||||
## Eindopdracht (volgt na les)
|
||||
De eindopdracht doen studenten thuis. Eisen blijven gelden uit het curriculum-overzicht:
|
||||
- Next.js + TypeScript + Tailwind
|
||||
- Supabase met auth en RLS
|
||||
- AI SDK met Tool Calling
|
||||
- Externe API
|
||||
- Deployed op Vercel
|
||||
- Pitch (8-12 min) na inleveren
|
||||
|
||||
---
|
||||
|
||||
## Leerdoelen
|
||||
Na deze les kan de student:
|
||||
- Een Next.js app deployen naar Vercel
|
||||
- Environment variables configureren in Vercel
|
||||
- Supabase redirect URLs instellen voor productie
|
||||
- Een deployment checklist doorlopen
|
||||
- Lighthouse gebruiken voor performance audit
|
||||
- Basis security checks uitvoeren
|
||||
- De eindopdracht requirements begrijpen
|
||||
- Een project afronden en inleveren
|
||||
- Documentatie voltooien volgens de vereisten
|
||||
- Het AI-landschap eind 2026 schetsen (providers + modaliteiten)
|
||||
- Per feature de juiste modaliteit kiezen
|
||||
- Een voice-feature (Whisper + TTS) implementeren
|
||||
- Een vision-feature met GPT-4o bouwen
|
||||
- Een lokaal model draaien via Ollama
|
||||
- Vercel AI Gateway gebruiken voor automatic fallback
|
||||
- Bepalen welke modaliteit past bij privacy- en cost-eisen
|
||||
|
||||
Reference in New Issue
Block a user