fix: les
This commit is contained in:
@@ -1,517 +1,447 @@
|
||||
# Les 13 — Lesstof
|
||||
## Externe APIs + Cursor agents + Vercel deploy
|
||||
# Les 14 — Lesstof
|
||||
## Cursor + Vercel: van leeg project naar preview-deploys
|
||||
|
||||
**Vak:** AI-Assisted Development
|
||||
**Opleiding:** NOVI Hogeschool Utrecht
|
||||
**Vorige les:** Les 12 — Tool Calling
|
||||
**Volgende les:** Les 14 — Agents
|
||||
**Vorige les:** Les 13 — Agents
|
||||
**Volgende les:** Les 15 — RAG + Embeddings
|
||||
|
||||
---
|
||||
|
||||
## Inhoud
|
||||
## Doel van deze les
|
||||
|
||||
1. [Externe APIs in Next.js](#1-externe-apis-in-nextjs)
|
||||
2. [Server- vs client-side fetching](#2-server--vs-client-side-fetching)
|
||||
3. [Environment variabelen](#3-environment-variabelen)
|
||||
4. [Cursor agents — Composer vs Background](#4-cursor-agents--composer-vs-background)
|
||||
5. [Vercel deployments](#5-vercel-deployments)
|
||||
6. [Preview deployments per branch](#6-preview-deployments-per-branch)
|
||||
7. [GitHub Actions CI](#7-github-actions-ci)
|
||||
8. [Branch protection](#8-branch-protection)
|
||||
9. [Werkstroom — feature van begin tot productie](#9-werkstroom--feature-van-begin-tot-productie)
|
||||
10. [Productie-overwegingen](#10-productie-overwegingen)
|
||||
Aan het einde van deze les heb je:
|
||||
|
||||
- Een vers Next.js project gescaffold via `npx create-next-app`
|
||||
- Een GitHub-repo met je code
|
||||
- Een Vercel-project met productie-URL én preview-URL's per branch
|
||||
- Vercel CLI lokaal gekoppeld + één keer `vercel env pull` gedaan
|
||||
- Een werkende `.cursor/rules/general.mdc` en `AGENTS.md` in je repo
|
||||
- Twee features gebouwd via Cursor in eigen branches → twee preview-URL's
|
||||
- Eén Pull Request gemerged naar productie
|
||||
|
||||
---
|
||||
|
||||
## 1. Externe APIs in Next.js
|
||||
## 1. Scaffolden met `npx create-next-app`
|
||||
|
||||
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 het doet
|
||||
|
||||
### 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
|
||||
|
||||
```typescript
|
||||
// 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. Vier manieren om een externe API te fetchen
|
||||
|
||||
Next.js geeft je per fetch-call de keuze hoe je data wilt renderen. Voor 95% van je werk komt het neer op drie server-modes plus client-side. De code verandert minimaal — meestal één optie in je `fetch()`.
|
||||
|
||||
### 2.1 Static (build-time)
|
||||
|
||||
```typescript
|
||||
// app/page.tsx — Server Component
|
||||
async function getPokemon() {
|
||||
const res = await fetch("https://pokeapi.co/api/v2/pokemon?limit=151");
|
||||
return res.json();
|
||||
}
|
||||
```
|
||||
|
||||
- Gefetched tijdens `next build`, daarna **HTML voor altijd**
|
||||
- Geen server-werk per request → snelste optie
|
||||
- Data ververst alleen bij een nieuwe build (= nieuwe deploy)
|
||||
- **Goed voor:** marketing-pagina's, blogs, productlijsten, alles dat zelden verandert
|
||||
- **Niet voor:** prijzen die per minuut updaten, user-specifieke data
|
||||
|
||||
### 2.2 ISR — Incremental Static Regeneration
|
||||
|
||||
```typescript
|
||||
const res = await fetch(URL, { next: { revalidate: 3600 } });
|
||||
```
|
||||
|
||||
- Eerste request: zelfde als static (HTML uit cache)
|
||||
- Na 3600 seconden: volgende request krijgt nog steeds cache, maar achter de schermen wordt de pagina vernieuwd
|
||||
- **Goed voor:** Pokédex detail-pages, een nieuws-feed die niet realtime hoeft, productdetails
|
||||
- **De sweet spot tussen snel en redelijk vers**
|
||||
|
||||
### 2.3 Dynamic (request-time / SSR)
|
||||
|
||||
```typescript
|
||||
const res = await fetch(URL, { cache: "no-store" });
|
||||
```
|
||||
|
||||
- Bij elke request opnieuw gefetched op de server
|
||||
- Altijd 100% vers, maar trager (geen cache)
|
||||
- **Goed voor:** dashboards met live data, user-specifieke views, anything per-request
|
||||
- **Let op cost:** elke request = serverless function call
|
||||
|
||||
### 2.4 Client-side (`useEffect`)
|
||||
|
||||
```typescript
|
||||
"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>;
|
||||
}
|
||||
```
|
||||
|
||||
- Fetch gebeurt in de browser na hydration
|
||||
- Goed voor user-interactie, real-time, infinite scroll
|
||||
- **Cruciaal:** API-keys staan **in de browser** als je hier rechtstreeks naar een externe API roept. Alleen voor publieke APIs, of via een eigen `/api/...` proxy-route.
|
||||
|
||||
### Spiekbriefje
|
||||
|
||||
| Mode | `fetch()` optie | Wanneer |
|
||||
|------|----------------|---------|
|
||||
| Static | `fetch(URL)` (default) | Data verandert per deploy |
|
||||
| ISR | `{ next: { revalidate: N } }` | Data verandert traag |
|
||||
| Dynamic | `{ cache: "no-store" }` | Data verandert per request |
|
||||
| Client | `useEffect` + fetch | User-interactie / live |
|
||||
| Tag-based | `{ next: { tags: ["x"] } }` | Triggered revalidation via `revalidateTag()` |
|
||||
|
||||
---
|
||||
|
||||
## 3. Environment variabelen — server-only vs client-exposed
|
||||
|
||||
### Twee soorten variabelen
|
||||
|
||||
| Type | Voorbeeld | Waar beschikbaar | Veiligheid |
|
||||
|------|-----------|------------------|------------|
|
||||
| Server-only | `OPENAI_API_KEY`, `DATABASE_URL` | Alleen op de server | **Geheim** — nooit zichtbaar voor de browser |
|
||||
| Client-exposed | `NEXT_PUBLIC_APP_ENV`, `NEXT_PUBLIC_APP_URL` | Server + client bundle | **Publiek** — iedereen kan ze zien in DevTools |
|
||||
|
||||
**Regel:** alles met `NEXT_PUBLIC_` prefix wordt ingebakken in de browser-bundle. Zonder prefix = server-only.
|
||||
|
||||
```typescript
|
||||
// ✅ Veilig — server-side gebruik
|
||||
process.env.OPENAI_API_KEY
|
||||
|
||||
// ❌ NOOIT
|
||||
"use client";
|
||||
const key = process.env.NEXT_PUBLIC_OPENAI_KEY; // staat in de HTML response
|
||||
```
|
||||
|
||||
### 3.1 Vercel — drie omgevingen, drie scopes
|
||||
|
||||
Op Vercel heb je per project drie environments. Bij elke env-var kies je in welke scopes hij wordt geïnjecteerd:
|
||||
|
||||
| Scope | Wordt gebruikt bij | URL-patroon |
|
||||
|-------|---------------------|-------------|
|
||||
| **Production** | Push naar `main` | `je-app.vercel.app` |
|
||||
| **Preview** | Push naar elke andere branch | `je-app-git-{branch}-{user}.vercel.app` |
|
||||
| **Development** | Lokaal (`pnpm dev`) | `localhost:3000` |
|
||||
|
||||
### 3.2 Per-omgeving andere waarden
|
||||
|
||||
In **Vercel → Project → Settings → Environment Variables** zet je per variabele drie keer een waarde:
|
||||
|
||||
| Var | Production | Preview | Development |
|
||||
|-----|------------|---------|-------------|
|
||||
| `DATABASE_URL` | productie-DB | staging-DB | lokale DB |
|
||||
| `OPENAI_API_KEY` | echte key | test-key (lage limit) | jouw key |
|
||||
| `STRIPE_KEY` | `sk_live_...` | `sk_test_...` | `sk_test_...` |
|
||||
| `NEXT_PUBLIC_APP_URL` | `je-app.com` | preview-URL | `http://localhost:3000` |
|
||||
|
||||
**Hoe in te stellen:** in de UI: Add new → vink alleen de juiste environment(s) aan → Save.
|
||||
|
||||
**Belangrijke veiligheidsregels:**
|
||||
- Productie-secrets (echte API keys, prod-DB-password): **alleen** Production vinken
|
||||
- Preview krijgt een test-variant, anders kunnen experimentele branches je productie raken
|
||||
- Development: `vercel env pull` om Vercel's dev-vars naar je `.env.local` te syncen, of zelf invullen
|
||||
|
||||
### 3.3 Verandering pakt pas door bij nieuwe build
|
||||
|
||||
Bestaande deploys zien een nieuwe env-var niet automatisch. Na het toevoegen of wijzigen: **redeploy** (Deployments → ··· → Redeploy) of push een nieuwe commit.
|
||||
|
||||
---
|
||||
|
||||
## 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
|
||||
`create-next-app` is het officiële scaffold-commando van het Next.js team. Eén commando, een paar interactieve vragen, en je hebt een werkende Next.js-app met sane defaults.
|
||||
|
||||
```bash
|
||||
pnpm i -g vercel
|
||||
vercel login
|
||||
vercel # preview deploy van current dir
|
||||
vercel --prod # production deploy
|
||||
vercel env pull # download .env.local van Vercel
|
||||
npx create-next-app@latest mijn-portfolio
|
||||
```
|
||||
|
||||
### De prompts uitgelegd
|
||||
|
||||
| Vraag | Aanbevolen | Waarom |
|
||||
|-------|-----------|--------|
|
||||
| TypeScript? | **Ja** | strict typing voorkomt veel bugs |
|
||||
| ESLint? | **Ja** | code-style consistency |
|
||||
| Tailwind CSS? | **Ja** | utility-first styling, breed gebruikt |
|
||||
| `src/` directory? | **Ja** | houdt project-root schoon |
|
||||
| App Router? | **Ja** | de moderne Next.js flow (server components) |
|
||||
| Turbopack? | **Ja** | snellere dev-builds |
|
||||
| Import alias? | **`@/*`** | `@/components/foo` ipv `../../components/foo` |
|
||||
|
||||
### Wat je krijgt
|
||||
|
||||
```
|
||||
mijn-portfolio/
|
||||
├── .gitignore # node_modules, .next, .env.local zijn al gegitignored
|
||||
├── next.config.ts
|
||||
├── package.json
|
||||
├── tsconfig.json
|
||||
├── src/
|
||||
│ └── app/
|
||||
│ ├── layout.tsx # root layout
|
||||
│ ├── page.tsx # homepage
|
||||
│ └── globals.css
|
||||
└── public/
|
||||
```
|
||||
|
||||
Direct `npm run dev` → `localhost:3000` werkt. Vanaf hier ben je productief.
|
||||
|
||||
---
|
||||
|
||||
## 2. Git + GitHub
|
||||
|
||||
### Init en eerste push
|
||||
|
||||
```bash
|
||||
git init
|
||||
git add .
|
||||
git commit -m "init"
|
||||
git branch -M main
|
||||
|
||||
# Met gh CLI (snelst):
|
||||
gh repo create mijn-portfolio --public --source=. --push
|
||||
|
||||
# Of handmatig:
|
||||
# 1. github.com → New repository → naam → Create (leeg, GEEN README)
|
||||
# 2. git remote add origin <url>
|
||||
# 3. git push -u origin main
|
||||
```
|
||||
|
||||
### Veelgemaakte fouten
|
||||
|
||||
| Fout | Oplossing |
|
||||
|------|-----------|
|
||||
| `gh: command not found` | `brew install gh` (Mac) / `winget install GitHub.cli` (Windows) |
|
||||
| `Authentication required` | `gh auth login` doorlopen |
|
||||
| `error: src refspec main does not match any` | Eerst `git add . && git commit -m "init"` |
|
||||
| `fatal: remote origin already exists` | `git remote remove origin` en opnieuw |
|
||||
|
||||
### Wat zit er NIET in je commit
|
||||
|
||||
Check je `.gitignore` — Next.js zet er standaard de juiste regels in:
|
||||
|
||||
```
|
||||
node_modules/
|
||||
.next/
|
||||
.env.local
|
||||
.env*.local
|
||||
```
|
||||
|
||||
**Belangrijk:** controleer altijd na je eerste push op github.com dat `.env.local` daar NIET staat. Een gelekte secret-key is dezelfde dag onveilig.
|
||||
|
||||
---
|
||||
|
||||
## 3. Vercel — drie stappen naar productie
|
||||
|
||||
### Project importeren
|
||||
|
||||
1. Ga naar **vercel.com/new**
|
||||
2. Klik **Import Git Repository**
|
||||
3. Kies je `mijn-portfolio` repo
|
||||
4. Framework auto-detect: **Next.js**
|
||||
5. Klik **Deploy**
|
||||
|
||||
Wacht ±45 seconden. Wat Vercel doet:
|
||||
- Kloont je repo
|
||||
- Detecteert framework
|
||||
- Draait `npm install`
|
||||
- Draait `npm run build`
|
||||
- Deploy't naar Edge Network
|
||||
- Geeft je een productie-URL
|
||||
|
||||
### Twee URL-types
|
||||
|
||||
| Type | URL-format | Trigger |
|
||||
|------|------------|---------|
|
||||
| **Productie** | `mijn-portfolio-<scope>.vercel.app` | push naar `main` |
|
||||
| **Preview** | `mijn-portfolio-git-<branch>-<scope>.vercel.app` | push naar elke andere branch |
|
||||
|
||||
### Wat je vanaf nu krijgt zonder extra werk
|
||||
|
||||
- Elke push naar GitHub → automatische deploy
|
||||
- Elke nieuwe branch → eigen preview-URL
|
||||
- Pull Request → Vercel-bot post preview-URL als comment
|
||||
- Productie-URL update vanzelf bij merge naar `main`
|
||||
|
||||
---
|
||||
|
||||
## 4. Environment Variables in Vercel
|
||||
|
||||
### Drie environments
|
||||
|
||||
| Environment | Actief bij |
|
||||
|-------------|-----------|
|
||||
| Production | deploys vanaf `main` |
|
||||
| Preview | alle andere branches |
|
||||
| Development | `vercel dev` lokaal |
|
||||
|
||||
Je kunt env vars in één, twee of alle drie tegelijk zetten.
|
||||
|
||||
### `NEXT_PUBLIC_` prefix
|
||||
|
||||
| Prefix | Wat gebeurt | Voorbeeld |
|
||||
|--------|-------------|-----------|
|
||||
| `NEXT_PUBLIC_FOO` | wordt in browser-bundle gestopt | publieke API-URL, Supabase anon-key |
|
||||
| `FOO` (geen prefix) | alleen server-side beschikbaar | OpenAI key, Stripe secret, DB password |
|
||||
|
||||
**Regel:** zet `NEXT_PUBLIC_` ALLEEN op variabelen die echt publiek mogen zijn. Twijfel? Geen prefix.
|
||||
|
||||
### Via het dashboard
|
||||
|
||||
Settings → Environment Variables → Add. Vul naam + waarde, kies environments, save.
|
||||
|
||||
---
|
||||
|
||||
## 5. Vercel CLI
|
||||
|
||||
### Installeren
|
||||
|
||||
```bash
|
||||
npm i -g vercel
|
||||
vercel login # opent browser voor auth
|
||||
```
|
||||
|
||||
### Belangrijkste commando's
|
||||
|
||||
```bash
|
||||
vercel link # lokale folder → Vercel project
|
||||
vercel env pull .env.local # productie env vars → lokaal
|
||||
vercel env pull --environment=preview .env.local
|
||||
|
||||
vercel env add OPENAI_API_KEY production
|
||||
vercel env rm OPENAI_API_KEY production
|
||||
vercel env ls # lijst alle vars
|
||||
|
||||
vercel # interactieve deploy
|
||||
vercel --prod # productie deploy (handmatig)
|
||||
|
||||
vercel logs # runtime logs
|
||||
vercel logs --follow # stream logs live
|
||||
```
|
||||
|
||||
### Typische workflow
|
||||
|
||||
```bash
|
||||
# Project klaarzetten (eenmalig):
|
||||
vercel link
|
||||
|
||||
# Bij elke nieuwe env var op productie:
|
||||
vercel env pull .env.local
|
||||
|
||||
# Bij env var rotatie:
|
||||
vercel env rm DATABASE_URL production
|
||||
vercel env add DATABASE_URL production
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. Preview deployments per branch
|
||||
## 6. Cursor — de IDE
|
||||
|
||||
Hier komt de magie. Vercel maakt automatisch een preview deploy voor **elke branch en elke PR**.
|
||||
### Wat is Cursor
|
||||
|
||||
### Hoe werkt het
|
||||
Cursor is een VS Code-fork met AI als kernfeature. Niet een extensie — het is de editor. Werkt met Claude, GPT, Gemini en lokale modellen.
|
||||
|
||||
```
|
||||
git push origin main → Production deploy
|
||||
(je-app.vercel.app)
|
||||
### Cursor 3 — twee windows
|
||||
|
||||
git push origin feature/search → Preview deploy
|
||||
(je-app-git-feature-search-user.vercel.app)
|
||||
In Cursor 3 zijn er **twee hoofdvensters**:
|
||||
|
||||
PR open → Vercel comment in PR:
|
||||
"🚀 Preview: <URL>"
|
||||
| Window | Wat je er doet | Switch met |
|
||||
|--------|----------------|-----------|
|
||||
| **Editor Window** (classic) | Code schrijven en reviewen — als VS Code | Cmd+Shift+N → Editor |
|
||||
| **Agents Window** | Meerdere agents parallel managen | Cmd+Shift+N → Agents |
|
||||
|
||||
**Sneltoets om te onthouden:** `Cmd+Shift+N` switcht tussen beide.
|
||||
|
||||
**Binnen het Editor Window:**
|
||||
- **Cmd+L** — chat-paneel (kies modus: Ask / Agent / Plan)
|
||||
- **Cmd+K** — inline edit op selectie
|
||||
- **Tab** — accepteer AI auto-completion
|
||||
- **Cmd+P** — file search (zoals VS Code)
|
||||
|
||||
**Binnen het Agents Window:**
|
||||
- Overzicht met lokale, cloud en remote agents
|
||||
- Op één plek alle running + done agents
|
||||
|
||||
**Gouden regel:**
|
||||
- Code schrijven of 1 feature bouwen → **Editor Window** + **Agent mode** in chat
|
||||
- Meerdere features parallel → **Agents Window** met Background agents
|
||||
- Snelle tweak in 1 file → **Cmd+K**
|
||||
|
||||
> **Versie-noot:** info hieronder is gebaseerd op de officiële Cursor 3 documentatie (`cursor.com/docs`). Cursor 3.7 en hoger heeft alle besproken features. Sommige UI-details kunnen per minor-versie iets verschillen.
|
||||
|
||||
### Editor Window — stap voor stap
|
||||
|
||||
Je hoofdwerkplek voor code:
|
||||
|
||||
1. **Cmd+Shift+N** — switcht naar Editor Window (als je in Agents Window zat)
|
||||
2. Layout: file explorer links, editor midden, terminal beneden (klassieke VS Code-stijl)
|
||||
3. **Cmd+L** opent chat-paneel rechts
|
||||
4. Voor snelle inline edits: selecteer code → **Cmd+K** → beschrijf wijziging
|
||||
5. Cursor toont **diff inline** in de editor (niet in een aparte panel)
|
||||
6. **Tab** om te accepteren, **Esc** om te rejecten
|
||||
7. **Cmd+P** voor file search
|
||||
8. **Tab** accepteert AI auto-completion suggesties
|
||||
|
||||
**Wanneer:** je standaard coding-flow, files reviewen met split screens, VS Code extensies gebruiken (linters, formatters, debugger).
|
||||
|
||||
**Tip:** kun je Cursor laten starten in Editor Window als default? Ja. Settings → "Open Agents Window on startup" → uit. Of start vanuit terminal met `cursor --classic`.
|
||||
|
||||
### Agent mode (binnen chat in Editor Window) — stap voor stap
|
||||
|
||||
De AI-modus *binnen* het chat-paneel:
|
||||
|
||||
1. **Cmd+L** opent chat-paneel rechts (in Editor Window)
|
||||
2. Bovenaan chat: **mode-selector** → kies **"Agent"**
|
||||
3. Typ de **hele taak** (niet een specifieke kleine wijziging)
|
||||
4. *"Bouw een /about pagina met team-grid in onze huisstijl"*
|
||||
5. **Enter** — agent start zelfstandig
|
||||
6. Cursor toont een lopende **takenlijst** + voortgang per stap
|
||||
7. Agent edit meerdere files, runt terminal-commando's (vraagt vooraf), kan zelfs **web browsen**
|
||||
8. **Geen limiet** op aantal tool-calls per taak
|
||||
9. Aan het einde: samenvatting → **Keep / Accept all** of per file
|
||||
|
||||
**Wanneer:** grotere features die meerdere bestanden raken, refactors, nieuwe pagina's of API-routes.
|
||||
|
||||
**Belangrijke tip:** hou je prompt specifiek. *"Bouw een about-pagina met team-grid"* = goed. *"Bouw een mooie website"* = veel te open.
|
||||
|
||||
### Background agents (Agents Window) — stap voor stap
|
||||
|
||||
**Async cloud-based agents** in geïsoleerde VMs:
|
||||
|
||||
**Cmd+Shift+N** → Agents Window opent.
|
||||
|
||||
**Een agent aanmaken:**
|
||||
1. In Agents Window: klik **New agent** (of `+`)
|
||||
2. Kies environment: **local / cloud / remote SSH**
|
||||
3. Beschrijf de taak — specifiek, als een ticket
|
||||
4. Optioneel: branch-naam (`feature/about`)
|
||||
5. Klik **Start**
|
||||
6. **Cmd+Shift+N** terug naar Editor Window — agent babysit zichzelf
|
||||
|
||||
**Resultaat ophalen:**
|
||||
1. **Cmd+Shift+N** naar Agents Window
|
||||
2. Klare agents staan op **Done** in de agents-lijst
|
||||
3. Klik agent → zie **diff + commit message + alle stappen**
|
||||
4. **Open in PR** → automatische PR op GitHub
|
||||
5. Vercel maakt preview-URL → review → merge
|
||||
|
||||
**Triggers van buitenaf:** Background agents kun je in Cursor 3 ook starten vanuit je telefoon, Slack, GitHub of Linear — handig tijdens vergaderingen.
|
||||
|
||||
**Wanneer:** 2–4 parallelle features, lange refactors die je niet wilt babysitten, taken vanaf mobiel.
|
||||
|
||||
### Context — `@`-mentions
|
||||
|
||||
In chat type je `@` voor een autocomplete. Wat je kunt mention'en:
|
||||
|
||||
| Tag | Wat het doet |
|
||||
|-----|--------------|
|
||||
| `@file:foo.tsx` | inclusief één specifiek bestand |
|
||||
| `@folder:components` | hele map als context |
|
||||
| `@code:functionName` | losse functie of class |
|
||||
| `@docs` | externe documentatie |
|
||||
| `@web` | live web-search |
|
||||
| `@git` | git history / blame |
|
||||
| `@recommended` | Cursor suggereert zelf relevante bestanden |
|
||||
|
||||
**Tip:** hou de scope klein. Veel mentions in één chat verslechtert de output, niet verbetert.
|
||||
|
||||
### Cursor Rules
|
||||
|
||||
Markdown-bestanden in `.cursor/rules/` die aan elke prompt worden toegevoegd als systeem-instructie.
|
||||
|
||||
**Voorbeeld `.cursor/rules/general.mdc`:**
|
||||
|
||||
```markdown
|
||||
---
|
||||
description: Algemene project-conventies
|
||||
alwaysApply: true
|
||||
---
|
||||
|
||||
- TypeScript strict mode
|
||||
- Tailwind voor styling — geen CSS modules
|
||||
- Server components by default; "use client" alleen waar nodig
|
||||
- Imports met @/ alias
|
||||
- Geen any-types
|
||||
```
|
||||
|
||||
### Wat krijg je hiermee
|
||||
YAML front-matter opties:
|
||||
- `alwaysApply: true/false` — actief in elke prompt
|
||||
- `globs: ["**/*.test.ts"]` — alleen actief op matching bestanden
|
||||
- `description: "..."` — wat de rule doet
|
||||
|
||||
- **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
|
||||
### Project context — `AGENTS.md`
|
||||
|
||||
### Belangrijk om in te stellen
|
||||
Eén markdown-bestand in je repo-root dat beschrijft:
|
||||
- Tech stack + waarom die keuzes
|
||||
- Architectuur en belangrijke patronen
|
||||
- Hoe lokaal draaien, hoe deployen
|
||||
- Pointers naar belangrijke bestanden
|
||||
|
||||
- **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
|
||||
`AGENTS.md` wordt door Cursor, Claude Code én GitHub Copilot gelezen. Eén file, meerdere tools.
|
||||
|
||||
### Comment-bot
|
||||
### Background agents — async cloud
|
||||
|
||||
Vercel installeert een GitHub App. Die plakt een comment op je PR met:
|
||||
Tweede Cursor-sessie die asynchroon op een feature werkt, in een eigen Git branch, in een aparte tab.
|
||||
|
||||
```
|
||||
🚀 Preview Deployment: https://...
|
||||
✅ Build successful — 1m 23s
|
||||
View build log
|
||||
```
|
||||
**Workflow:**
|
||||
1. Beschrijf feature → klik "open in background"
|
||||
2. Agent werkt in eigen branch, jij blijft in main editor
|
||||
3. Agent meldt zich klaar → review diff → apply/iterate/discard
|
||||
|
||||
Per push naar de branch wordt deze comment ge-update.
|
||||
**Wanneer:** voor parallelle features. Drie of vier agents tegelijk is normaal.
|
||||
|
||||
### Top 7 tips voor power-users
|
||||
|
||||
1. **Cmd+I** voor Composer met multi-file context (niet alleen Cmd+L)
|
||||
2. **`@-recommended`** laat Cursor zelf relevante bestanden voorstellen
|
||||
3. **Plan + Apply per stap** — niet alles in één klap accepteren
|
||||
4. **`alwaysApply: false`** rules voor opt-in conventies
|
||||
5. **Auto-mode** — Cursor kiest beste model per taak
|
||||
6. **Cmd+Shift+Enter** voor diff-preview vóór accept
|
||||
7. **Notepads** — herbruikbare prompt-snippets per project
|
||||
|
||||
---
|
||||
|
||||
## 7. GitHub Actions CI
|
||||
## 7. De feature-workflow
|
||||
|
||||
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`:
|
||||
|
||||
```yaml
|
||||
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:
|
||||
### Vijf stappen, één feature
|
||||
|
||||
```
|
||||
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
|
||||
1. Plan → Cursor chat: beschrijf de feature, vraag plan
|
||||
2. Branch → git checkout -b feature/x (Cursor kan dit ook)
|
||||
3. Build → Apply het plan, eventueel inline tweaks
|
||||
4. Commit+ → git add . && git commit -m "feat: x" && git push
|
||||
Push
|
||||
5. Preview → Vercel maakt preview-URL, test & itereer
|
||||
```
|
||||
|
||||
Tijdsindicatie voor één feature: 10-30 minuten end-to-end (afhankelijk van complexiteit).
|
||||
### Eén feature ≈ 10 minuten
|
||||
|
||||
### Wat als CI rood is
|
||||
Inclusief AI denkwerk. Wat dit versnelt is niet dat AI mooier code schrijft — het is dat de **cycle korter wordt**.
|
||||
|
||||
- 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"
|
||||
### Anti-patterns
|
||||
|
||||
### 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
|
||||
- Geen branch maken, direct op `main` werken (geen preview, geen rollback)
|
||||
- 5 features in één commit ("WIP" commits)
|
||||
- Plan niet lezen → Apply → het deugt niet → terugkrabbelen
|
||||
- Background agents starten zonder duidelijke prompt → bagger output
|
||||
|
||||
---
|
||||
|
||||
## 10. Productie-overwegingen
|
||||
## 8. Production checklist
|
||||
|
||||
### Costs
|
||||
Voordat je een app "klaar" beschouwt:
|
||||
|
||||
| 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
|
||||
| Check | Waarom |
|
||||
|-------|--------|
|
||||
| Productie-URL werkt voor alle routes | Anders krijgen gebruikers 404 |
|
||||
| Env vars staan goed (alle environments) | Anders crashen API routes |
|
||||
| `.env.local` staat in `.gitignore` | Anders lekken keys op GitHub |
|
||||
| Eerste feature-branch + PR gedaan | Bewijs dat preview-flow werkt |
|
||||
| `.cursor/rules/general.mdc` is ingevuld | Anders weet Cursor je conventies niet |
|
||||
| `AGENTS.md` is ingevuld | Anders weet AI de architectuur niet |
|
||||
| Build slaagt zonder warnings | Anders begin je met technical debt |
|
||||
| `404` en `error.tsx` pages bestaan | Voor nette foutmeldingen |
|
||||
|
||||
---
|
||||
|
||||
## Bronnen
|
||||
## 9. Verder lezen
|
||||
|
||||
- **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
|
||||
- **Cursor docs** — `docs.cursor.com` — features, shortcuts, Rules-syntax
|
||||
- **Vercel docs** — `vercel.com/docs` — alle CLI-commando's, env vars, domains
|
||||
- **Next.js docs** — `nextjs.org/docs` — App Router, server components, routing
|
||||
- **AGENTS.md spec** — `agentsmd.org` — community-gedragen format
|
||||
- **Pro Git** (gratis online) — `git-scm.com/book` — definitieve Git-referentie
|
||||
|
||||
---
|
||||
|
||||
## Samenvatting
|
||||
|
||||
Vandaag heb je geleerd:
|
||||
|
||||
- Scaffolden met `npx create-next-app` — alle defaults uitgelegd
|
||||
- Git init + GitHub push (via `gh` CLI of handmatig)
|
||||
- Vercel project koppelen — productie + preview URLs gratis erbij
|
||||
- Vercel CLI — `link`, `env pull/add/rm`, `logs`, `--prod`
|
||||
- Environment variables — drie environments, `NEXT_PUBLIC_` prefix
|
||||
- Cursor: chat, plan, build, inline edit, rules, AGENTS.md, background agents
|
||||
- Feature workflow: plan → branch → build → push → preview
|
||||
- Top tips voor Cursor power-users
|
||||
|
||||
Volgende les bouwen we hier RAG bovenop — een PDF Q&A-app met embeddings.
|
||||
|
||||
Reference in New Issue
Block a user