This commit is contained in:
2026-06-17 07:15:32 +02:00
parent c023192113
commit ad8b25e70c
115 changed files with 6316 additions and 16971 deletions

View File

@@ -1,455 +1,166 @@
# Les 13 — Docenttekst (Autocue)
# Les 14 — Docenttekst (normaal)
**Online les — letterlijk voorleesbaar. Slide-nummers staan tussen `[SLIDE N]` zodat je weet wanneer door te klikken.**
**Lesvorm:** online, demo-driven. Cursor + browser side-by-side delen.
**Duur:** 180 minuten met 1 pauze van 15 minuten.
> **Voor de les klaarzetten:**
> - Cursor open in lege werkmap
> - Browser tabs open: github.com, vercel.com, pokeapi.co
> - Terminal klaar
> - Cursor Pro/Business actief (voor Background Agent)
> - GitHub + Vercel ingelogd
> - Webcam check + scherm delen ingericht
**Online les via Teams. Voor uitgebreide voorbereiding + context per blok.**
**Voor letterlijk voorleesbaar script: zie `Les14-Docenttekst-Autocue.md`.**
---
## BLOK 1 — Welkom + Terugblik (10 min)
## Lesvorm en flow
`[SLIDE 1]`
| Onderdeel | Indeling |
|-----------|----------|
| Theorie + demo | ±1 uur klassikaal (live demo via screenshare) |
| Pauze | 15 minuten |
| Nu jullie | ±1,5 uur zelf doen met begeleiding via chat |
Welkom bij Les 13. Vandaag is een belangrijke les, want we verlaten voor het eerst je laptop.
**Setup tijdens de les:**
- Monitor 1 (privé): autocue-document fullscreen
- Monitor 2 (gedeeld in Teams): Cursor + browser + terminal + slides naast elkaar
Tot nu toe draaiden al jullie projecten op `localhost:3000`. Dat is prima om te leren, maar in de praktijk wil je dat anderen je werk kunnen zien. Klanten. Collega's. Werkgevers. Vandaag zetten we die stap.
We gaan drie dingen leren die je voor elk professioneel project nodig hebt. Eén: data ophalen van externe websites en APIs. Twee: je code automatisch online zetten via Vercel. Drie: efficiënt werken met Cursor agents.
Aan het einde van deze les heb je een live URL die je aan iedereen kunt delen.
`[SLIDE 2]`
Even kort terug. In de afgelopen lessen hebben we gewerkt aan AI-features. Les 11 was de Vercel AI SDK, Les 12 was Tool Calling. Allemaal mooi, maar steeds lokaal.
Vandaag stappen we even uit dat AI-pad. Geen LLM's. Geen API keys voor AI. We gaan terug naar de basis: hoe ziet een professionele Next.js-workflow eruit van localhost tot productie?
We gebruiken een eenvoudige Pokédex als demo-app. Waarom Pokémon? Omdat de PokéAPI gratis is, geen API key vraagt, en je krijgt direct visuele resultaten. Perfect om je te focussen op de workflow, niet op de data.
`[SLIDE 3]`
Dit is de planning voor vandaag. Honderdtachtig minuten.
We beginnen met theorie. Drie blokken van een kwartier: externe APIs in Next.js, Vercel met preview-omgevingen, en Cursor agents.
Dan vier live demo's. In demo één bouwen we de Pokédex met Composer. In demo twee deployen we naar Vercel en zetten we environment variables in. Na de pauze: demo drie met de Background Agent om een feature parallel te bouwen. Demo vier: GitHub Actions om CI in te richten.
Na elke demo bouw je het zelf na in je eigen repo. Vragen tussendoor altijd welkom — typ ze in de chat.
Tip voor de online-les: zet je Teams-deelvenster zo in dat slides en code allebei zichtbaar zijn. Cursor + terminal samen, slides klein in een hoek.
---
## BLOK 2 — Theorie: Externe APIs (15 min)
## Voorbereiding — week vooraf
`[SLIDE 4]`
**Accounts checken (studenten allemaal):**
- GitHub-account met `gh` CLI ingelogd (`gh auth login`)
- Vercel-account met CLI: `npm i -g vercel && vercel login`
- Cursor geïnstalleerd, Pro of Business plan actief, ingelogd
Wat is een externe API. In simpele woorden: andere mensen of bedrijven hebben data of functionaliteit, en die stellen ze beschikbaar via HTTP. Jij doet een fetch-request, krijgt JSON terug, en kunt daar dingen mee doen.
Een paar voorbeelden van APIs die je in projecten zult tegenkomen.
PokéAPI — onze demo van vandaag. Pokemon-data, geen key nodig.
Open-Meteo — gratis weerservice, ook geen key.
GitHub API — informatie over repositories, gebruikers, issues.
Tavily — web search. Die heeft wél een API key nodig.
Stripe — betalingen. Twee keys: een publishable en een secret.
Voor APIs met een key onthoud je één regel: nooit, ooit, in je code committen. Altijd in environment variables. Hier komen we straks bij Vercel uitgebreid op terug.
`[SLIDE 5]`
Dit is misschien wel de belangrijkste slide van vandaag. Drie manieren om een API te fetchen in Next.js. Static, server, of client. Welke je kiest hangt af van je use case.
Eerste optie: **static**. De fetch gebeurt tijdens `next build`. Eén keer, en daarna is het HTML. Snel, want geen server-werk per request. Goed voor data die zelden verandert: een blog-post, een marketing-pagina, een lijst van producten.
Tweede optie: **server, oftewel dynamic**. De fetch gebeurt bij elke request opnieuw. Altijd vers, maar trager. Goed voor data die per gebruiker anders is, of die altijd up-to-date moet zijn.
Derde optie: **ISR**, Incremental Static Regeneration. Een mix van de twee. Wordt gecached zoals static, maar elke X seconden mag Next.js de cache vervangen. Het beste van beide werelden. Voor onze Pokédex de juiste keuze voor de detail-pagina's: snel, maar elk uur kijkt Next.js of de PokéAPI iets nieuws heeft.
Vierde optie: **client-side fetching**, met useEffect. Dit doe je alleen als de data live moet, of als je user-interactie nodig hebt. Belangrijk: bij client-side staat je API key in de browser. Dus alleen voor publieke APIs of voor data die geen geheim is.
Kijk naar het code-blokje onderaan. Het verschil tussen die drie server-modes is letterlijk één optie in je fetch-call. Verder verandert je code helemaal niet. Dat is de kracht van Next.js: je kiest het render-gedrag per fetch.
Vandaag gebruiken we static voor de Pokédex-lijst en ISR voor de detail-pages.
**Communicatie:** stuur een Slack-bericht een dag vooraf met deze checklist. Als iemand morgen vastloopt op de installatie ben je een kwartier kwijt.
---
## BLOK 3 — Theorie: Vercel + Cursor + GitHub (15 min)
## Voorbereiding — dag van de les
`[SLIDE 6]`
**30 minuten vooraf:**
- Cursor open in een nieuwe lege folder voor de demo
- Browser tabs: github.com (logged in), vercel.com/dashboard, vercel.com/new
- Twee terminals klaar (één in de demo-folder, één voor ad-hoc commando's)
- Slides in een aparte fullscreen of klein in een hoek
- Autocue-document op tweede monitor
Korte sidetrack — straks komen we terug op Vercel. Even Cursor: twee soorten agents.
**Backup scenario:**
- Een eerder voltooide demo-folder klaar voor het geval live demo vastloopt
- Screenshots van Vercel preview-URL's voor het geval Vercel traag deploy't
- Pre-gemaakte `.cursor/rules/general.mdc` en `AGENTS.md` om snel te kunnen plakken
Composer is de agent die je al kent. Cmd+I openen, prompt typen, hij maakt aanpassingen in je editor. Synchroon. Jij wacht, hij werkt, jij kijkt, je accepteert de diff. Pair programming.
Background Agent is anders. Die draait in Cursor's cloud. Je geeft een opdracht, hij gaat aan de slag, hij maakt een branch, hij pusht naar GitHub, hij opent een Pull Request. Allemaal terwijl jij iets anders doet. Asynchroon dus.
Het verschil komt straks duidelijk in de demo. Voor nu: onthoud dat je twee modes hebt. Eén voor naast je, één voor namens je.
`[SLIDE 7]`
Nu Vercel. Dit is het hart van de les. Drie omgevingen, drie scopes — en het is cruciaal dat je dit begrijpt.
Productie is de live versie. Wordt gedeployed elke keer dat je naar de `main` branch pusht. URL is `je-app.vercel.app`. Dit ziet iedereen.
Preview is wat je krijgt voor élke andere branch. Push naar `feature/search` en je krijgt automatisch een URL terug. Iets als `je-app-git-feature-search-jouwnaam.vercel.app`. Ook publiek bereikbaar, maar alleen mensen met de link.
Development is je lokale `pnpm dev` op localhost. Alleen jij ziet dat.
Nu de belangrijke vraag: hoe ga je daar mee om als je verschillende databases, of verschillende API keys hebt per omgeving? Want dat wil je. Je wilt absoluut niet dat een experimentele preview-branch in je productie-database gaat schrijven.
Bekijk de tabel met environment variables. In Vercel ga je naar Project, Settings, Environment Variables. En daar zet je per variabele drie keer een waarde. Voor productie. Voor preview. En voor development.
Een paar voorbeelden. Je `DATABASE_URL` is voor productie je echte database. Voor preview een staging-database. Voor development je lokale Postgres. Drie totaal verschillende waarden, één variabele-naam.
Je `OPENAI_API_KEY` is in productie de echte key met hoge limit. In preview een test-key zodat experimenten je niet failliet maken. In development je persoonlijke key.
Voor Stripe heel concreet: productie is `sk_live_...`, preview en development zijn allebei `sk_test_...`. Een experiment dat per ongeluk een betaling doet komt nooit op een echte creditcard.
Onderaan staat één killer-combo: Cursor Background Agent maakt een Pull Request, Vercel ziet die PR en bouwt automatisch een preview URL, die URL komt automatisch in een comment op de PR. Reviewer klikt, opent in de browser, test live. Geen lokale setup nodig. Dit is voor mij persoonlijk een van de redenen dat ik altijd met Vercel werk.
`[SLIDE 8]`
GitHub Actions, snel. Waarom: voordat je iets merget, weet je zeker dat de code lint en bouwt op een schone machine. Niet "het werkt op mijn laptop", maar "het werkt op een verse ubuntu". Belangrijk omdat Background Agents soms lint-errors maken — CI vangt dat op.
Kijk naar het code-blok. Een minimale workflow. Bij elke pull request en bij elke push naar main: checkout, pnpm install, pnpm lint, pnpm build. Duurt ongeveer twee minuten op een kleine app.
In demo vier gaan we dit bouwen.
**Copy-paste-klaar materiaal:**
- Repo-naam (`mijn-portfolio` of vergelijkbaar)
- Twee feature-prompts (zie autocue Bijlage C)
- `.cursor/rules/general.mdc` inhoud (zie autocue Bijlage A)
- `AGENTS.md` inhoud (zie autocue Bijlage B)
---
## BLOK 4Wat we vandaag bouwen (5 min)
## Per blokwat je extra wilt zeggen
`[SLIDE 9]`
### Blok 1 — Welkom + Vandaag (slides 12)
**Doel:** verwachtingen zetten — het is een live demo van begin tot eind.
Dit is wat we vandaag bouwen. Een Pokédex.
Maak duidelijk dat het anders is dan eerdere lessen: je bouwt een hele cyclus voor hun ogen op. Vraag tussendoor of het tempo klopt — online is het lastig om non-verbale signalen te lezen. Laat ze hun hand opsteken (Teams reactie) als iets onduidelijk is.
De stack: Next.js 16 met TypeScript en Tailwind. Geen Shadcn vandaag, we houden het simpel. PokéAPI als data-bron, geen API key. Cursor voor de code. GitHub voor de versie-controle. Vercel voor de deploys.
### Blok 2 — Scaffold + Git + Vercel (slides 37)
**Doel:** in 15 minuten van leeg naar live productie-URL.
Vier features die we bouwen. Een lijst met de eerste 151 Pokémon. Detail-pages per Pokémon. Een zoek-functie. Type-filter chips.
**Slide 3 — Scaffold:** ga niet door de `create-next-app` prompts heen alsof het triviaal is. Studenten hebben dit vaak nog nooit gedaan. Beschrijf elke keuze kort:
- TypeScript: ja, want strict typing
- ESLint: ja, standaard
- Tailwind: ja, we gebruiken het hele jaar
- src/ dir: ja, het houdt root schoon
- App Router: ja, dat is de moderne flow
- Turbopack: ja als default, geeft betere DX
De eerste twee bouwen we met Composer, op de `main` branch. De andere twee met de Background Agent op feature-branches.
**Slide 4 — Git:** veelgemaakte fout is `git push` zonder eerst remote add. Laat zien wat de foutmelding eruitziet en hoe je het oplost. Wijs ook expliciet op `.gitignore` — je toont dat `node_modules` en `.env.local` NIET in de eerste commit zitten.
Aan het einde heb je: een productie-URL, twee preview-URL's, drie Pull Requests, een werkende CI-pipeline, en een geverifieerd begrip van static versus ISR.
**Slide 5 — Vercel:** wacht écht de 45 seconden af. Gebruik die tijd om uit te leggen wat Vercel doet onder de motorkap (clone, install, build, deploy). Het wachten levert spanning op — gebruik het didactisch.
**Slide 6/7 — URLs en env vars:** dit is nog theorie, want we hebben nog geen secrets. Belofte aan studenten: "zo direct ga ik dit ook live gebruiken met Vercel CLI."
### Blok 3 — Vercel CLI (slides 810)
**Doel:** student begrijpt het verschil tussen dashboard en CLI, en ziet één concrete workflow (`link` + `env pull`).
Belangrijk: maak duidelijk dat we GEEN env vars echt hebben — we tonen de syntax. Als je het wilt demonstreren met een echte var, voeg er één toe (`MIJN_NAAM=Tim`) en pull die naar lokaal, om te laten zien dat de file gevuld wordt.
`vercel env pull` is een eye-opener voor veel studenten. Het scheelt je manuelle gepruts elke keer als productie-vars wijzigen.
### Blok 4 — Cursor in detail (slides 1117)
**Doel:** student kent de hoofdfeatures en weet wanneer welke te gebruiken.
Deze 7 slides zijn de inhoudelijke kern. Niet door doorheen jakkeren. Geef per modus een micro-demo:
- **Slide 12 (modi):** open de chat met Cmd+L, sluit met Esc. Druk Cmd+K op een regel in code en typ "rename this variable". Toggle Plan-mode in de chat — laat zien hoe de UI verandert.
- **Slide 13 (@-mentions):** typ `@` in chat, laat het autocomplete-menu zien. Probeer `@web:Next.js 16 release notes` voor een live web-search demo.
- **Slide 14 (Cursor Rules):** maak live een `.cursor/rules/general.mdc` aan. Zet er één duidelijke regel in (bv. "altijd functional components, nooit class components"). Test daarna in een nieuwe chat dat de AI die regel volgt.
- **Slide 15 (AGENTS.md):** plak je voorbereide voorbeeld. Leg uit waarom ook Claude Code en Copilot dit lezen.
- **Slide 16 (Background agents):** demo de feature-2-prompt al hier even kort, om visueel te maken hoe een agent in een aparte tab opent.
Vraag aan het eind van dit blok: "welke modus zou je gebruiken voor X?" — twee of drie scenario's. Kort, voor engagement.
### Blok 5 — Live feature-workflow (slides 1822)
**Doel:** de hele cyclus laten zien — niet alleen Cursor, niet alleen Vercel, maar de combo.
**Slide 19 — Demo 1:** plan + apply. Maak het visueel: open de chat, plak de feature-1-prompt, wacht tot het plan verschijnt, lees het door, klik Apply. Dan met Cmd+K één tweak. Commit.
**Slide 20 — Push + preview:** push, switch naar browser tab Vercel, wacht op build, open preview-URL. Gebruik de wachttijd om te zeggen: "kijk, vanaf hier ben je niet meer alleen — je kunt deze URL nu delen met collega's of klanten zonder dat zij iets hoeven te installeren."
**Slide 21 — Demo 2 background agent:** dit is de WOW-moment van de les. Plak de feature-2-prompt, klik "open in background", en demonstreer LETTERLIJK dat je in main editor blijft werken. Doe een Cmd+K in een ander bestand. Dat illustreert het parallel-werken.
**Slide 22 — Merge:** open beide PR's op github.com. Toon de Vercel-bot comment. Merge één naar `main`. Switch terug naar Vercel dashboard om de productie-deploy te zien starten.
### Blok 6 — Recap + Nu jullie (slides 2325)
**Doel:** overgang naar zelf-doen.
Voor de pauze: vraag of er nog iets onduidelijk was uit de demo. In een online setting moet je actief uitlokken — studenten typen vaak niet uit zichzelf.
Na de pauze: laat een gedeelde chat open zodat studenten kunnen tonen waar ze vastlopen. Wees actief in de chat. Loop om de 15 minuten een check-in: "hoe ver iedereen?"
---
## BLOK 5 — LIVE DEMO 1: Pokédex met Composer (30 min)
## Veelvoorkomende vragen + antwoorden
`[SLIDE 10]`
**"Waarom Cursor en niet gewoon VS Code met GitHub Copilot?"**
Beide werken. Cursor's voordeel: tighter integratie van plan/build/agent flows en background agents. VS Code + Copilot is solid voor inline-completion. Voor agent-workflows is Cursor (of Claude Code) doorgaans soepeler. Test allebei en kies.
Tijd voor de eerste demo. Open Cursor, lege werkmap, terminal openen.
**"Wat kost Cursor?"**
Hobby tier is gratis met limits. Pro is rond €20/maand. Voor de cursus genoeg.
Eerste commando, typ mee:
**"Kan ik mijn API-key in Cursor gebruiken in plaats van hun subscription?"**
Ja — Settings → Models. Voeg je OpenAI/Anthropic key toe. Goedkoper bij weinig gebruik, duurder bij veel.
```bash
pnpm create next-app pokedex --typescript --tailwind --app
```
**"Wat als ik een typo maak in `.cursor/rules/`?"**
Cursor parseert de YAML front-matter, gooit een waarschuwing bij syntax errors. Open de file en kijk linksonder voor de error.
Beantwoord de vragen: geen src directory, gebruik Turbopack, default alias is prima.
**"Zal Cursor mijn code naar OpenAI sturen?"**
Hangt af van je settings. Cursor heeft "Privacy mode" — code wordt niet bewaard door OpenAI of Anthropic. Check Settings → Privacy.
Stap in de map: `cd pokedex` en open in Cursor met `cursor .` of File → Open Folder.
**"Hoe kies ik tussen Plan en Build?"**
Plan voor onbekende terrein of grote features. Build als je precies weet wat je wilt en het kleiner is. Bij twijfel: Plan, dan klik je Apply als het bevalt.
Nu het magische moment. Druk op Cmd+I — of Ctrl+I op Windows — voor Composer. Type deze prompt letterlijk over:
**"Werkt Vercel CLI ook voor andere frameworks?"**
Ja — Astro, SvelteKit, Vue, Remix, alles wat Vercel ondersteunt. De link- en env-flow is identiek.
> Bouw een lijst-pagina met de eerste 151 Pokémon van PokéAPI. URL is `https://pokeapi.co/api/v2/pokemon?limit=151`. Gebruik Tailwind cards in een grid met de naam en sprite van elke Pokémon. De sprite staat op `https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/{id}.png` waar {id} het index-nummer is. Gebruik een static fetch — dus géén revalidate optie meegeven.
Composer gaat aan de slag. Je ziet diffs verschijnen in `app/page.tsx`. Lees ze met me mee. Accepteer alle wijzigingen.
Start lokaal:
```bash
pnpm dev
```
Open `localhost:3000`. Daar zou nu een grid van 151 Pokémon moeten staan. Werkt het? Mooi.
Tweede prompt in Composer:
> Voeg een detail-pagina toe op `/pokemon/[id]`. Fetch van `https://pokeapi.co/api/v2/pokemon/{id}`. Toon de official artwork — die staat in `sprites.other["official-artwork"].front_default`. Toon ook de types als chips. Gebruik ISR met `revalidate: 3600`. Zorg dat de cards op de homepage linken naar `/pokemon/[id]`.
Wacht op de diffs. Accepteer ze. Open een random Pokémon. Werkt? Goed.
Belangrijke uitleg terwijl studenten kijken:
Kijk naar het verschil tussen `app/page.tsx` en `app/pokemon/[id]/page.tsx`. De homepage gebruikt gewoon `fetch(URL)`. De detail-pagina gebruikt `fetch(URL, { next: { revalidate: 3600 } })`. Dat is het hele verschil tussen static en ISR. Eén optie.
Open de browser Network tab — F12. Klik door wat detail-pages. Je ziet dat er geen calls vanuit de browser naar PokéAPI gaan. Alles is server-side. Dat betekent: als PokéAPI morgen omvalt, blijft jouw site werken tot de revalidate triggert.
Optioneel — en als de tijd het toelaat — voeg een derde route toe met `cache: "no-store"`. Bijvoorbeeld een "random pokemon" pagina. Zo zien studenten alle drie de modes naast elkaar.
Commit alles in de terminal:
```bash
git add . && git commit -m "Initial Pokédex met Composer"
```
**"Wat als ik géén Vercel wil gebruiken?"**
Alternatieven: Netlify (vergelijkbare workflow), Cloudflare Pages (goedkoper bij schaal), zelf hosten op een Hetzner box met Coolify (zoals Tim doet). De Cursor-workflow blijft hetzelfde — alleen de deploy-step verandert.
---
## BLOK 6 — LIVE DEMO 2: Vercel deploy + env vars (20 min)
## Foutmodi tijdens de les
`[SLIDE 11]`
Tijd om dit live te zetten.
Open github.com in een nieuwe tab. Klik "New repository". Naam `pokedex`. Public. Geen README, geen gitignore, geen license — die hebben we al lokaal.
Klik Create. GitHub laat een URL zien. Kopieer die.
Terug in de terminal:
```bash
git branch -M main
git remote add origin https://github.com/JOUWNAAM/pokedex.git
git push -u origin main
```
Refresh github.com. Daar staat je code.
Open vercel.com. Log in met GitHub. Klik "Add New" en kies "Project". Vercel toont een lijst met je repositories — kies `pokedex`. Klik "Deploy".
Wacht zestig tot negentig seconden. Je ziet de build logs voorbij komen. Aan het einde: live URL. Klik. Daar staat je Pokédex op het internet. Live.
Nu het belangrijkste stuk: environment variables.
Open `app/page.tsx` lokaal in Cursor. Voeg ergens bovenaan in de return een regel toe:
```tsx
<p className="mb-4 text-sm text-zinc-500">
Omgeving: {process.env.NEXT_PUBLIC_APP_ENV ?? "onbekend"}
</p>
```
Push naar main:
```bash
git add . && git commit -m "Toon huidige omgeving"
git push
```
Vercel deployt automatisch opnieuw. Maar de regel toont "onbekend" — omdat we de variabele nog niet hebben ingesteld.
Ga in Vercel naar je project → Settings → Environment Variables. Klik "Add new".
Variable name: `NEXT_PUBLIC_APP_ENV`. Value: `production`. **Belangrijk:** vink ALLEEN Production aan. Klik Save.
Tweede keer toevoegen. Zelfde naam, value `preview`, en vink ALLEEN Preview aan. Save.
Ga naar de Deployments tab en redeploy de laatste deploy. Of push een kleine wijziging om automatisch te triggeren. Wacht. Open productie-URL — staat nu "production".
Nu een feature-branch. Terug in Cursor terminal:
```bash
git checkout -b chore/banner
# kleine wijziging — bv een spatie ergens
git add . && git commit -m "Banner aanpassing"
git push -u origin chore/banner
```
Open de Vercel deployments tab. Daar verschijnt een nieuwe deployment voor `chore/banner`. Klik de preview URL. Daar zie je "preview" staan, niet "production". Twee URL's, twee waarden, één variabele.
Voor `.env.local` zou je `NEXT_PUBLIC_APP_ENV=development` zetten — dat doen ze in het huiswerk.
Belangrijke regel: voor secrets — echte API keys, database passwords — vink je in Vercel **alleen** Production aan. In Preview gebruik je een aparte test-key. Dit voorkomt dat experimenten je productie-data raken.
---
## BLOK 7 — Pauze (15 min)
`[SLIDE 12]`
Vijftien minuten pauze. Ik mute mijn microfoon en zet de camera uit. Tot zo.
---
## BLOK 8 — LIVE DEMO 3: Background Agent + preview (25 min)
`[SLIDE 13]`
Welkom terug. Nu het stuk wat veel mensen voor het eerst zien: de Cursor Background Agent.
Open Cursor. Druk Cmd+Shift+P voor het command palette. Type "Background Agent". Eerste keer: Cursor vraagt of je je repository wilt verbinden aan de cloud. Accepteer in de browser, autoriseer GitHub.
Nu kun je een Background Agent starten. Type deze prompt — letterlijk over:
> Maak een nieuwe branch genaamd `feature/search`. Voeg bovenaan de homepage een zoekbalk toe. Wanneer iemand typt, filter dan de Pokémon-lijst op naam. Gebruik client-side state met useState. Push de branch naar GitHub en open een Pull Request met titel "Add search bar" en een korte beschrijving in de body.
Klik start. De agent gaat aan de slag.
Wat je nu kunt doen — en dit is het hele punt: iets anders doen. Een tweede Background Agent starten met een andere taak.
Nieuwe Background Agent, prompt:
> Maak branch `feature/type-filter`. Op de homepage, naast de zoekbalk: chips om te filteren op type. Type-data moet je per Pokémon fetchen via de detail-endpoint. Push de branch en open een PR.
Beide agents lopen nu parallel. Klik op de eerste in het Background panel — je ziet wat hij doet. Bij vragen kan hij je stoppen voor input.
Wacht drie tot vijf minuten. Pull-Requests verschijnen op GitHub.
Open de eerste PR — "Add search bar". Onderaan zie je een comment van Vercel met de preview URL. Klik. Test de zoekbalk live in de browser. Werkt? Goed.
Open de code-diff in de GitHub UI. Lees mee. De agent heeft toegevoegd: een useState voor de query, een input bovenaan, een filter op de lijst. Logisch.
Als de code goed is, klik "Merge pull request". Push gaat naar `main`. Vercel deployt naar productie. Binnen een minuut staat de zoekbalk live.
Hetzelfde voor de tweede PR. Review, test op preview-URL, merge.
Wat hier net gebeurde: in vijf minuten zijn er twee features autonoom gebouwd door agents, getest op aparte preview-URLs, en gemerged naar productie. Zonder dat ik één regel code zelf heb geschreven.
---
## BLOK 9 — LIVE DEMO 4: GitHub Actions CI (15 min)
`[SLIDE 14]`
Laatste demo. We voegen CI toe. Lint en build moeten slagen voor elke PR.
Open Composer in Cursor, Cmd+I, prompt:
> Voeg een GitHub Actions workflow toe op `.github/workflows/ci.yml`. Bij pull request én bij push naar main: checkout, setup pnpm met `pnpm/action-setup@v4`, setup node 22 met `actions/setup-node@v4` en `cache: pnpm`, install, run lint, run build.
Composer maakt het bestand. Accepteer.
Push de wijziging:
```bash
git checkout -b chore/add-ci
git add . && git commit -m "Add GitHub Actions CI"
git push -u origin chore/add-ci
```
Open de PR op GitHub. Onder de PR zie je de "Checks" tab — de workflow draait. Wacht ongeveer twee minuten. Groene vinkjes — goed.
Nu de demo van een falende CI. Introduceer een typo in de code. Open `app/page.tsx` lokaal, verander een opening tag in iets fouts — bijvoorbeeld `<dvi>` in plaats van `<div>`. Commit en push naar dezelfde branch.
CI draait opnieuw, faalt. Rode X. Open de logs in GitHub — zie de TypeScript error.
Fix met Composer:
> Repareer de TypeScript build error in `app/page.tsx`.
Composer fixt. Commit, push. CI draait. Groen.
Laatste stap: branch protection. Ga naar GitHub repo → Settings → Branches → Add rule. Branch name pattern: `main`. Vink aan: "Require status checks to pass before merging". Selecteer de CI-workflow. Save.
Vanaf nu mag niemand — ook jij niet — naar main mergen zonder groene CI.
Merge de PR. Klaar.
---
## BLOK 10 — Composer vs Background (10 min)
`[SLIDE 15]`
Vandaag hebben we beide gebruikt. Wanneer kies je welke?
Composer is je pair-programmer. Je zit erbij, hij maakt aanpassingen, je accepteert per file. Goed voor: snelle wijzigingen tijdens je werk, complex refactor waar je wilt meekijken, onbekend gebied waar je niet wilt dat een agent vastloopt.
Background Agent is je delegate. Je geeft een welomschreven taak, gaat iets anders doen, krijgt later een PR met preview URL. Goed voor: features met heldere specs, parallel werken aan meerdere features, tijdens een meeting iets voorbereiden.
Mentaal model: Composer is "samen werken". Background Agent is "uitbesteden".
Twee waarschuwingen voor Background Agent. Een: hij kan vastlopen op rare config — debuggen is moeilijker omdat je er niet bij was. Twee: hij verbruikt credits, dus Cursor Pro of Business is wel nodig.
Praktische tip: te vage prompts geven matige PR's. Wees specifiek. Noem de bestanden, beschrijf de UX, geef voorbeelden van wat je wilt. Hoe meer context, hoe beter de output.
---
## BLOK 11 — Lesopdracht + Huiswerk (10 min)
`[SLIDE 16]`
Tijd voor jullie eigen werk. Twee delen.
**Lesopdracht — doe je nu, dertig minuten:**
Een. Eigen Pokédex-repo opzetten met dezelfde stappen als de demo: `pnpm create next-app`, Composer prompt voor de lijst, Composer prompt voor de detail-page.
Twee. Push naar GitHub.
Drie. Verbind met Vercel, deploy. Open de productie-URL en stuur de URL in de chat — ik wil zien dat het werkt.
Vier. Voeg de `NEXT_PUBLIC_APP_ENV` environment variable toe met een aparte waarde voor production en preview. Verifieer dat het werkt op beide URLs.
**Huiswerk — voor volgende les:**
A. Eén feature toevoegen met de Background Agent. Mijn voorstel: zoekbalk, type-filter, favorieten-systeem, of vergelijk-twee-pokemon. Open de PR, krijg de preview URL.
B. GitHub Actions CI toevoegen met lint en build.
C. Branch protection op `main` instellen.
D. Schrijf een `DEPLOY.md` in de root van je repo met: productie-URL, één preview-URL, en een reflectie van ongeveer driehonderd woorden over Composer versus Background Agent. Wanneer werkte welke beter? Geef één voorbeeld waar Background verbluffend goed of juist slecht was.
Bonus voor wie wil: vervang de Pokédex door een andere externe API. Open-Meteo voor weer, GitHub API voor jouw eigen repositories, of een free API naar keuze.
Inleveren via Teams, voor volgende les.
---
## BLOK 12 — Afsluiting (5 min)
`[SLIDE 17]`
Vandaag hebben we veel gedaan.
We hebben externe APIs leren fetchen vanuit Server Components. We hebben drie rendering modes gezien: static voor de lijst, ISR voor detail-pages, en kort genoemd hoe je dynamic of client-side zou doen. Dat is een knop die je per fetch omdraait.
We hebben Cursor Composer gebruikt voor synchrone wijzigingen, en Background Agent voor twee parallel-features. Verschillende tools voor verschillende momenten.
We hebben naar Vercel gedeployed. Productie op main, preview per branch. En het belangrijkste: environment variables per omgeving. Een variabele kan drie totaal verschillende waarden hebben, één per scope.
En tenslotte GitHub Actions CI. Zekerheid dat je code lint en bouwt voor de merge.
Volgende les is les 14: Agents. Nog een stap verder dan tool calling. LLM in een loop met tools, autonoom twintig tot vijftig stappen. We bouwen een research-agent from scratch met `ToolLoopAgent`, `stopWhen` en `prepareStep`. En we bespreken wanneer agents wel of niet de juiste keuze zijn.
Dat was 'm. Bedankt voor jullie aandacht. Vragen?
---
## VEELVOORKOMENDE FOUTEN — voor mezelf
| Probleem | Oplossing |
| Probleem | Snelle fix |
|----------|-----------|
| Vercel deploy faalt op build | Check Build Logs — meestal type-error of missende env var |
| Background Agent doet niks | Repo niet gekoppeld aan Cursor cloud — Cmd+Shift+P → Repository Settings |
| Preview URL toont oude versie | Hard refresh (Cmd+Shift+R), of Vercel cache invalidate |
| Env var komt niet door | Redeploy na toevoegen var — bestaande build pakt 'm niet automatisch |
| `process.env.NEXT_PUBLIC_*` undefined | Moet beginnen met `NEXT_PUBLIC_` om in browser te werken |
| GitHub Actions faalt op pnpm | `actions/setup-node` MET `cache: pnpm` — anders geen lockfile-aware install |
| Branch protection blokkeert PR | Eerst CI groen zien voor je merge |
| Composer 'kan repo niet vinden' | Cursor verbinden met die specifieke repo via Cmd+Shift+P |
| `gh repo create` faalt — niet ingelogd | `gh auth login` opnieuw |
| Vercel detecteert geen Next.js | Build directory leeg gelaten, niet `out/` typen |
| Vercel build crasht op env var | Tijdelijk een dummy zetten in dashboard |
| Cursor verliest context | Esc, nieuwe chat starten, opnieuw `@`-mention |
| Background agent doet niets | Eerst zien of het Pro/Business-plan vereist |
| `vercel link` koppelt aan verkeerd project | `rm -rf .vercel` en opnieuw |
---
## TIMING-CHECK
## Vooruitblik Les 15
| Blok | Cumulatief | Duur |
|------|-----------|------|
| 1. Welkom + Terugblik | 010 | 10 min |
| 2. Theorie Externe APIs | 1025 | 15 min |
| 3. Theorie Vercel + GH | 2540 | 15 min |
| 4. Wat we bouwen | 4045 | 5 min |
| 5. Demo 1 — Composer | 4575 | 30 min |
| 6. Demo 2 — Vercel + env | 7595 | 20 min |
| 7. Pauze | 95110 | 15 min |
| 8. Demo 3 — Background Agent | 110135 | 25 min |
| 9. Demo 4 — GitHub Actions | 135150 | 15 min |
| 10. Composer vs Background | 150160 | 10 min |
| 11. Lesopdracht + Huiswerk | 160170 | 10 min |
| 12. Afsluiting | 170175 | 5 min |
| Buffer voor vragen | 175180 | 5 min |
Volgende les: RAG met embeddings. We bouwen een PDF Q&A-app. Studenten moeten daarvoor hun Next.js-app van vandaag live hebben staan, met minstens twee PR's gemerged. Anders missen ze het fundament voor de RAG-stack.
Totaal: 180 minuten.
Stuur de avond ervoor een Slack-bericht: "checklist voor Les 15 — productie-URL + 2 merged PR's — laat in chat zien als je vastzit."