Files
novi-lessons/Les13-Cursor-Vercel-Deploy/Les13-Docenttekst.md
2026-06-07 10:44:05 +02:00

21 KiB

Les 13 — Externe APIs + Cursor + Vercel

Docenttekst (Klas A — 3 uur, fysiek, demo-driven)

Les: 14 van 18 Onderwerp: Externe APIs + Cursor agents (Composer + Background) + Vercel preview deploys + GitHub Actions CI Duur: 180 minuten Format: Tim demonstreert klassikaal. Studenten kijken mee. Zelf bouwen = huiswerk. Demo-app: Pokédex (PokéAPI, geen key, visueel) — nieuwe kleine app


Hoe deze tekst werkt

  • [SLIDE X] — klik naar slide X
  • [SCHERM: slides | cursor | terminal | browser | github | vercel] — welk venster op de beamer
  • Vertel: "..." — wat je zegt (mag eigen woorden)
  • *[stage direction]* — instructie voor jezelf
  • 💬 = verwachte studentenvraag

VÓÓR DE LES — Setup (60 min)

1. Cursor versie checken

  • Cursor moet >=0.45 zijn voor Background Agents
  • Pro account aktief (Tim's eigen) — Background Agents zitten daar in
  • Test: Cmd+Shift+P → "Open Background Agent" zichtbaar in command palette
  • Login bij Cursor cloud — eenmalige flow

2. Vercel + GitHub klaar

  • Vercel account (Tim's eigen) — gekoppeld aan GitHub
  • Test repo: maak vooraf 1 dummy-repo aan (om snel te kunnen demonstreren als demo crasht)
  • Bookmark: vercel.com/dashboard, github.com/USER

3. Demo-app vooraf gemaakt (backup)

  • Werkende pokedex-demo lokaal + op GitHub + op Vercel
  • Als live coding faalt: switch hier naartoe, vertel "dit is hoe het er eindelijk uitziet"

4. Folder & terminal-tabs

5. Internet check

  • Background Agents werken alleen met goede verbinding
  • Vercel deploys ook
  • Backup hotspot indien WiFi gisteren rare dingen deed

6. Backup screenshots

Heb klaar voor als demo faalt:

  • Cursor Background Agent UI (run completed)
  • GitHub PR met Vercel comment
  • Vercel preview deploy
  • GitHub Actions groene check
  • Branch protection settings page

HET SCRIPT — Lees mee tijdens de les

BLOK 1 — Welkom + Terugblik (10 min)

[SLIDE 1 — Title] [SCHERM: slides]

Vertel: "Welkom bij les 14. Vandaag gaan we van localhost de wereld in. Externe APIs, Vercel, Cursor's coding agents, GitHub Actions CI. Heel hands-on."

[SLIDE 2 — Terugblik]

Vertel: "Lessen 11 t/m 13 gingen over AI: SDK, tools, agents. Alles draaide op jouw laptop. Dat was prima om te leren, maar in het echt deploy je iets en wil je dat anderen het kunnen gebruiken.

Vandaag drie dingen tegelijk. Een — externe APIs aanroepen. Geen LLM, gewoon data ophalen. Twee — die app naar Vercel. Drie — Cursor's twee agent-modes leren kennen en daarmee feature branches openen die automatisch preview-URLs krijgen op Vercel."

[SLIDE 3 — Planning]

Vertel: "Drie uur. Eerst 45 minuten theorie verdeeld over de drie onderwerpen. Daarna vier demos. Pauze rond minuut 90. Tot slot lesopdracht en huiswerk."


BLOK 2 — Theorie Externe APIs (15 min)

[SLIDE 4 — Wat is een externe API]

Vertel: "Een externe API is een HTTP-endpoint van iemand anders. Je doet fetch(), je krijgt JSON. Klaar. Dat is het idee.

Drie smaken qua authenticatie. Geen key — PokéAPI en Open-Meteo bijvoorbeeld. Met key — Tavily, TMDB, de meeste paid APIs. OAuth — Google, GitHub user-data, dat is complexer.

In Next.js fetch je op twee plekken. Server-side, in een Server Component of API route. Of client-side, met useEffect. Server-side is bijna altijd beter voor initial data. Je key blijft veilig, het is gecached, en sneller."

[SLIDE 5 — Code]

Vertel: "Code voorbeeld. Server Component is async. Doe fetch, parse als JSON, return. Met next: { revalidate: 3600 } zegt je tegen Next.js: cache dit een uur. Eerste user triggert de fetch, de volgende honderd users krijgen de gecachte versie. Schaalbaar zonder dat je iets hoeft te doen.

💬 Vraag: 'Wanneer client-side?'

Antwoord: "Bij user-interactie. Een zoekbalk waar je live filtert — moet client-side, want de input verandert in de browser. Real-time updates, polling — client-side. Maar de eerste page-load: server-side."


BLOK 3 — Theorie Cursor Agents (15 min)

[SLIDE 6 — Composer vs Background]

Vertel: "Cursor heeft TWEE soorten agents. Niet hetzelfde. Niet uitwisselbaar. Vandaag gaan we beide doen.

Composer. Cmd+I. Lokaal in je editor. Jij wacht, agent werkt, je ziet de diffs verschijnen. Je accepteert per file. Synchroon — je bent erbij. Dit is pair programming.

Background Agent. Cmd+Shift+P → 'Open Background Agent'. Runt in Cursor's cloud, niet jouw machine. Je geeft een prompt, gaat iets anders doen, komt terug. De agent maakt een branch, doet commits, opent een PR op GitHub. Asynchroon — je hoeft er niet bij te zijn.

Het verschil zit in waar je bent in je workflow. Composer voor exploreren, voor pair-programming, voor 'ik wil even meekijken'. Background Agent voor 'ik weet wat ik wil, voer maar uit terwijl ik vergader'."

💬 Vraag: 'Kost Background Agent geld?'

Antwoord: "Ja, zit in Cursor Pro. Twintig dollar per maand. Hobby-tier — gratis Cursor — heeft alleen Composer. Voor de huiswerk-opdracht: trial van Pro werkt prima, of vraag credits via Cursor support voor studenten."

💬 Vraag: 'Hoe vergelijkt dit met Claude Code of OpenCode?'

Antwoord: "Allemaal coding agents, allemaal goed. Cursor's Background Agent is uniek in dat-ie autonoom een PR opent — Claude Code en OpenCode draaien lokaal en doen geen PR-flow zelf. Het hangt af van je workflow. We zien beide in deze les."


BLOK 4 — Theorie Vercel + CI (15 min)

[SLIDE 7 — Vercel preview deploys]

Vertel: "Vercel is hosting platform van de Next.js-makers. Voor Next.js apps de simpelste deploy ter wereld. Push naar GitHub, een minuut later: live.

Het magische zit in preview deploys. Elke branch krijgt automatisch een eigen URL. Niet alleen main — letterlijk elke. Push naar feature/searchje-app-git-feature-search-user.vercel.app is live. PR's krijgen een comment met de URL.

Waarom is dit zo krachtig? Background Agent maakt een PR — preview URL is direct klikbaar. Reviewer test de feature live, niet alleen code-diff. Stakeholders kunnen iets zien. Geen 'werkt op mijn laptop'-discussies meer.

Environments — drie scopes. Production = main. Preview = alle andere branches. Development = lokaal. Per env-variabele kies je waar-ie beschikbaar is."

[SLIDE 8 — GitHub Actions CI]

Vertel: "Last theory bit. GitHub Actions. Een script dat draait wanneer er iets gebeurt — push, PR, merge.

Minimaal voor dit vak: lint en build per PR. Eerst tien regels YAML, daarna heb je voor elke PR: lint draait, TypeScript build slaagt, anders rode X.

Waarom belangrijk? Background Agent kan typo's maken. CI vangt dat op voor je merget. Plus: 'werkte op mijn laptop' bestaat niet meer."


BLOK 5 — Demo 1: Pokédex met Composer (30 min)

[SLIDE 9 — Wat we bouwen]

Vertel: "Tijd voor demo. We bouwen vandaag een Pokédex. PokéAPI heeft data van duizend Pokémon, geen key nodig, gratis. Vier features in totaal — twee met Composer nu, twee met Background Agent na de pauze."

[SLIDE 10 — DEMO 1] [SCHERM: terminal + cursor]

Vertel: "Klas, kijk mee. Vragen tussendoor mogen."

*[Terminal:]*

cd ~/novi/novi-lessons/Les13-Cursor-Vercel-Deploy
pnpm create next-app@latest pokedex \
  --typescript --tailwind --app --no-src-dir --import-alias "@/*"
cd pokedex
cursor .

*[Cursor opens]*

Vertel: "Cursor open. Nu Composer. Op Mac: Cmd+I. Op Windows: Ctrl+I."

*[Cmd+I — Composer panel opens]*

Vertel: "Composer is een tab in Cursor — niet hetzelfde als de gewone Chat. Composer kan meerdere files tegelijk wijzigen. Chat alleen één antwoord per keer."

*[Type in Composer:]*

Bouw een Pokédex-startpagina op app/page.tsx. Haal de eerste 151 Pokémon op van https://pokeapi.co/api/v2/pokemon?limit=151 als async Server Component. Toon in een grid van cards (Tailwind, 4 kolommen op desktop, 2 op tablet, 1 op mobile). Elke card: naam (capitalized), sprite van https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/{id}.png, en het Pokemon nummer (#001). Hover effect: card lichtjes vergroten en schaduw. Gebruik next/image. Voeg PokéAPI's sprite domain toe aan next.config.ts.

Vertel: "Klik 'Submit'. Composer denkt na. Je ziet diffs verschijnen — app/page.tsx, eventueel next.config.ts."

*[Accept all diffs]*

pnpm dev

*[Open browser → localhost:3000]*

Vertel: "Daar staan onze 151 Pokémon. Werkt out of the box."

💬 Vraag: 'Hoe weet Composer welke files te wijzigen?'

Antwoord: "Cursor heeft toegang tot je hele workspace. Composer ziet de file-structure, package.json, alles. Hij beslist zelf welke files relevant zijn voor de prompt. Soms vraagt hij om bevestiging — vooral bij nieuwe files."

*[Tweede Composer prompt:]*

Voeg detail-pagina toe op app/pokemon/[name]/page.tsx. Toon: grote sprite van https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/other/official-artwork/{id}.png, de naam, types als gekleurde chips (gebruik officiële Pokemon type colors zoals fire = red, water = blue, etc), en stats (HP, Attack, Defense, Sp.Atk, Sp.Def, Speed) als progress bars die de waarde tonen. Voeg height + weight onderaan. Link de homepage-cards naar /pokemon/{name}.

*[Accept diffs, refresh browser, klik op een card]*

Vertel: "Detail-pagina werkt. Stats als balkjes. Types met kleurtjes. Composer heeft type-colors zelf gevonden — die zitten in zijn training data."

*[Optioneel — als tijd:]*

De stats balkjes zijn te dun en de kleur is wat saai. Maak ze dikker en gebruik een paarse gradient.

Vertel: "Composer kan ook polish doen. Twee minuten later: betere UI. Dit is wat ik bedoelde met 'pair programming' — snel iteraten op visuals."


BLOK 6 — Demo 2: Vercel deploy (15 min)

[SLIDE 11 — DEMO 2] [SCHERM: terminal + github + vercel]

Vertel: "App werkt lokaal. Nu de wereld in."

*[Terminal:]*

git init
git add .
git commit -m "Initial Pokédex with Composer"
git branch -M main

*[Browser → github.com/new]*

Vertel: "Nieuwe repo. Naam: pokedex. Public — geen secrets in onze code dus public mag. Géén README, géén license — Next.js heeft alles al."

*[Klik 'Create repository']*

git remote add origin https://github.com/JOUW-USER/pokedex.git
git push -u origin main

*[Refresh GitHub — code is daar]*

*[Browser → vercel.com/dashboard]* [SCHERM: vercel]

Vertel: "Vercel. Add New → Project. Import Git Repository. Kies pokedex."

*[Op import-screen — alle defaults laten staan]*

Vertel: "Vercel detecteert Next.js automatisch. Build command: pnpm build. Output directory: .next. Niks aanpassen. Klik Deploy."

*[Wachten ~60-90s]*

Vertel: "Tijdens het builden: dit is wat er gebeurt. Vercel pulled je code van GitHub, install dependencies, runt pnpm build. Output gaat naar hun CDN. Klaar.

*[Build done — klik op URL]*

Vertel: "Daar staat-ie. Productie URL. Live."

*[Demonstreer: open URL op je telefoon — werkt]*

Vertel: "Werkt op telefoon. Werkt overal. Internet."

*[Terug naar Cursor — kleine wijziging:]*

*[Composer:]* "Verander de h1 van 'Pokédex' naar 'Mijn Pokédex (Live!)'"

git add . && git commit -m "Update title" && git push

*[Browser → Vercel dashboard]*

Vertel: "Nieuwe deploy verschijnt direct. Wacht 30 seconden..."

*[Refresh productie URL]*

Vertel: "Nieuwe titel zichtbaar. Geen extra commando. Push naar main = deploy."

💬 Vraag: 'En als de build faalt?'

Antwoord: "Productie blijft op de laatste werkende versie. Vercel deployt alleen als build slaagt. Je krijgt mail dat de build mislukte, productie blijft online. Geen downtime."


BLOK 7 — Pauze (15 min)

[SLIDE 12 — Pauze]

Vertel: "Pauze. Vijftien minuten."

*[Tijdens pauze: open Cursor Background Agent flow alvast — zorg dat repo geconnect is]*


BLOK 8 — Demo 3: Background Agent (25 min)

[SLIDE 13 — DEMO 3] [SCHERM: cursor + github + vercel]

Vertel: "Nu de Background Agent. Dit is écht anders. Geen pair-programming meer — we delegeren."

*[Cursor: Cmd+Shift+P]*

Vertel: "Cmd+Shift+P opent command palette. Type 'Background Agent'."

*[Select 'Open Background Agent']*

Vertel: "Eerste keer: Cursor vraagt verbinding met je repo. Volg de flow — opent browser, OAuth met GitHub, Cursor mag in jouw cloud sandbox draaien."

*[Connect flow]*

Vertel: "Klaar. Nu de prompt. Belangrijk: SPECIFIEK zijn. De agent ziet ons niet. Hij krijgt alleen de prompt."

*[Schrijf:]*

Maak een nieuwe branch feature/search. Voeg een controlled input toe bovenaan app/page.tsx. Wanneer gebruiker typt, filter de Pokémon-lijst case-insensitive op naam. Houd Tailwind-styling consistent met bestaande cards (rounded corners, padding p-4). Voeg een count toe rechtsboven: "X van 151 zichtbaar". Push de branch en open een PR met titel "Add search bar". PR body: korte beschrijving + screenshot suggestie.

*[Submit]*

Vertel: "Agent draait nu. Cursor toont je een panel waarin je kunt zien wat-ie doet — bestanden inlezen, edits maken, terminal commands."

*[Wachten ~3-5 minuten. Tijdens wachten:]*

Vertel: "Belangrijk om uit te leggen — terwijl deze agent draait, ben ik vrij om iets anders te doen. Lokaal coden, Composer gebruiken voor andere features, koffie halen. Dat is het voordeel.

Andere relevante punten. Agent draait in Cursor's sandbox — niet jouw laptop. Hij heeft toegang tot je repo, kan pnpm install doen, kan tests draaien, kan PR's openen. Maar hij heeft GEEN toegang tot jouw productie-secrets of services. Sandbox is geïsoleerd."

*[Agent done — PR verschijnt op GitHub]* [SCHERM: github]

Vertel: "Pull request op GitHub. Klik."

*[PR open]*

Vertel: "Vercel heeft een comment achtergelaten — preview URL. Klik."

*[Browser → Vercel preview URL]*

Vertel: "Live, op een ANDERE URL dan productie. Test zoekbalk."

*[Type 'pika' — Pikachu blijft over]*

Vertel: "Werkt. Search live op preview URL. Productie ongewijzigd."

*[Terug naar GitHub PR — Files Changed tab]*

Vertel: "Code-review. Agent heeft app/page.tsx aangepast, eventueel een nieuwe component gemaakt. Lees diff, check of het ok is."

*[Eventueel: comment in PR]*

Vertel: "Stel ik wil een wijziging — bv. 'voeg ook een clear-button toe'. Twee opties. Een: open de branch lokaal, Composer fix. Twee: nieuwe Background Agent prompt op deze branch. Voor demo doen we optie twee."

*[Cursor → Background Agent → existing or new]*

Op de bestaande branch feature/search: voeg een 'X' clear-button toe rechts in de zoekinput die de input leegmaakt.

*[Wacht 2-3 min, refresh PR, refresh preview URL]*

Vertel: "Update zichtbaar. Klik X — input leeg. Werkt."

*[Eventueel: merge]*

Vertel: "Tevreden? Merge PR. Vercel productie-deploy start automatisch. Een minuut later: search live op productie."

💬 Vraag: 'Wat als agent vastloopt?'

Antwoord: "Twee opties. Pakje sluiten en opnieuw beginnen met betere prompt. Of: open de branch lokaal, kijk wat agent gedaan heeft, fix met Composer. De agent is geen blackbox — hij commit echt op een branch, je kunt erin kijken."


BLOK 9 — Demo 4: GitHub Actions CI (15 min)

[SLIDE 14 — DEMO 4] [SCHERM: cursor + github]

Vertel: "Laatste demo. CI. Eén check per PR — lint + build."

*[Cursor → Composer]*

Voeg een GitHub Actions workflow toe: .github/workflows/ci.yml. Runt op pull_request en push naar main. Steps: checkout, install pnpm 9, setup node 20 met pnpm cache, install dependencies met frozen lockfile, run lint, run build.

*[Accept diffs]*

*[Terminal:]*

git checkout -b chore/add-ci
git add .github/workflows/ci.yml
git commit -m "Add CI workflow"
git push -u origin chore/add-ci

*[GitHub → openen PR]* [SCHERM: github]

Vertel: "PR open. Klik tab 'Actions' — workflow draait. ~1-2 min."

*[Wacht]*

Vertel: "Groene check verschijnt. Merge PR. CI is nu live op elke toekomstige PR."

*[Demo: failing CI]*

Vertel: "Laat ik laten zien wat er gebeurt bij een fout."

*[Cursor → Composer:]*

Maak een TypeScript fout in app/page.tsx. Verwijder een belangrijke import. Push naar een nieuwe branch chore/test-ci-fail.

git push -u origin chore/test-ci-fail

*[GitHub → PR open → wait]*

Vertel: "Rode X. Build faalt. Klik op de details — daar staat letterlijk wat mis is."

*[Fix met Composer]*

Repareer de TypeScript-fout in app/page.tsx (voeg de import terug). Commit.

git push

*[Wacht — groene check]*

Vertel: "Fixed. CI groen. Merge mag nu."

*[Branch protection toevoegen — kort]* [SCHERM: github settings]

Vertel: "Tot slot — branch protection. Settings → Branches → Add rule. Branch pattern: main. Vink aan: require PR before merging. Require status checks: select onze CI workflow. Save.

Wat dit doet: niemand kan nog direct naar main pushen. Background Agents werken via PRs — dat blijft werken. PR moet groene CI hebben voor merge."

*[Demo: probeer direct push naar main]*

git checkout main && echo "test" >> README.md && git commit -am "direct" && git push
! [remote rejected] main -> main (protected branch hook declined)

Vertel: "Geblokkeerd. Goed."


BLOK 10 — Composer vs Background reflectie (10 min)

[SLIDE 15 — Wanneer welke]

Vertel: "Twee tools, één keuze per taak. Wanneer welke?

Composer voor pair-programming. Snel feedback, jij stuurt, agent voert uit, jij accepteert per diff. Goed voor: exploreren, leren, refactors waar je wilt meekijken.

Background Agent voor delegatie. Specifieke feature, kun je niet bij zijn, parallel werken aan andere taken. Goed voor: PR-prep, parallel werken aan 3 features, terwijl-je-vergadert.

Risico's bij Background. Vage prompts = vage PR's. Specifiek zijn helpt. Agent kost credits — voor solo-projecten geen issue, voor teams kan oplopen.

Wat ik zelf doe: 80% Composer, 20% Background. Background voor de écht goed-gedefinieerde features die ik dan parallel laat draaien."

💬 Vraag: 'Welke is beter voor onze eindopdracht?'

Antwoord: "Beide. Ontwerpen + leren = Composer. Specifieke features uitwerken = Background. Voor de eindopdracht-pitch: laat zien dat je beide kunt — dat is een vaardigheid."


BLOK 11 — Lesopdracht + Huiswerk (10 min)

[SLIDE 16 — Lesopdracht + Huiswerk]

Vertel: "Lesopdracht — in de les. Half uur. Je eigen Pokédex setuppen, één feature met Composer, push naar GitHub, deploy op Vercel. Aan het eind: jouw eigen productie-URL.

Huiswerk — voor volgende week. Vier dingen.

Een: feature toevoegen via Background Agent. Branch + PR + preview URL.

Twee: GitHub Actions CI workflow. Lint + build per PR.

Drie: branch protection op main. PR's verplicht, CI moet groen.

Vier: DEPLOY.md schrijven. URLs, prompt die je aan Background Agent gaf, reflectie over Composer vs Background, bewijs van CI (groen + rood voorbeeld), één observatie.

Bonus: tweede externe API, environment scoping, parallelle Background Agents.

Tien punten, voldoende is zes. Inleveren via Brightspace: repo URL + productie URL + DEPLOY.md."


BLOK 12 — Afsluiting (5 min)

[SLIDE 17 — Afsluiting]

Vertel: "Wat hebben we vandaag gedaan. Externe APIs in Server Components. Cursor Composer voor synchrone werk. Cursor Background Agent voor async PR's. Vercel productie + preview per branch. GitHub Actions CI. Branch protection.

Volgende les: RAG en embeddings. Vector search met pgvector. We bouwen een tool die semantic search doet — handig om in een agent te plakken. Combo van les 13 en 15.

Daarna: performance + observability, eindopdracht-werkdagen, pitch.

Vragen?"

*[Vragenronde — minstens 5 min over laten]*


NA DE LES — Wrap-up

  • Push working pokedex repo naar GitHub als referentie voor studenten
  • Brightspace: link naar referentie-repo + huiswerk-instructies
  • Verzamel vragen die niet beantwoord — terug in Les 13 opening
  • Voor Klas B (later): check of Cursor Pro licenties beschikbaar zijn voor studenten, anders Background Agent demo moeilijk

Veelvoorkomende fouten tijdens live coding

Fout Oplossing
next/image PokéAPI domain error Composer: "voeg images.remotePatterns toe in next.config.ts"
Cursor Composer onresponsive Cmd+I opnieuw, of restart Cursor
Background Agent verbinding faalt Logout/login Cursor cloud, refresh repo connection
Vercel deploy faalt: missing dep pnpm install lokaal, commit lockfile, push
GitHub Actions: pnpm not found Check pnpm/action-setup@v3 versie in yml
Branch protection: kan eigen PR niet mergen Tijdens demo: voeg jezelf toe als bypass user
Preview URL 404 Wachten — eerste build duurt soms 2 min
Background Agent fixt verkeerde files Te vage prompt — specifiek met file paths volgende keer

Mentale model voor de klas

Als studenten verward zijn over de Cursor agent-modes:

Composer = jij pair-programt met AI. Synchroon. Cmd+I. Lokaal.

Background Agent = jij delegeert aan AI. Async. Cmd+Shift+P. Cloud. Opent PR.

Belangrijkste regel voor Background Agent: prompts moeten zo specifiek zijn alsof je het aan een nieuwe junior junior dev op afstand uitlegt. Geen context-cues, geen "je weet wel".