14 KiB
Les 13 — Lesstof
Externe APIs + Cursor agents + Vercel deploy
Vak: AI-Assisted Development Opleiding: NOVI Hogeschool Utrecht Vorige les: Les 14 — RAG + Embeddings Volgende les: Les 14 — RAG + Embeddings
Inhoud
- Externe APIs in Next.js
- Server- vs client-side fetching
- Environment variabelen
- Cursor agents — Composer vs Background
- Vercel deployments
- Preview deployments per branch
- GitHub Actions CI
- Branch protection
- Werkstroom — feature van begin tot productie
- Productie-overwegingen
1. Externe APIs in Next.js
Een externe API is een HTTP-endpoint van iemand anders waar je data of functionaliteit kunt ophalen. Voor de meeste apps die je gaat bouwen heb je er minstens één nodig.
Wat valt eronder
- Data-APIs — PokéAPI (Pokemon), Open-Meteo (weer), GitHub API (repos), TMDB (films)
- AI-providers — OpenAI, Anthropic, Tavily (web search)
- Payment — Stripe, Mollie
- Auth — Clerk, Auth0, Supabase Auth
- Email — Resend, Postmark, SendGrid
Drie smaken qua authenticatie
- Geen key — PokéAPI, Open-Meteo. Direct fetchen.
- API key in URL of header — Tavily, TMDB. Key beheren als env-variabele.
- OAuth flow — Google, GitHub. Complexer, vaak via libraries.
Basis-pattern in Next.js
// Server Component
async function getPokemon(name: string) {
const res = await fetch(`https://pokeapi.co/api/v2/pokemon/${name}`);
if (!res.ok) throw new Error("Niet gevonden");
return res.json();
}
export default async function Page({ params }) {
const data = await getPokemon(params.name);
return <div>{data.name}</div>;
}
Drie dingen om te onthouden:
- Server Components mogen
asynczijn —awaitdirect in component - Errors moet je zelf afvangen (
!res.ok) fetchin een Server Component wordt automatisch gecached door Next.js
2. Server- vs client-side fetching
Server-side (Server Component of API route)
// app/pokemon/[name]/page.tsx
async function getPokemon(name) {
const res = await fetch(`https://pokeapi.co/api/v2/pokemon/${name}`, {
next: { revalidate: 3600 }, // cache 1 uur
});
return res.json();
}
Voordelen:
- API key blijft op de server (nooit in client-bundle)
- Caching gratis via Next.js
- SEO-vriendelijk (HTML met data terug)
- Snellere TTFB (geen extra roundtrip)
Wanneer gebruiken: initiële data, lijsten, detail-pagina's.
Client-side (useEffect of useState met fetch)
"use client";
import { useEffect, useState } from "react";
export function LivePokemon({ name }) {
const [data, setData] = useState(null);
useEffect(() => {
fetch(`/api/pokemon/${name}`).then((r) => r.json()).then(setData);
}, [name]);
return data ? <div>{data.name}</div> : <p>Loading...</p>;
}
Wanneer gebruiken:
- User-interactie (search, filter, infinite scroll)
- Real-time updates (polling, websockets)
- Data die per user verschilt en niet op server kan
Belangrijke regel: API keys NOOIT in client-code. Voor authenticated externe APIs: maak een API-route in
app/api/...als proxy.
Cache-opties bij fetch
fetch(url, { cache: "force-cache" }) // permanent (default Next.js)
fetch(url, { next: { revalidate: 3600 } }) // ISR — herval na N seconden
fetch(url, { cache: "no-store" }) // nooit cachen (per request)
fetch(url, { next: { tags: ["pokemon"] } }) // tag-based revalidation
3. Environment variabelen
Drie scopes in Next.js + Vercel
| Scope | Wanneer | Waar |
|---|---|---|
OPENAI_API_KEY |
Server-only | Process env op server |
NEXT_PUBLIC_APP_URL |
Server + client | In client-bundle (zichtbaar in DevTools!) |
.env.local |
Lokaal alleen | Niet committen, .gitignore |
Regel
Alles wat geheim is — zonder NEXT_PUBLIC_ prefix. Met prefix = in client bundle = iedereen kan het zien.
// ✅ Server-only — veilig
process.env.OPENAI_API_KEY
// ❌ NEVER doen
"use client";
const key = process.env.NEXT_PUBLIC_OPENAI_KEY; // staat in HTML response!
Vercel environment scoping
Op Vercel heb je drie environments:
- Production — deploys vanaf
main - Preview — alle andere branches + PRs
- Development — lokaal (
vercel env pullom te syncen)
Per env-var kies je in welke scopes hij beschikbaar is. Handig:
OPENAI_API_KEY_PROD → Production scope
OPENAI_API_KEY_TEST → Preview + Development scope
Op die manier verbruiken preview deploys niet je productie-quota.
4. Cursor agents — Composer vs Background
Cursor heeft twee soorten "agents". Niet hetzelfde, niet uitwisselbaar.
Composer
- Lokaal in je editor (
Cmd+I/Ctrl+I) - Synchroon — jij wacht, agent werkt, jij ziet diffs
- Multi-file edits in één keer
- Terminal-commands met approval
- Voor: pair programming, snelle changes, exploreren
Background Agent
- Runt in Cursor's cloud sandbox
- Asynchroon — jij geeft prompt, gaat iets anders doen
- Maakt zelf een branch + commit + opent PR
- Kan tests draaien, dependencies installeren
- Verbonden via Cursor cloud (eenmalige setup)
- Voor: welomschreven features, parallel werk, PR-prep
Aanroep
Cursor Composer: Cmd+I (Mac) of Ctrl+I (Win/Linux)
Cursor Chat: Cmd+L (kan switchen naar Agent mode)
Background Agent: Cmd+Shift+P → "Open Background Agent"
Of via Slack-integratie
Mentale model
- Composer = pair programming. Jij + AI samen aan dezelfde plek tegelijk.
- Background Agent = delegeren. Je geeft taak, gaat iets anders doen, komt terug als-ie klaar is.
Wanneer welke
| Scenario | Tool |
|---|---|
| Snel iets aanpassen tijdens coden | Composer |
| Refactor over 5 files — wil zien wat hij doet | Composer |
| Onbekend gebied / leren | Composer |
| Welomschreven feature, can-be-async | Background Agent |
| Parallel werken aan 3 features | 3x Background Agent |
| Tijdens vergadering PR voorbereiden | Background Agent |
Hoe schrijf je een goede Background Agent prompt
Een Background Agent ziet je niet — je moet specifiek zijn.
Slecht:
"Voeg search toe."
Goed:
"Maak een nieuwe branch
feature/search. Voeg een controlled input toe bovenaanapp/page.tsx. Filter de Pokémon-lijst op naam terwijl gebruiker typt. Case-insensitive. Gebruik Tailwind. Houd het stijl-consistent met bestaande cards. Push de branch en open een PR met titel 'Add search bar' en korte beschrijving in PR body."
Specifiek: bestandsnamen, gedrag, edge cases, output-formaat (branch + PR + titel).
5. Vercel deployments
Vercel is hosting platform door Next.js team (zelfde bedrijf). Voor Next.js apps de simpelste deploy.
Eerste deployment
- Push je repo naar GitHub
vercel.com→ Add New → Import Git Repository- Kies repo, klik Deploy
- ~60-90s later: live URL
Geen config nodig. Vercel detecteert Next.js automatisch.
Build settings (als je ze nodig hebt)
- Framework: Next.js (auto)
- Build command:
pnpm build(auto) - Output directory:
.next(auto) - Install command:
pnpm install - Root directory: alleen aanpassen als app in subfolder zit (monorepo)
CLI alternatief
pnpm i -g vercel
vercel login
vercel # preview deploy van current dir
vercel --prod # production deploy
vercel env pull # download .env.local van Vercel
6. Preview deployments per branch
Hier komt de magie. Vercel maakt automatisch een preview deploy voor elke branch en elke PR.
Hoe werkt het
git push origin main → Production deploy
(je-app.vercel.app)
git push origin feature/search → Preview deploy
(je-app-git-feature-search-user.vercel.app)
PR open → Vercel comment in PR:
"🚀 Preview: <URL>"
Wat krijg je hiermee
- Reviewers klikken op de URL in de PR, testen de feature live
- Background Agents maken PR → Vercel zet preview neer → klikbaar
- Stakeholders zien een feature voor merge, niet alleen screenshots
- Geen "werkt op mijn laptop" — alles draait op Vercel infra
Belangrijk om in te stellen
- Environment scoping: preview-deploys mogen geen productie-keys gebruiken — gebruik aparte env vars per scope
- Database: in productie wijs je naar prod-DB, in preview kun je naar test-DB wijzen — meer dan een Vercel-feature, eigen architectuur
Comment-bot
Vercel installeert een GitHub App. Die plakt een comment op je PR met:
🚀 Preview Deployment: https://...
✅ Build successful — 1m 23s
View build log
Per push naar de branch wordt deze comment ge-update.
7. GitHub Actions CI
Een CI (Continuous Integration) check draait automatisch op je code. Minimaal: lint + build.
Waarom
- Voor merge weet je: code lint clean, types kloppen, build slaagt
- Cursor Background Agent maakt PR → CI draait → groene check of feedback
- Voorkomt dat broken code in main komt
Minimaal workflow
.github/workflows/ci.yml:
name: CI
on:
pull_request:
branches: [main]
push:
branches: [main]
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v3
with:
version: 9
- uses: actions/setup-node@v4
with:
node-version: 20
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm lint
- run: pnpm build
Wat gebeurt er
- Trigger: PR open of update, of push naar
main - Runner: Ubuntu container op GitHub infra
- Stappen:
- Checkout code
- Install pnpm + Node 20
- Install dependencies
- Run lint (faalt op fouten)
- Run build (faalt op TypeScript errors)
- Status: groene check of rode X op de PR
Tijdsbudget
Voor een kleine Next.js app: 1-2 minuten. Voor grote apps met tests: 3-10 minuten.
Caching
Met cache: pnpm herbruikt GH Actions de node_modules-cache tussen runs — scheelt 60-80% tijd.
8. Branch protection
Standaard kan iedereen pushen naar main. Voor productie wil je dat niet.
Branch protection rules (op GitHub)
- Repo settings → Branches → Add rule
- Branch name pattern:
main - Check: Require a pull request before merging
- Check: Require status checks to pass before merging → select CI workflow
- Check: Do not allow bypassing the above settings
Effect
- Niemand kan direct naar
mainpushen — moet via PR - PR kan pas merge als CI groen is
- Force-push naar main geblokkeerd
- Background Agents werken automatisch via PRs (zo bedoeld)
Voor solo-projecten
Beetje overkill, maar oefenen is goed. En het voorkomt 'fluitje van een cent' bugs naar main.
9. Werkstroom — feature van begin tot productie
De volledige flow zoals je 'm in dit vak gebruikt:
1. Idee voor feature
↓
2. Background Agent prompt (specifiek!)
↓
3. Cursor opent branch + maakt commits + opent PR
↓
4. GitHub Actions CI draait — lint + build
↓
5. Vercel zet preview deploy neer — URL in PR comment
↓
6. Jij/team reviewt: code-diff + live preview
↓
7. Eventueel: commentaar in PR, Background Agent retried
↓
8. Merge PR → main
↓
9. Vercel productie-deploy is automatisch
↓
10. Klaar — live op je-app.vercel.app
Tijdsindicatie voor één feature: 10-30 minuten end-to-end (afhankelijk van complexiteit).
Wat als CI rood is
- Klik op rode X in PR → naar GitHub Actions logs
- Lees error: lint-error, build-error, of test-failure
- Twee opties:
- Composer: open feature branch lokaal, fix met Composer, push
- Background Agent: nieuwe prompt: "fix de CI error in deze PR — lees de logs en repareer"
Wat als preview niet werkt
- Open Vercel dashboard → project → Deployments → klik op preview build
- Build logs lezen
- Vaak: env-var mist (Vercel preview scope leeg)
- Of: dependency die op Vercel niet beschikbaar is
10. Productie-overwegingen
Costs
| Service | Free tier | Wanneer betalen |
|---|---|---|
| Vercel | Hobby tier — gratis voor persoonlijk gebruik | Commercieel of >100GB bandwidth |
| GitHub Actions | 2000 min/maand gratis (public repos unlimited) | Bij grote teams of veel runs |
| Cursor | Hobby (gratis), Pro ($20/mnd), Business | Background Agents zitten in Pro/Business |
| PokéAPI | Volledig gratis, geen rate-limit issues | n.v.t. |
Performance
Vercel doet veel automatisch:
- Edge CDN voor static assets
- ISR (Incremental Static Regeneration) voor
revalidate - Image optimization via
next/image - Automatische gzip/brotli
Voor sub-1s page loads: meestal niks doen.
Observability
- Vercel Analytics — page views + Core Web Vitals (gratis tier beperkt)
- Vercel Logs — server-side console.log zichtbaar
- Sentry / LogRocket — externe tools voor error tracking
- GitHub Actions logs — bewaard 90 dagen
Security
- API keys NOOIT in client (geen
NEXT_PUBLIC_) .env.localin.gitignore(vooraf checken!)- Rotate keys regelmatig — vooral na PR's van Background Agents
- Vercel environment scoping om dev/prod te scheiden
Rollback
Als productie kapot is:
- Vercel dashboard → Deployments
- Vorige werkende deploy → "Promote to Production"
- Klaar, ~10 seconden — geen rebuild nodig
Bronnen
- Next.js fetching: https://nextjs.org/docs/app/building-your-application/data-fetching
- Next.js caching: https://nextjs.org/docs/app/building-your-application/caching
- PokéAPI: https://pokeapi.co/
- Cursor docs: https://docs.cursor.com/
- Cursor Background Agents: https://docs.cursor.com/background-agent
- Vercel docs: https://vercel.com/docs
- Vercel preview deployments: https://vercel.com/docs/deployments/preview-deployments
- Vercel environment variables: https://vercel.com/docs/environment-variables
- GitHub Actions: https://docs.github.com/en/actions
- GitHub branch protection: https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches