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

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

  1. Externe APIs in Next.js
  2. Server- vs client-side fetching
  3. Environment variabelen
  4. Cursor agents — Composer vs Background
  5. Vercel deployments
  6. Preview deployments per branch
  7. GitHub Actions CI
  8. Branch protection
  9. Werkstroom — feature van begin tot productie
  10. 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 async zijn — await direct in component
  • Errors moet je zelf afvangen (!res.ok)
  • fetch in 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 pull om 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 bovenaan app/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

  1. Push je repo naar GitHub
  2. vercel.com → Add New → Import Git Repository
  3. Kies repo, klik Deploy
  4. ~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

  1. Trigger: PR open of update, of push naar main
  2. Runner: Ubuntu container op GitHub infra
  3. Stappen:
    • Checkout code
    • Install pnpm + Node 20
    • Install dependencies
    • Run lint (faalt op fouten)
    • Run build (faalt op TypeScript errors)
  4. 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)

  1. Repo settings → Branches → Add rule
  2. Branch name pattern: main
  3. Check: Require a pull request before merging
  4. Check: Require status checks to pass before merging → select CI workflow
  5. Check: Do not allow bypassing the above settings

Effect

  • Niemand kan direct naar main pushen — 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.local in .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:

  1. Vercel dashboard → Deployments
  2. Vorige werkende deploy → "Promote to Production"
  3. Klaar, ~10 seconden — geen rebuild nodig

Bronnen