fix: implement lessons feedback
This commit is contained in:
@@ -72,7 +72,13 @@ Introductie tot standalone AI coding tools. OpenCode als eerste hands-on ervarin
|
||||
|
||||
## Huiswerk (2 uur)
|
||||
|
||||
**Component Library Bouwen:**
|
||||
### React Opfrissen (30 min)
|
||||
**BELANGRIJK:** Voordat je verder gaat, fris je React kennis op via EdHub.
|
||||
- Bekijk de React basics modules
|
||||
- Focus op: components, props, state, hooks
|
||||
- Dit is essentieel voor de rest van de cursus!
|
||||
|
||||
### Component Library Bouwen (1.5 uur)
|
||||
Bouw een volledige landing page component library met OpenCode:
|
||||
- Hero section
|
||||
- Features section (3 cards met icons)
|
||||
|
||||
@@ -20,6 +20,9 @@ Cruciale kennis over veilig en ethisch werken met AI, gecombineerd met professio
|
||||
|
||||
## Te Behandelen
|
||||
|
||||
### Groepsdiscussie (15 min)
|
||||
Bespreek klassikaal de blog posts uit Les 2 - wat waren de ervaringen met AI-assisted coding? Welke limitations ontdekte je?
|
||||
|
||||
### Deel 1: Ethics, Privacy & Security (1 uur)
|
||||
|
||||
**Privacy Risico's - Wat NOOIT te delen:**
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
---
|
||||
|
||||
## Hoofdstuk
|
||||
**Hoofdstuk 2: Intermediate** (Les 4-9)
|
||||
**Deel 1: AI Foundations** (Les 1-4)
|
||||
|
||||
## Beschrijving
|
||||
Geavanceerde prompt engineering technieken en introductie tot Skills.sh voor herbruikbare AI best practices.
|
||||
@@ -20,6 +20,9 @@ Geavanceerde prompt engineering technieken en introductie tot Skills.sh voor her
|
||||
|
||||
## Te Behandelen
|
||||
|
||||
### Groepsdiscussie (15 min)
|
||||
Bespreek klassikaal de security/privacy bevindingen uit Les 3 - welke issues vonden jullie in AI-gegenereerde code? Hoe zien jullie AI Safety Checklists eruit?
|
||||
|
||||
### Geavanceerde Prompt Engineering
|
||||
- Zero-shot vs few-shot prompting
|
||||
- Chain-of-thought reasoning
|
||||
|
||||
@@ -1,307 +1,393 @@
|
||||
# Les 5: AI Tool Selection & Workflows
|
||||
# Les 5: TypeScript Basics
|
||||
|
||||
---
|
||||
|
||||
## Hoofdstuk
|
||||
**Hoofdstuk 2: Intermediate** (Les 4-9)
|
||||
**Deel 2: Technical Foundations** (Les 5-9)
|
||||
|
||||
## Beschrijving
|
||||
Leer de sterke en zwakke punten van elke AI tool kennen. Ontwikkel een framework om de juiste tool te kiezen voor de juiste taak en bouw je eigen workflow.
|
||||
Introductie tot TypeScript voor React developers. Leer waarom TypeScript waardevol is, hoe je types schrijft, en hoe je het combineert met React.
|
||||
|
||||
---
|
||||
|
||||
## Te Behandelen
|
||||
|
||||
### Waarom Tool Selection Belangrijk Is
|
||||
### Waarom TypeScript?
|
||||
|
||||
Je kent nu meerdere AI tools:
|
||||
- ChatGPT (brainstormen, planning, uitleg)
|
||||
- Claude (lange context, nuance, analyse)
|
||||
- v0.dev (UI prototyping)
|
||||
- OpenCode (code schrijven met project context)
|
||||
|
||||
**Het probleem:** Elke tool heeft sterke en zwakke punten. De juiste tool kiezen bespaart tijd en levert betere resultaten.
|
||||
|
||||
---
|
||||
|
||||
### Tool Vergelijking
|
||||
|
||||
| Tool | Sterk in | Minder sterk in | Kosten |
|
||||
|------|----------|-----------------|--------|
|
||||
| **ChatGPT** | Brainstormen, uitleg, planning, algemene kennis | Grote codebases, lange context | Gratis / Pro €20/maand |
|
||||
| **Claude** | Lange documenten, nuance, analyse, veiligheid | Soms te voorzichtig, geen images genereren | Gratis / Pro $20/maand |
|
||||
| **v0.dev** | UI components, snel prototypen, Tailwind | Complexe logica, backend | Gratis tier |
|
||||
| **OpenCode** | Code schrijven, project context, terminal | Geen web access, geen images | Gratis |
|
||||
|
||||
---
|
||||
|
||||
### Tool Selection Framework
|
||||
|
||||
**Stap 1: Identificeer de taak**
|
||||
- Wat wil je bereiken?
|
||||
- Hoe complex is het?
|
||||
- Hoeveel context is nodig?
|
||||
|
||||
**Stap 2: Kies de juiste tool**
|
||||
**Het probleem met JavaScript:**
|
||||
```javascript
|
||||
function greet(name) {
|
||||
return "Hello, " + name.toUpperCase();
|
||||
}
|
||||
|
||||
greet(42); // Runtime error! 42.toUpperCase is not a function
|
||||
```
|
||||
Als je wilt... Gebruik...
|
||||
─────────────────────────────────────────────────
|
||||
Brainstormen over een idee → ChatGPT
|
||||
Een lange codebase analyseren → Claude
|
||||
Snel een UI component maken → v0.dev
|
||||
Code schrijven met project context → OpenCode
|
||||
Een complex document begrijpen → Claude
|
||||
Uitleg krijgen over een concept → ChatGPT
|
||||
React component met styling → v0.dev
|
||||
Feature implementeren in project → OpenCode
|
||||
|
||||
**De oplossing met TypeScript:**
|
||||
```typescript
|
||||
function greet(name: string): string {
|
||||
return "Hello, " + name.toUpperCase();
|
||||
}
|
||||
|
||||
greet(42); // Compile error! Argument of type 'number' is not assignable to type 'string'
|
||||
```
|
||||
|
||||
**Voordelen:**
|
||||
- Fouten vinden VOORDAT je code runt
|
||||
- Betere autocomplete in je editor
|
||||
- Code is zelf-documenterend
|
||||
- AI tools begrijpen je code beter
|
||||
|
||||
---
|
||||
|
||||
### Basic Types
|
||||
|
||||
```typescript
|
||||
// Primitives
|
||||
let name: string = "Tim";
|
||||
let age: number = 25;
|
||||
let isStudent: boolean = true;
|
||||
|
||||
// Arrays
|
||||
let numbers: number[] = [1, 2, 3];
|
||||
let names: string[] = ["Tim", "Anna"];
|
||||
|
||||
// Alternative array syntax
|
||||
let scores: Array<number> = [90, 85, 88];
|
||||
|
||||
// Objects
|
||||
let user: { name: string; age: number } = {
|
||||
name: "Tim",
|
||||
age: 25
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Workflow Patterns
|
||||
### Type Inference
|
||||
|
||||
**Pattern 1: Planning → Prototyping → Implementation**
|
||||
```
|
||||
1. ChatGPT: Brainstorm features, maak planning
|
||||
2. v0.dev: Genereer UI prototypes
|
||||
3. OpenCode: Implementeer met project context
|
||||
TypeScript raadt types vaak zelf:
|
||||
|
||||
```typescript
|
||||
// TypeScript weet dat dit een string is
|
||||
let message = "Hello"; // type: string
|
||||
|
||||
// TypeScript weet dat dit een number is
|
||||
let count = 42; // type: number
|
||||
|
||||
// TypeScript weet wat de functie returned
|
||||
function double(x: number) {
|
||||
return x * 2; // return type: number (inferred)
|
||||
}
|
||||
```
|
||||
|
||||
**Pattern 2: Research → Design → Build**
|
||||
```
|
||||
1. ChatGPT/Claude: Research beste aanpak
|
||||
2. v0.dev: Design components
|
||||
3. OpenCode: Bouw en integreer
|
||||
```
|
||||
**Regel:** Je hoeft niet altijd types te schrijven. Laat TypeScript inferren waar mogelijk.
|
||||
|
||||
**Pattern 3: Quick Iteration**
|
||||
```
|
||||
1. v0.dev: Snel component genereren
|
||||
2. OpenCode: Aanpassen en integreren
|
||||
3. Repeat
|
||||
---
|
||||
|
||||
### Interfaces
|
||||
|
||||
Voor het beschrijven van object shapes:
|
||||
|
||||
```typescript
|
||||
interface User {
|
||||
id: number;
|
||||
name: string;
|
||||
email: string;
|
||||
isActive: boolean;
|
||||
}
|
||||
|
||||
const user: User = {
|
||||
id: 1,
|
||||
name: "Tim",
|
||||
email: "tim@example.com",
|
||||
isActive: true
|
||||
};
|
||||
|
||||
// Optional properties met ?
|
||||
interface Product {
|
||||
id: number;
|
||||
name: string;
|
||||
price: number;
|
||||
description?: string; // optioneel
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Praktijk: Dezelfde Taak, Drie Tools
|
||||
### Type Aliases
|
||||
|
||||
**Opdracht:** Bouw een Contact Form component
|
||||
Alternatief voor interfaces, meer flexibel:
|
||||
|
||||
**Met ChatGPT:**
|
||||
```
|
||||
Prompt: Ik wil een contact form maken met React en Tailwind.
|
||||
Velden: naam, email, bericht. Validatie nodig.
|
||||
Geef me de code en leg uit hoe het werkt.
|
||||
```
|
||||
→ Krijg: Uitleg + code, maar zonder project context
|
||||
```typescript
|
||||
// Type alias voor object
|
||||
type User = {
|
||||
id: number;
|
||||
name: string;
|
||||
};
|
||||
|
||||
**Met v0.dev:**
|
||||
```
|
||||
Prompt: Modern contact form with name, email, message fields.
|
||||
Tailwind styling, validation, responsive design.
|
||||
```
|
||||
→ Krijg: Visueel prototype, direct te gebruiken
|
||||
// Type alias voor union types
|
||||
type Status = "pending" | "approved" | "rejected";
|
||||
|
||||
**Met OpenCode:**
|
||||
// Type alias voor functie
|
||||
type GreetFunction = (name: string) => string;
|
||||
```
|
||||
Prompt: Maak een ContactForm component in src/components/
|
||||
met naam, email en bericht velden. Gebruik onze bestaande
|
||||
Input en Button components. Voeg Zod validatie toe.
|
||||
```
|
||||
→ Krijg: Geïntegreerde code die past in je project
|
||||
|
||||
**Interface vs Type:**
|
||||
- Interface: voor objecten, kan extended worden
|
||||
- Type: voor alles, meer flexibel
|
||||
|
||||
---
|
||||
|
||||
### Wanneer Combineer Je Tools?
|
||||
### TypeScript met React
|
||||
|
||||
**Scenario 1: Nieuwe feature bouwen**
|
||||
1. ChatGPT: "Hoe zou je een dark mode toggle implementeren in React?"
|
||||
2. v0.dev: "Dark mode toggle component with smooth transition"
|
||||
3. OpenCode: "Integreer deze toggle in onze navbar, sla preference op in localStorage"
|
||||
**Props typen:**
|
||||
|
||||
**Scenario 2: Bug oplossen**
|
||||
1. OpenCode: Vraag om bug te identificeren
|
||||
2. Claude: Als de foutmelding complex is, vraag om uitleg
|
||||
3. OpenCode: Implementeer de fix
|
||||
```typescript
|
||||
// Interface voor props
|
||||
interface ButtonProps {
|
||||
label: string;
|
||||
onClick: () => void;
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
**Scenario 3: Nieuwe technologie leren**
|
||||
1. ChatGPT: "Leg uit hoe React Server Components werken"
|
||||
2. v0.dev: "Example of React Server Component with data fetching"
|
||||
3. OpenCode: "Help me dit toe te passen in mijn Next.js project"
|
||||
// Component met typed props
|
||||
function Button({ label, onClick, disabled = false }: ButtonProps) {
|
||||
return (
|
||||
<button onClick={onClick} disabled={disabled}>
|
||||
{label}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
// Gebruik
|
||||
<Button label="Click me" onClick={() => console.log("Clicked!")} />
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Anti-Patterns (Wat Niet Te Doen)
|
||||
### useState met Types
|
||||
|
||||
**❌ Verkeerde tool voor de taak:**
|
||||
- ChatGPT vragen om een hele app te bouwen → te weinig context
|
||||
- v0.dev vragen om complexe backend logica → niet zijn sterke punt
|
||||
- OpenCode vragen om design inspiratie → kan geen images maken
|
||||
```typescript
|
||||
import { useState } from 'react';
|
||||
|
||||
**❌ Heen en weer kopiëren zonder begrip:**
|
||||
- Kopieer niet blind code van ChatGPT naar je project
|
||||
- Begrijp eerst WAT de code doet
|
||||
// Type inference werkt vaak
|
||||
const [count, setCount] = useState(0); // number
|
||||
|
||||
**❌ Dezelfde prompt in elke tool:**
|
||||
- Pas je prompt aan per tool
|
||||
- v0.dev wil visuele beschrijvingen
|
||||
- OpenCode wil project-specifieke context
|
||||
// Explicit type voor complexe data
|
||||
interface User {
|
||||
id: number;
|
||||
name: string;
|
||||
}
|
||||
|
||||
const [user, setUser] = useState<User | null>(null);
|
||||
|
||||
// Array van objecten
|
||||
const [users, setUsers] = useState<User[]>([]);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Je Eigen Workflow Documenteren
|
||||
### Generics Basics
|
||||
|
||||
Maak een `docs/WORKFLOW.md` in je project:
|
||||
Generics maken code herbruikbaar:
|
||||
|
||||
```markdown
|
||||
# Mijn AI Workflow
|
||||
```typescript
|
||||
// Array is een generic type
|
||||
const numbers: Array<number> = [1, 2, 3];
|
||||
const names: Array<string> = ["Tim", "Anna"];
|
||||
|
||||
## Planning Fase
|
||||
- Tool: ChatGPT
|
||||
- Wat: Feature breakdown, technische beslissingen
|
||||
- Template prompt: "Ik wil [feature]. Wat zijn de stappen?"
|
||||
// Promise is een generic type
|
||||
async function fetchUser(): Promise<User> {
|
||||
const response = await fetch('/api/user');
|
||||
return response.json();
|
||||
}
|
||||
|
||||
## UI Design Fase
|
||||
- Tool: v0.dev
|
||||
- Wat: Component prototypes
|
||||
- Template prompt: "Modern [component] with [requirements]"
|
||||
// Je kunt ook eigen generics maken
|
||||
function firstElement<T>(arr: T[]): T | undefined {
|
||||
return arr[0];
|
||||
}
|
||||
|
||||
## Implementation Fase
|
||||
- Tool: OpenCode
|
||||
- Wat: Code schrijven en integreren
|
||||
- Template prompt: "Maak [component] in [locatie] met [requirements]"
|
||||
const first = firstElement([1, 2, 3]); // type: number | undefined
|
||||
```
|
||||
|
||||
## Debugging
|
||||
- Tool: OpenCode (eerst), Claude (als het complex is)
|
||||
- Wat: Errors oplossen
|
||||
- Template prompt: "Ik krijg deze error: [error]. Dit is mijn code: [code]"
|
||||
---
|
||||
|
||||
### Veelvoorkomende Errors
|
||||
|
||||
**Error 1: Type 'X' is not assignable to type 'Y'**
|
||||
```typescript
|
||||
let name: string = 42; // Error!
|
||||
// Fix: gebruik correct type
|
||||
let name: string = "Tim";
|
||||
```
|
||||
|
||||
**Error 2: Property 'X' does not exist on type 'Y'**
|
||||
```typescript
|
||||
interface User { name: string; }
|
||||
const user: User = { name: "Tim" };
|
||||
console.log(user.age); // Error! 'age' bestaat niet
|
||||
// Fix: voeg property toe aan interface
|
||||
```
|
||||
|
||||
**Error 3: Object is possibly 'undefined'**
|
||||
```typescript
|
||||
const users: User[] = [];
|
||||
console.log(users[0].name); // Error! users[0] kan undefined zijn
|
||||
// Fix: check eerst
|
||||
if (users[0]) {
|
||||
console.log(users[0].name);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### JS naar TS Omzetten
|
||||
|
||||
**Stap 1:** Rename `.js` naar `.tsx` (voor React) of `.ts`
|
||||
|
||||
**Stap 2:** Fix de rode errors - meestal:
|
||||
- Voeg types toe aan function parameters
|
||||
- Maak interfaces voor objecten
|
||||
- Handle nullable values
|
||||
|
||||
**Voorbeeld:**
|
||||
|
||||
```javascript
|
||||
// Voorheen (JavaScript)
|
||||
function UserCard({ user }) {
|
||||
return <div>{user.name}</div>;
|
||||
}
|
||||
```
|
||||
|
||||
```typescript
|
||||
// Nu (TypeScript)
|
||||
interface User {
|
||||
id: number;
|
||||
name: string;
|
||||
}
|
||||
|
||||
interface UserCardProps {
|
||||
user: User;
|
||||
}
|
||||
|
||||
function UserCard({ user }: UserCardProps) {
|
||||
return <div>{user.name}</div>;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Tools
|
||||
- ChatGPT
|
||||
- Claude
|
||||
- v0.dev
|
||||
- OpenCode/WebStorm
|
||||
- TypeScript (via Next.js)
|
||||
- React
|
||||
|
||||
---
|
||||
|
||||
## Lesopdracht (2 uur)
|
||||
|
||||
### Tool Comparison Challenge
|
||||
### TypeScript Hands-on
|
||||
|
||||
**Deel 1: Dezelfde Taak, Drie Tools (1 uur)**
|
||||
**Deel 1: JS naar TS Omzetten (45 min)**
|
||||
|
||||
Bouw een "Contact Form" component met alle drie de tools:
|
||||
Gegeven JavaScript component:
|
||||
|
||||
1. **ChatGPT (20 min)**
|
||||
- Vraag om code + uitleg
|
||||
- Noteer: hoe lang duurde het, kwaliteit output, wat miste?
|
||||
```javascript
|
||||
function ProductCard({ product, onAddToCart }) {
|
||||
return (
|
||||
<div className="p-4 border rounded">
|
||||
<h2>{product.name}</h2>
|
||||
<p>${product.price}</p>
|
||||
{product.description && <p>{product.description}</p>}
|
||||
<button onClick={() => onAddToCart(product.id)}>
|
||||
Add to Cart
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
2. **v0.dev (20 min)**
|
||||
- Genereer visueel prototype
|
||||
- Noteer: hoe snel, hoe mooi, hoe aanpasbaar?
|
||||
Zet dit om naar TypeScript:
|
||||
1. Maak `Product` interface
|
||||
2. Maak `ProductCardProps` interface
|
||||
3. Type de component
|
||||
4. Fix alle TypeScript errors
|
||||
|
||||
3. **OpenCode (20 min)**
|
||||
- Integreer in bestaand project
|
||||
- Noteer: hoe goed past het, hoeveel aanpassing nodig?
|
||||
**Deel 2: Interfaces Schrijven (30 min)**
|
||||
|
||||
**Deel 2: Analyse (30 min)**
|
||||
Maak interfaces voor:
|
||||
|
||||
Vul dit schema in:
|
||||
1. **User** met: id, name, email, avatar (optioneel), createdAt
|
||||
2. **Product** met: id, name, price, description (optioneel), inStock, category
|
||||
3. **Order** met: id, userId, products (array), total, status (pending/shipped/delivered)
|
||||
|
||||
| Aspect | ChatGPT | v0.dev | OpenCode |
|
||||
|--------|---------|--------|----------|
|
||||
| Tijd tot werkend component | | | |
|
||||
| Kwaliteit code | | | |
|
||||
| Visueel design | | | |
|
||||
| Past in project | | | |
|
||||
| Hoeveel aanpassing nodig | | | |
|
||||
| Totaalscore (1-10) | | | |
|
||||
**Deel 3: React Component met Types (45 min)**
|
||||
|
||||
**Deel 3: Workflow Documentatie (30 min)**
|
||||
Bouw een `UserList` component:
|
||||
- Props: users array, onSelectUser callback
|
||||
- State: selectedUserId (number of null)
|
||||
- Toon lijst van users, highlight geselecteerde
|
||||
|
||||
- Maak `docs/WORKFLOW.md` in je project
|
||||
- Documenteer je ideale workflow per taaktype
|
||||
- Inclusief template prompts voor elke tool
|
||||
Alle types moeten correct zijn. Geen `any` gebruiken!
|
||||
|
||||
### Deliverable
|
||||
- Screenshot van alle 3 contact forms
|
||||
- Ingevuld vergelijkingsschema
|
||||
- `docs/WORKFLOW.md` bestand
|
||||
- ProductCard.tsx met correcte types
|
||||
- types.ts met alle interfaces
|
||||
- UserList.tsx volledig getypt
|
||||
|
||||
---
|
||||
|
||||
## Huiswerk (2 uur)
|
||||
|
||||
### Bouw Je Tool Selection Cheat Sheet
|
||||
### TypeScript Verdieping
|
||||
|
||||
**Deel 1: Cheat Sheet Maken (1 uur)**
|
||||
**Deel 1: Drie Components Bouwen (1 uur)**
|
||||
|
||||
Maak een persoonlijke "Tool Selection Cheat Sheet" (1 pagina):
|
||||
Bouw volledig in TypeScript:
|
||||
|
||||
```markdown
|
||||
# Mijn AI Tool Cheat Sheet
|
||||
1. **SearchInput** component
|
||||
- Props: value, onChange, placeholder (optioneel)
|
||||
- Volledig getypt
|
||||
|
||||
## Wanneer gebruik ik wat?
|
||||
2. **DataTable** component
|
||||
- Generic: werkt met elk type data
|
||||
- Props: data array, columns config
|
||||
- Type-safe rendering
|
||||
|
||||
### ChatGPT
|
||||
- ✅ Gebruik voor: [jouw ervaring]
|
||||
- ❌ Niet voor: [jouw ervaring]
|
||||
- 💡 Beste prompt tip: [jouw tip]
|
||||
3. **Modal** component
|
||||
- Props: isOpen, onClose, title, children
|
||||
- Correct gebruik van React.ReactNode
|
||||
|
||||
### Claude
|
||||
- ✅ Gebruik voor: [jouw ervaring]
|
||||
- ❌ Niet voor: [jouw ervaring]
|
||||
- 💡 Beste prompt tip: [jouw tip]
|
||||
**Deel 2: Eindproject Interfaces (30 min)**
|
||||
|
||||
### v0.dev
|
||||
- ✅ Gebruik voor: [jouw ervaring]
|
||||
- ❌ Niet voor: [jouw ervaring]
|
||||
- 💡 Beste prompt tip: [jouw tip]
|
||||
Bedenk de data structuur voor je eindproject:
|
||||
- Welke entiteiten heb je? (users, posts, products, etc.)
|
||||
- Maak interface voor elke entiteit
|
||||
- Documenteer relaties tussen entiteiten
|
||||
|
||||
### OpenCode
|
||||
- ✅ Gebruik voor: [jouw ervaring]
|
||||
- ❌ Niet voor: [jouw ervaring]
|
||||
- 💡 Beste prompt tip: [jouw tip]
|
||||
**Deel 3: Cheat Sheet (30 min)**
|
||||
|
||||
## Mijn Favoriete Combinaties
|
||||
1. [Workflow 1]
|
||||
2. [Workflow 2]
|
||||
```
|
||||
|
||||
**Deel 2: Testen op Nieuwe Taken (45 min)**
|
||||
|
||||
Test je cheat sheet op 2 nieuwe taken:
|
||||
1. Bouw een "Testimonial Card" component
|
||||
2. Voeg een "Dark Mode Toggle" toe
|
||||
|
||||
Per taak:
|
||||
- Kies tools op basis van je cheat sheet
|
||||
- Voer uit en noteer resultaat
|
||||
- Update cheat sheet indien nodig
|
||||
|
||||
**Deel 3: Reflectie (15 min)**
|
||||
|
||||
Schrijf korte reflectie (400 woorden):
|
||||
- Welke tool is jouw favoriet en waarom?
|
||||
- Wanneer combineer je tools?
|
||||
- Wat ga je anders doen na deze les?
|
||||
Maak persoonlijke TypeScript cheat sheet:
|
||||
- Meest gebruikte types
|
||||
- Interface vs Type wanneer
|
||||
- Common patterns met React
|
||||
- Hoe je errors oplost
|
||||
|
||||
### Deliverable
|
||||
- Tool Selection Cheat Sheet (1 pagina)
|
||||
- 2 gebouwde components (Testimonial Card, Dark Mode Toggle)
|
||||
- Reflectie (400 woorden)
|
||||
- 3 TypeScript components
|
||||
- types/index.ts met eindproject interfaces
|
||||
- TypeScript cheat sheet (1 pagina)
|
||||
|
||||
---
|
||||
|
||||
## Leerdoelen
|
||||
Na deze les kan de student:
|
||||
- De sterke en zwakke punten van elke AI tool benoemen
|
||||
- De juiste tool kiezen voor een specifieke taak
|
||||
- Meerdere tools combineren in een effectieve workflow
|
||||
- Een persoonlijke workflow documenteren
|
||||
- Template prompts schrijven per tool
|
||||
- Kritisch evalueren welke tool wanneer het beste werkt
|
||||
- Uitleggen waarom TypeScript waardevol is
|
||||
- Basic types gebruiken (string, number, boolean, arrays)
|
||||
- Interfaces en type aliases schrijven
|
||||
- React components typen met props
|
||||
- useState met types gebruiken
|
||||
- Generics op basisniveau begrijpen
|
||||
- JavaScript code omzetten naar TypeScript
|
||||
- TypeScript errors lezen en oplossen
|
||||
|
||||
@@ -1,288 +1,365 @@
|
||||
# Les 6: Hands-on: Van Idee naar Prototype
|
||||
# Les 6: Next.js Fundamentals 1 - SSR & Routing
|
||||
|
||||
---
|
||||
|
||||
## Hoofdstuk
|
||||
**Hoofdstuk 2: Intermediate** (Les 4-9)
|
||||
**Deel 2: Technical Foundations** (Les 5-9)
|
||||
|
||||
## Beschrijving
|
||||
Pas alles wat je hebt geleerd toe in een hands-on sessie. Ga van een vaag idee naar een werkend prototype met behulp van je AI workflow.
|
||||
Introductie tot Next.js voor React developers. Leer wat Server-Side Rendering is, hoe de App Router werkt, en bouw je eerste Next.js applicatie met meerdere pagina's.
|
||||
|
||||
---
|
||||
|
||||
## Te Behandelen
|
||||
|
||||
### Van Idee naar Feature Breakdown
|
||||
### Wat is Next.js?
|
||||
|
||||
**Het probleem:** Je hebt een idee, maar waar begin je?
|
||||
**React met superpowers:**
|
||||
- React = library voor UI components
|
||||
- Next.js = framework dat React complete maakt
|
||||
|
||||
**Stap 1: Beschrijf je idee in 1-2 zinnen**
|
||||
```
|
||||
"Ik wil een app waar je kunt bijhouden welke planten water nodig hebben."
|
||||
```
|
||||
|
||||
**Stap 2: Vraag AI om feature breakdown**
|
||||
```
|
||||
Prompt: Ik wil een plant watering tracker app bouwen.
|
||||
Wat zijn de minimale features voor een werkend prototype?
|
||||
Denk aan: wat moet een gebruiker kunnen doen?
|
||||
```
|
||||
|
||||
**Stap 3: Prioriteer (MVP denken)**
|
||||
- Wat is essentieel? → In prototype
|
||||
- Wat is nice-to-have? → Later
|
||||
**Next.js voegt toe:**
|
||||
- Routing (geen extra library nodig)
|
||||
- Server-Side Rendering (SEO, performance)
|
||||
- API routes (backend in je frontend project)
|
||||
- Optimalisaties (images, fonts, bundling)
|
||||
|
||||
---
|
||||
|
||||
### Component Thinking
|
||||
### Server-Side Rendering (SSR) vs Client-Side Rendering (CSR)
|
||||
|
||||
**Vraag jezelf af:**
|
||||
- Welke "blokken" zie ik op het scherm?
|
||||
- Welke blokken worden herhaald?
|
||||
- Welke blokken komen op meerdere pagina's?
|
||||
|
||||
**Voorbeeld: Plant Tracker**
|
||||
**Client-Side Rendering (gewone React):**
|
||||
```
|
||||
Herhaalde componenten:
|
||||
- PlantCard (naam, foto, laatste water datum)
|
||||
- WaterButton (markeer als water gegeven)
|
||||
1. Browser vraagt pagina
|
||||
2. Server stuurt lege HTML + JavaScript
|
||||
3. JavaScript laadt in browser
|
||||
4. JavaScript rendert de pagina
|
||||
5. Gebruiker ziet content
|
||||
```
|
||||
**Probleem:** Lege pagina tot JS klaar is. Google ziet ook lege pagina.
|
||||
|
||||
Pagina componenten:
|
||||
- PlantList (toont alle PlantCards)
|
||||
- AddPlantForm (nieuw plant toevoegen)
|
||||
**Server-Side Rendering (Next.js):**
|
||||
```
|
||||
1. Browser vraagt pagina
|
||||
2. Server rendert HTML met content
|
||||
3. Browser toont direct de content
|
||||
4. JavaScript laadt (hydration)
|
||||
5. Pagina wordt interactief
|
||||
```
|
||||
**Voordeel:** Direct content zichtbaar, beter voor SEO.
|
||||
|
||||
---
|
||||
|
||||
### De App Router
|
||||
|
||||
Next.js 13+ gebruikt de "App Router" met file-based routing:
|
||||
|
||||
```
|
||||
app/
|
||||
├── page.tsx → /
|
||||
├── about/
|
||||
│ └── page.tsx → /about
|
||||
├── products/
|
||||
│ ├── page.tsx → /products
|
||||
│ └── [id]/
|
||||
│ └── page.tsx → /products/123
|
||||
└── layout.tsx → Wrapper voor alle pagina's
|
||||
```
|
||||
|
||||
**De regel:** Elke `page.tsx` wordt een route!
|
||||
|
||||
---
|
||||
|
||||
### Project Aanmaken
|
||||
|
||||
```bash
|
||||
npx create-next-app@latest mijn-app
|
||||
|
||||
# Antwoorden:
|
||||
# ✔ TypeScript? → Yes
|
||||
# ✔ ESLint? → Yes
|
||||
# ✔ Tailwind CSS? → Yes
|
||||
# ✔ `src/` directory? → Yes
|
||||
# ✔ App Router? → Yes
|
||||
# ✔ Customize import alias? → No
|
||||
|
||||
cd mijn-app
|
||||
npm run dev
|
||||
```
|
||||
|
||||
Open `http://localhost:3000` - je app draait!
|
||||
|
||||
---
|
||||
|
||||
### Pagina's Maken
|
||||
|
||||
**Simpele pagina (`app/about/page.tsx`):**
|
||||
```tsx
|
||||
export default function AboutPage() {
|
||||
return (
|
||||
<div className="p-8">
|
||||
<h1 className="text-3xl font-bold">Over Ons</h1>
|
||||
<p>Welkom op de about pagina!</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
Dat is alles! Ga naar `/about` en je ziet je pagina.
|
||||
|
||||
---
|
||||
|
||||
### Layouts
|
||||
|
||||
Layouts wrappen pagina's en blijven behouden tijdens navigatie.
|
||||
|
||||
**Root Layout (`app/layout.tsx`):**
|
||||
```tsx
|
||||
export default function RootLayout({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode
|
||||
}) {
|
||||
return (
|
||||
<html lang="nl">
|
||||
<body>
|
||||
<header className="p-4 bg-blue-500 text-white">
|
||||
<nav>Mijn App</nav>
|
||||
</header>
|
||||
<main>{children}</main>
|
||||
<footer className="p-4 bg-gray-200">
|
||||
© 2024
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### MVP (Minimum Viable Product) Denken
|
||||
### Nested Layouts
|
||||
|
||||
**Wat is MVP?**
|
||||
De simpelste versie van je app die nog steeds waarde levert.
|
||||
|
||||
**❌ Niet MVP:**
|
||||
- Alle features tegelijk
|
||||
- Perfect design
|
||||
- Edge cases afhandelen
|
||||
- Login systeem
|
||||
|
||||
**✅ Wel MVP:**
|
||||
- Core functionaliteit werkt
|
||||
- Basis styling
|
||||
- Happy path werkt
|
||||
- Hardcoded data is oké
|
||||
|
||||
---
|
||||
|
||||
### De Prototype Workflow
|
||||
Je kunt layouts nesten voor secties:
|
||||
|
||||
```
|
||||
1. IDEE (1-2 zinnen)
|
||||
↓
|
||||
2. FEATURES (AI breakdown)
|
||||
↓
|
||||
3. PRIORITEER (wat is MVP?)
|
||||
↓
|
||||
4. COMPONENTS (welke blokken?)
|
||||
↓
|
||||
5. BOUWEN (tool per stap)
|
||||
↓
|
||||
6. ITEREREN (feedback → aanpassen)
|
||||
app/
|
||||
├── layout.tsx → Root layout
|
||||
├── page.tsx → Homepage
|
||||
└── dashboard/
|
||||
├── layout.tsx → Dashboard layout (sidebar)
|
||||
└── page.tsx → Dashboard pagina
|
||||
```
|
||||
|
||||
**Dashboard Layout (`app/dashboard/layout.tsx`):**
|
||||
```tsx
|
||||
export default function DashboardLayout({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode
|
||||
}) {
|
||||
return (
|
||||
<div className="flex">
|
||||
<aside className="w-64 bg-gray-100 p-4">
|
||||
<nav>Sidebar hier</nav>
|
||||
</aside>
|
||||
<div className="flex-1">{children}</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Voorbeeld: Weer Widget Prototype
|
||||
### Dynamic Routes
|
||||
|
||||
**Stap 1: Idee**
|
||||
"Simpele weer widget met 3-daagse forecast"
|
||||
Voor pagina's met parameters zoals `/products/123`:
|
||||
|
||||
**Stap 2: AI Feature Breakdown**
|
||||
**Folder structuur:**
|
||||
```
|
||||
Vraag aan ChatGPT:
|
||||
"Wat zijn de minimale features voor een weer widget met 3-daagse forecast?"
|
||||
|
||||
Antwoord:
|
||||
- Huidige temperatuur tonen
|
||||
- Weer icoon (zon, regen, etc.)
|
||||
- 3-daagse forecast (dag + temp + icoon)
|
||||
- Locatie tonen
|
||||
app/products/[id]/page.tsx
|
||||
```
|
||||
|
||||
**Stap 3: MVP Selectie**
|
||||
- ✅ Huidige temperatuur
|
||||
- ✅ Weer icoon
|
||||
- ✅ 3 dagen forecast
|
||||
- ❌ Locatie selectie (later)
|
||||
- ❌ Animated icons (later)
|
||||
**De pagina:**
|
||||
```tsx
|
||||
interface Props {
|
||||
params: { id: string }
|
||||
}
|
||||
|
||||
**Stap 4: Components**
|
||||
```
|
||||
WeatherWidget/
|
||||
├── CurrentWeather (temp + icoon)
|
||||
├── ForecastDay (dag + temp + icoon)
|
||||
└── ForecastList (3x ForecastDay)
|
||||
export default function ProductPage({ params }: Props) {
|
||||
return (
|
||||
<div>
|
||||
<h1>Product {params.id}</h1>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
**Stap 5: Bouwen**
|
||||
1. v0.dev: "Weather widget with current temp and 3 day forecast, minimal design"
|
||||
2. OpenCode: "Integreer dit in mijn project, maak components in src/components/weather/"
|
||||
|
||||
**Stap 6: Itereren**
|
||||
- Wat werkt niet?
|
||||
- Wat kan beter?
|
||||
- Vraag AI om verbeteringen
|
||||
Nu werkt `/products/1`, `/products/abc`, etc.
|
||||
|
||||
---
|
||||
|
||||
### Mini-Project Ideeën
|
||||
### Link Component
|
||||
|
||||
Kies een van deze voor je lesopdracht:
|
||||
Gebruik `Link` voor client-side navigatie (snel, geen page reload):
|
||||
|
||||
| Project | Core Feature | Complexiteit |
|
||||
|---------|-------------|--------------|
|
||||
| **Weer Widget** | 3-daagse forecast | ⭐ |
|
||||
| **Quiz App** | 3 vragen + score | ⭐ |
|
||||
| **Recipe Card** | Ingrediënten toggle | ⭐ |
|
||||
| **Pomodoro Timer** | Start/stop + countdown | ⭐⭐ |
|
||||
| **Expense Tracker** | Lijst + totaal | ⭐⭐ |
|
||||
```tsx
|
||||
import Link from 'next/link'
|
||||
|
||||
export default function Navigation() {
|
||||
return (
|
||||
<nav className="flex gap-4">
|
||||
<Link href="/">Home</Link>
|
||||
<Link href="/about">About</Link>
|
||||
<Link href="/products">Products</Link>
|
||||
<Link href="/products/123">Product 123</Link>
|
||||
</nav>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
**Niet doen:**
|
||||
```tsx
|
||||
// ❌ Dit werkt maar is langzamer
|
||||
<a href="/about">About</a>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Documenteer Je Proces
|
||||
### Special Files
|
||||
|
||||
Maak aantekeningen tijdens het bouwen:
|
||||
Next.js heeft speciale bestanden:
|
||||
|
||||
```markdown
|
||||
# Mijn Prototype: [naam]
|
||||
| File | Doel |
|
||||
|------|------|
|
||||
| `page.tsx` | De pagina content |
|
||||
| `layout.tsx` | Wrapper, blijft behouden |
|
||||
| `loading.tsx` | Loading state |
|
||||
| `error.tsx` | Error boundary |
|
||||
| `not-found.tsx` | 404 pagina |
|
||||
|
||||
## Idee
|
||||
[1-2 zinnen]
|
||||
|
||||
## Feature Breakdown
|
||||
1. [feature 1]
|
||||
2. [feature 2]
|
||||
3. [feature 3]
|
||||
|
||||
## MVP Selectie
|
||||
- ✅ [wat wel]
|
||||
- ❌ [wat niet (nog)]
|
||||
|
||||
## Components
|
||||
- [Component 1]
|
||||
- [Component 2]
|
||||
|
||||
## Prompts die Werkten
|
||||
**Loading state (`app/products/loading.tsx`):**
|
||||
```tsx
|
||||
export default function Loading() {
|
||||
return <div>Laden...</div>
|
||||
}
|
||||
```
|
||||
[prompt]
|
||||
```
|
||||
→ [wat leverde het op]
|
||||
|
||||
## Wat Ging Fout
|
||||
- [probleem 1] → [hoe opgelost]
|
||||
---
|
||||
|
||||
## Lessons Learned
|
||||
- [les 1]
|
||||
- [les 2]
|
||||
### Metadata (SEO)
|
||||
|
||||
Voeg metadata toe per pagina:
|
||||
|
||||
```tsx
|
||||
import type { Metadata } from 'next'
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'Over Ons | Mijn App',
|
||||
description: 'Lees meer over ons bedrijf',
|
||||
}
|
||||
|
||||
export default function AboutPage() {
|
||||
return <h1>Over Ons</h1>
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Tools
|
||||
- ChatGPT (voor planning)
|
||||
- v0.dev (voor prototypes)
|
||||
- OpenCode/WebStorm (voor implementation)
|
||||
- Next.js 14
|
||||
- TypeScript
|
||||
- Tailwind CSS
|
||||
- OpenCode/WebStorm
|
||||
- Vercel
|
||||
|
||||
---
|
||||
|
||||
## Lesopdracht (2 uur)
|
||||
|
||||
### Bouw Je Mini-Prototype
|
||||
### Bouw Multi-Page Next.js App
|
||||
|
||||
**Deel 1: Planning (30 min)**
|
||||
**Deel 1: Project Setup (20 min)**
|
||||
|
||||
1. Kies een project uit de lijst (of bedenk eigen simpel idee)
|
||||
2. Schrijf je idee in 1-2 zinnen
|
||||
3. Vraag ChatGPT om feature breakdown
|
||||
4. Selecteer MVP features (max 3)
|
||||
5. Schets de components op papier
|
||||
1. `npx create-next-app@latest my-shop` (TypeScript + Tailwind + App Router)
|
||||
2. Open in editor
|
||||
3. `npm run dev`
|
||||
4. Verifieer: `localhost:3000` werkt
|
||||
|
||||
**Deel 2: Bouwen (1 uur)**
|
||||
**Deel 2: Pagina's Maken (40 min)**
|
||||
|
||||
1. Genereer UI in v0.dev
|
||||
2. Open project in OpenCode
|
||||
3. Integreer en pas aan
|
||||
4. Zorg dat het werkt (happy path)
|
||||
Maak deze pagina's:
|
||||
1. `/` - Homepage met welkomstbericht
|
||||
2. `/about` - Over ons pagina
|
||||
3. `/products` - Producten overzicht
|
||||
4. `/contact` - Contact pagina
|
||||
|
||||
**Focus op WORKFLOW, niet perfectie!**
|
||||
Elke pagina moet unieke content hebben.
|
||||
|
||||
**Deel 3: Documentatie (30 min)**
|
||||
**Deel 3: Layout met Navigatie (30 min)**
|
||||
|
||||
Maak `docs/PROTOTYPE-LOG.md`:
|
||||
- Je idee
|
||||
- Feature breakdown
|
||||
- MVP keuzes
|
||||
- Prompts die werkten
|
||||
- Wat ging fout en hoe opgelost
|
||||
- Lessons learned
|
||||
1. Maak Header component met navigatie (gebruik Link)
|
||||
2. Maak Footer component
|
||||
3. Voeg beide toe aan root layout
|
||||
4. Test: navigatie werkt zonder page reload
|
||||
|
||||
**Deel 4: Dynamic Route (30 min)**
|
||||
|
||||
1. Maak `/products/[id]` route
|
||||
2. Toon product ID op de pagina
|
||||
3. Maak links naar `/products/1`, `/products/2`, `/products/3`
|
||||
4. Test: alle links werken
|
||||
|
||||
**Bonus:** Voeg `loading.tsx` toe aan products folder
|
||||
|
||||
### Deliverable
|
||||
- Werkend prototype (kan simpel zijn)
|
||||
- `docs/PROTOTYPE-LOG.md` met je proces
|
||||
- Screenshot van werkend prototype
|
||||
- Werkende Next.js app met 4+ pagina's
|
||||
- Navigatie met Link component
|
||||
- Dynamic route die werkt
|
||||
- Deploy naar Vercel
|
||||
|
||||
---
|
||||
|
||||
## Huiswerk (2 uur)
|
||||
|
||||
### Verbeter en Reflecteer
|
||||
### Uitbreiden en Verdiepen
|
||||
|
||||
**Deel 1: Prototype Verbeteren (1 uur)**
|
||||
**Deel 1: Nested Layout (45 min)**
|
||||
|
||||
1. Fix eventuele bugs
|
||||
2. Voeg 1 extra feature toe
|
||||
3. Verbeter styling
|
||||
4. Handle 1 edge case
|
||||
1. Maak `/dashboard` section met eigen layout
|
||||
2. Dashboard layout heeft sidebar
|
||||
3. Maak `/dashboard/settings` en `/dashboard/profile` pagina's
|
||||
4. Test: sidebar blijft bij navigatie binnen dashboard
|
||||
|
||||
**Deel 2: Peer Review (30 min)**
|
||||
**Deel 2: Special Files (45 min)**
|
||||
|
||||
- Deel je prototype met een klasgenoot
|
||||
- Krijg feedback
|
||||
- Geef feedback op hun prototype
|
||||
1. Maak `loading.tsx` voor products (toon "Laden...")
|
||||
2. Maak `error.tsx` voor products (toon error message)
|
||||
3. Maak `not-found.tsx` in app root (custom 404)
|
||||
4. Test elk van deze states
|
||||
|
||||
**Deel 3: Reflectie (30 min)**
|
||||
**Deel 3: Metadata (30 min)**
|
||||
|
||||
Schrijf "Lessons Learned" document (300 woorden):
|
||||
- Wat ging goed in je workflow?
|
||||
- Waar liep je vast?
|
||||
- Welke tool was het meest nuttig?
|
||||
- Wat doe je volgende keer anders?
|
||||
- Hoe voelde het om met AI te bouwen vs alleen?
|
||||
1. Voeg metadata toe aan elke pagina (title, description)
|
||||
2. Bekijk in browser: `<head>` toont juiste meta tags
|
||||
3. Test met Lighthouse: SEO score
|
||||
|
||||
### Deliverable
|
||||
- Verbeterd prototype
|
||||
- Peer review feedback (gegeven en ontvangen)
|
||||
- Lessons Learned document (300 woorden)
|
||||
|
||||
---
|
||||
|
||||
## Voorbereiding Les 7
|
||||
|
||||
In Les 7 gaan we echt bouwen met Next.js. Zorg dat je klaar bent:
|
||||
- Node.js geïnstalleerd (versie 18+)
|
||||
- Git geconfigureerd
|
||||
- GitHub account aangemaakt
|
||||
- OpenCode/WebStorm werkt
|
||||
|
||||
Test: run `node --version` in je terminal. Je zou v18 of hoger moeten zien.
|
||||
- App met nested layouts
|
||||
- Special files (loading, error, not-found)
|
||||
- Metadata op elke pagina
|
||||
- Screenshot van Lighthouse SEO score
|
||||
|
||||
---
|
||||
|
||||
## Leerdoelen
|
||||
Na deze les kan de student:
|
||||
- Van een vaag idee naar concrete features gaan
|
||||
- AI gebruiken voor feature breakdown
|
||||
- MVP denken toepassen (essentieel vs nice-to-have)
|
||||
- Een app opdelen in components
|
||||
- De complete workflow doorlopen (idee → prototype)
|
||||
- Het bouwproces documenteren
|
||||
- Reflecteren op wat werkt en wat niet
|
||||
- Uitleggen wat Next.js toevoegt aan React
|
||||
- Het verschil tussen SSR en CSR beschrijven
|
||||
- Een Next.js project opzetten met App Router
|
||||
- Pagina's maken met file-based routing
|
||||
- Layouts gebruiken voor herhalende elementen
|
||||
- Dynamic routes maken met parameters
|
||||
- Link component gebruiken voor navigatie
|
||||
- Special files toepassen (loading, error, not-found)
|
||||
- Metadata toevoegen voor SEO
|
||||
|
||||
@@ -1,349 +1,412 @@
|
||||
# Les 7: Backend Basics met Supabase
|
||||
|
||||
> 📋 **Lesmateriaal nog niet uitgewerkt**
|
||||
>
|
||||
> De volgende bestanden worden gegenereerd wanneer deze les wordt uitgewerkt:
|
||||
> - Les07-Slide-Overzicht.md
|
||||
> - Les07-Lesplan.md
|
||||
> - Les07-Bijlage-A-Lesopdracht.md
|
||||
> - Les07-Bijlage-B-Huiswerkopdracht.md
|
||||
# Les 7: Next.js Fundamentals 2 - API Routes & Data Fetching
|
||||
|
||||
---
|
||||
|
||||
## Hoofdstuk
|
||||
**Hoofdstuk 2: Intermediate** (Les 4-9)
|
||||
**Deel 2: Technical Foundations** (Les 5-9)
|
||||
|
||||
## Beschrijving
|
||||
Zet je eerste "echte" Next.js project op en koppel het aan Supabase voor database en authenticatie. Je leert de complete flow van lokaal ontwikkelen tot productie deployment.
|
||||
Leer data fetching in Next.js: Server Components, Client Components, API routes en React Query. Bouw een volledig werkende app met data.
|
||||
|
||||
---
|
||||
|
||||
## Te Behandelen
|
||||
|
||||
### Stap 1: Next.js Project Aanmaken
|
||||
### Server Components vs Client Components
|
||||
|
||||
Dit is de eerste keer dat je een volledig Next.js project opzet.
|
||||
**Server Components (default in Next.js):**
|
||||
- Renderen op de server
|
||||
- Geen JavaScript naar de browser
|
||||
- Kunnen direct data fetchen (async/await)
|
||||
- Kunnen NIET: useState, useEffect, event handlers
|
||||
|
||||
```bash
|
||||
# Maak nieuw project
|
||||
npx create-next-app@latest todo-app
|
||||
**Client Components:**
|
||||
- Renderen in de browser
|
||||
- JavaScript naar de browser
|
||||
- Kunnen interactief zijn
|
||||
- Markeer met `'use client'` bovenaan
|
||||
|
||||
# Beantwoord de vragen:
|
||||
# ✔ Would you like to use TypeScript? → Yes
|
||||
# ✔ Would you like to use ESLint? → Yes
|
||||
# ✔ Would you like to use Tailwind CSS? → Yes
|
||||
# ✔ Would you like to use `src/` directory? → Yes
|
||||
# ✔ Would you like to use App Router? → Yes
|
||||
# ✔ Would you like to customize the default import alias? → No
|
||||
---
|
||||
|
||||
# Ga naar project folder
|
||||
cd todo-app
|
||||
|
||||
# Open in je editor
|
||||
code . # of: cursor .
|
||||
```
|
||||
|
||||
### Stap 2: Project Structuur Begrijpen
|
||||
### Wanneer Wat?
|
||||
|
||||
```
|
||||
todo-app/
|
||||
├── src/
|
||||
│ └── app/
|
||||
│ ├── layout.tsx # Root layout (header, footer)
|
||||
│ ├── page.tsx # Homepage (/)
|
||||
│ └── globals.css # Global styles + Tailwind
|
||||
├── public/ # Static files (images, etc.)
|
||||
├── .env.local # Environment variables (maak zelf aan)
|
||||
├── next.config.js # Next.js configuratie
|
||||
├── tailwind.config.ts # Tailwind configuratie
|
||||
├── package.json # Dependencies
|
||||
└── tsconfig.json # TypeScript configuratie
|
||||
Server Component → Data tonen, geen interactie
|
||||
Client Component → Interactie nodig (forms, buttons, state)
|
||||
```
|
||||
|
||||
### Stap 3: Lokaal Draaien
|
||||
|
||||
```bash
|
||||
# Start development server
|
||||
npm run dev
|
||||
|
||||
# Open browser: http://localhost:3000
|
||||
```
|
||||
|
||||
### Stap 4: Supabase Project Aanmaken
|
||||
|
||||
**Op supabase.com:**
|
||||
|
||||
1. Ga naar [supabase.com](https://supabase.com) en maak account (gratis)
|
||||
2. Klik "New Project"
|
||||
3. Kies een naam (bijv. `todo-app`)
|
||||
4. Kies een database wachtwoord (bewaar deze!)
|
||||
5. Kies region: `West EU (Frankfurt)` (dichtst bij NL)
|
||||
6. Wacht ~2 minuten tot project klaar is
|
||||
|
||||
**Credentials ophalen:**
|
||||
|
||||
1. Ga naar Settings → API
|
||||
2. Kopieer:
|
||||
- `Project URL` → dit wordt `NEXT_PUBLIC_SUPABASE_URL`
|
||||
- `anon public` key → dit wordt `NEXT_PUBLIC_SUPABASE_ANON_KEY`
|
||||
|
||||
### Stap 5: Environment Variables (Lokaal)
|
||||
|
||||
Maak `.env.local` in je project root:
|
||||
|
||||
```bash
|
||||
# .env.local (NOOIT committen naar Git!)
|
||||
NEXT_PUBLIC_SUPABASE_URL=https://xxxxx.supabase.co
|
||||
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.xxxxx
|
||||
```
|
||||
|
||||
Maak ook `.env.example` (deze WEL committen):
|
||||
|
||||
```bash
|
||||
# .env.example (template voor anderen)
|
||||
NEXT_PUBLIC_SUPABASE_URL=your-supabase-url
|
||||
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
|
||||
```
|
||||
|
||||
**Check .gitignore:**
|
||||
```
|
||||
# .gitignore moet bevatten:
|
||||
.env*.local
|
||||
```
|
||||
|
||||
### Stap 6: Supabase SDK Installeren
|
||||
|
||||
```bash
|
||||
npm install @supabase/supabase-js
|
||||
```
|
||||
|
||||
### Stap 7: Supabase Client Maken
|
||||
|
||||
Maak `src/lib/supabase.ts`:
|
||||
|
||||
```typescript
|
||||
import { createClient } from '@supabase/supabase-js'
|
||||
|
||||
const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL!
|
||||
const supabaseAnonKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
|
||||
|
||||
export const supabase = createClient(supabaseUrl, supabaseAnonKey)
|
||||
```
|
||||
|
||||
### Stap 8: Database Tabel Maken (via UI)
|
||||
|
||||
**In Supabase Dashboard:**
|
||||
|
||||
1. Ga naar Table Editor
|
||||
2. Klik "New Table"
|
||||
3. Naam: `todos`
|
||||
4. Kolommen:
|
||||
| Name | Type | Default | Primary |
|
||||
|------|------|---------|---------|
|
||||
| id | int8 | - | ✓ (auto) |
|
||||
| title | text | - | |
|
||||
| completed | bool | false | |
|
||||
| created_at | timestamptz | now() | |
|
||||
| user_id | uuid | auth.uid() | |
|
||||
|
||||
5. Klik "Save"
|
||||
|
||||
### Stap 9: CRUD Operaties
|
||||
|
||||
```typescript
|
||||
// CREATE - nieuwe todo toevoegen
|
||||
const { data, error } = await supabase
|
||||
.from('todos')
|
||||
.insert({ title: 'Nieuwe taak' })
|
||||
|
||||
// READ - todos ophalen
|
||||
const { data, error } = await supabase
|
||||
.from('todos')
|
||||
.select('*')
|
||||
.order('created_at', { ascending: false })
|
||||
|
||||
// UPDATE - todo afvinken
|
||||
const { data, error } = await supabase
|
||||
.from('todos')
|
||||
.update({ completed: true })
|
||||
.eq('id', todoId)
|
||||
|
||||
// DELETE - todo verwijderen
|
||||
const { error } = await supabase
|
||||
.from('todos')
|
||||
.delete()
|
||||
.eq('id', todoId)
|
||||
```
|
||||
|
||||
### Stap 10: Authenticatie Setup
|
||||
|
||||
```bash
|
||||
npm install @supabase/auth-ui-react @supabase/auth-ui-shared
|
||||
```
|
||||
|
||||
**Login component:**
|
||||
**Voorbeeld:**
|
||||
```tsx
|
||||
import { Auth } from '@supabase/auth-ui-react'
|
||||
import { ThemeSupa } from '@supabase/auth-ui-shared'
|
||||
import { supabase } from '@/lib/supabase'
|
||||
// Server Component - data ophalen
|
||||
async function ProductList() {
|
||||
const products = await fetchProducts() // Direct fetchen!
|
||||
return <ul>{products.map(p => <li>{p.name}</li>)}</ul>
|
||||
}
|
||||
|
||||
// Client Component - interactie
|
||||
'use client'
|
||||
function AddToCartButton({ productId }) {
|
||||
const [added, setAdded] = useState(false)
|
||||
return <button onClick={() => setAdded(true)}>Add</button>
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Data Fetching in Server Components
|
||||
|
||||
Simpelweg `async/await` gebruiken:
|
||||
|
||||
```tsx
|
||||
// app/products/page.tsx
|
||||
interface Product {
|
||||
id: number
|
||||
name: string
|
||||
price: number
|
||||
}
|
||||
|
||||
async function getProducts(): Promise<Product[]> {
|
||||
const res = await fetch('https://api.example.com/products')
|
||||
return res.json()
|
||||
}
|
||||
|
||||
export default async function ProductsPage() {
|
||||
const products = await getProducts()
|
||||
|
||||
export function LoginForm() {
|
||||
return (
|
||||
<Auth
|
||||
supabaseClient={supabase}
|
||||
appearance={{ theme: ThemeSupa }}
|
||||
providers={[]}
|
||||
magicLink={true}
|
||||
/>
|
||||
<div>
|
||||
<h1>Producten</h1>
|
||||
<ul>
|
||||
{products.map(product => (
|
||||
<li key={product.id}>
|
||||
{product.name} - €{product.price}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
**Session checken:**
|
||||
```typescript
|
||||
const { data: { user } } = await supabase.auth.getUser()
|
||||
---
|
||||
|
||||
if (user) {
|
||||
// User is ingelogd
|
||||
} else {
|
||||
// Redirect naar login
|
||||
### API Routes (Route Handlers)
|
||||
|
||||
Bouw je eigen API in Next.js:
|
||||
|
||||
**Folder structuur:**
|
||||
```
|
||||
app/
|
||||
└── api/
|
||||
└── products/
|
||||
└── route.ts → /api/products
|
||||
```
|
||||
|
||||
**GET request (`app/api/products/route.ts`):**
|
||||
```typescript
|
||||
import { NextResponse } from 'next/server'
|
||||
|
||||
const products = [
|
||||
{ id: 1, name: 'Laptop', price: 999 },
|
||||
{ id: 2, name: 'Phone', price: 699 },
|
||||
]
|
||||
|
||||
export async function GET() {
|
||||
return NextResponse.json(products)
|
||||
}
|
||||
```
|
||||
|
||||
**POST request:**
|
||||
```typescript
|
||||
export async function POST(request: Request) {
|
||||
const body = await request.json()
|
||||
|
||||
const newProduct = {
|
||||
id: Date.now(),
|
||||
name: body.name,
|
||||
price: body.price,
|
||||
}
|
||||
|
||||
products.push(newProduct)
|
||||
|
||||
return NextResponse.json(newProduct, { status: 201 })
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Deployment naar Vercel (Productie)
|
||||
### 'use client' Directive
|
||||
|
||||
### Stap 1: GitHub Repository
|
||||
Wanneer je interactie nodig hebt:
|
||||
|
||||
```bash
|
||||
# In je project folder
|
||||
git init
|
||||
git add .
|
||||
git commit -m "Initial commit"
|
||||
```tsx
|
||||
'use client' // MOET bovenaan!
|
||||
|
||||
# Maak repo op GitHub, dan:
|
||||
git remote add origin https://github.com/jouw-username/todo-app.git
|
||||
git push -u origin main
|
||||
import { useState } from 'react'
|
||||
|
||||
export function Counter() {
|
||||
const [count, setCount] = useState(0)
|
||||
|
||||
return (
|
||||
<button onClick={() => setCount(count + 1)}>
|
||||
Count: {count}
|
||||
</button>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### Stap 2: Vercel Deployment
|
||||
|
||||
1. Ga naar [vercel.com](https://vercel.com)
|
||||
2. "Add New Project"
|
||||
3. Import je GitHub repository
|
||||
4. **BELANGRIJK:** Voeg Environment Variables toe:
|
||||
- `NEXT_PUBLIC_SUPABASE_URL` → je Supabase URL
|
||||
- `NEXT_PUBLIC_SUPABASE_ANON_KEY` → je anon key
|
||||
5. Klik "Deploy"
|
||||
|
||||
### Stap 3: Supabase URL Toestaan
|
||||
|
||||
In Supabase Dashboard:
|
||||
1. Ga naar Authentication → URL Configuration
|
||||
2. Voeg je Vercel URL toe aan "Redirect URLs":
|
||||
- `https://jouw-app.vercel.app/**`
|
||||
|
||||
---
|
||||
|
||||
## Overzicht: Lokaal vs Productie
|
||||
### React Query (TanStack Query)
|
||||
|
||||
| Aspect | Lokaal | Productie |
|
||||
|--------|--------|-----------|
|
||||
| URL | `localhost:3000` | `jouw-app.vercel.app` |
|
||||
| Env vars | `.env.local` | Vercel Dashboard |
|
||||
| Database | Supabase (zelfde) | Supabase (zelfde) |
|
||||
| Command | `npm run dev` | Automatisch via Vercel |
|
||||
**Waarom React Query?**
|
||||
- Automatische caching
|
||||
- Loading en error states
|
||||
- Refetching (focus, interval)
|
||||
- Optimistic updates
|
||||
|
||||
**Let op:** Je gebruikt dezelfde Supabase database voor lokaal en productie. Voor een echt project zou je aparte databases hebben, maar voor deze cursus is dat niet nodig.
|
||||
**Installatie:**
|
||||
```bash
|
||||
npm install @tanstack/react-query
|
||||
```
|
||||
|
||||
**Setup Provider (`app/providers.tsx`):**
|
||||
```tsx
|
||||
'use client'
|
||||
|
||||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
|
||||
import { useState } from 'react'
|
||||
|
||||
export function Providers({ children }: { children: React.ReactNode }) {
|
||||
const [queryClient] = useState(() => new QueryClient())
|
||||
|
||||
return (
|
||||
<QueryClientProvider client={queryClient}>
|
||||
{children}
|
||||
</QueryClientProvider>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
**In Layout:**
|
||||
```tsx
|
||||
import { Providers } from './providers'
|
||||
|
||||
export default function RootLayout({ children }) {
|
||||
return (
|
||||
<html>
|
||||
<body>
|
||||
<Providers>{children}</Providers>
|
||||
</body>
|
||||
</html>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### useQuery - Data Ophalen
|
||||
|
||||
```tsx
|
||||
'use client'
|
||||
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
|
||||
interface Product {
|
||||
id: number
|
||||
name: string
|
||||
price: number
|
||||
}
|
||||
|
||||
async function fetchProducts(): Promise<Product[]> {
|
||||
const res = await fetch('/api/products')
|
||||
return res.json()
|
||||
}
|
||||
|
||||
export function ProductList() {
|
||||
const { data, isLoading, error } = useQuery({
|
||||
queryKey: ['products'],
|
||||
queryFn: fetchProducts,
|
||||
})
|
||||
|
||||
if (isLoading) return <div>Laden...</div>
|
||||
if (error) return <div>Error: {error.message}</div>
|
||||
|
||||
return (
|
||||
<ul>
|
||||
{data?.map(product => (
|
||||
<li key={product.id}>{product.name}</li>
|
||||
))}
|
||||
</ul>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### useMutation - Data Wijzigen
|
||||
|
||||
```tsx
|
||||
'use client'
|
||||
|
||||
import { useMutation, useQueryClient } from '@tanstack/react-query'
|
||||
|
||||
interface NewProduct {
|
||||
name: string
|
||||
price: number
|
||||
}
|
||||
|
||||
async function createProduct(product: NewProduct) {
|
||||
const res = await fetch('/api/products', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(product),
|
||||
})
|
||||
return res.json()
|
||||
}
|
||||
|
||||
export function AddProductForm() {
|
||||
const queryClient = useQueryClient()
|
||||
|
||||
const mutation = useMutation({
|
||||
mutationFn: createProduct,
|
||||
onSuccess: () => {
|
||||
// Invalidate and refetch
|
||||
queryClient.invalidateQueries({ queryKey: ['products'] })
|
||||
},
|
||||
})
|
||||
|
||||
const handleSubmit = (e: React.FormEvent) => {
|
||||
e.preventDefault()
|
||||
mutation.mutate({ name: 'New Product', price: 99 })
|
||||
}
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmit}>
|
||||
<button type="submit" disabled={mutation.isPending}>
|
||||
{mutation.isPending ? 'Toevoegen...' : 'Voeg toe'}
|
||||
</button>
|
||||
</form>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Combineren: Server + Client
|
||||
|
||||
```tsx
|
||||
// app/products/page.tsx (Server Component)
|
||||
import { ProductList } from './product-list'
|
||||
import { AddProductForm } from './add-product-form'
|
||||
|
||||
export default function ProductsPage() {
|
||||
return (
|
||||
<div>
|
||||
<h1>Producten</h1>
|
||||
<AddProductForm /> {/* Client Component */}
|
||||
<ProductList /> {/* Client Component */}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Tools
|
||||
- Next.js
|
||||
- Supabase (gratis tier)
|
||||
- Vercel (gratis tier)
|
||||
- Cursor/OpenCode
|
||||
- Next.js 14
|
||||
- React Query (TanStack Query)
|
||||
- TypeScript
|
||||
- OpenCode/WebStorm
|
||||
|
||||
---
|
||||
|
||||
## Lesopdracht (2 uur)
|
||||
|
||||
### Bouw een Todo App met Supabase
|
||||
### Bouw CRUD App met API Routes
|
||||
|
||||
**Deel 1: Project Setup (30 min)**
|
||||
- Run `npx create-next-app@latest todo-app` met juiste opties
|
||||
- Maak Supabase account en project aan
|
||||
- Configureer `.env.local` met credentials
|
||||
- Installeer `@supabase/supabase-js`
|
||||
- Maak `src/lib/supabase.ts`
|
||||
- Test: `npm run dev` werkt zonder errors
|
||||
**Deel 1: API Routes (40 min)**
|
||||
|
||||
**Deel 2: Database (20 min)**
|
||||
- Maak `todos` tabel via Supabase Table Editor
|
||||
- Voeg 3 test todos toe via de UI
|
||||
- Test: data is zichtbaar in Table Editor
|
||||
1. Maak `app/api/products/route.ts`
|
||||
2. Implementeer GET (alle producten)
|
||||
3. Implementeer POST (product toevoegen)
|
||||
4. Test met browser/Postman: `/api/products`
|
||||
|
||||
**Deel 3: CRUD Interface (50 min)**
|
||||
- Bouw UI om todos te tonen (lijst)
|
||||
- Voeg form toe om nieuwe todo te maken
|
||||
- Voeg checkbox toe om todo af te vinken
|
||||
- Voeg delete button toe
|
||||
- Test: alle CRUD operaties werken
|
||||
**Deel 2: React Query Setup (20 min)**
|
||||
|
||||
**Deel 4: Authenticatie (20 min)**
|
||||
- Installeer auth packages
|
||||
- Maak login pagina met Auth UI
|
||||
- Toon alleen todos voor ingelogde user
|
||||
- Test: login met magic link werkt
|
||||
1. Installeer `@tanstack/react-query`
|
||||
2. Maak `app/providers.tsx`
|
||||
3. Wrap app in `QueryClientProvider`
|
||||
|
||||
**Deel 3: Data Tonen met useQuery (30 min)**
|
||||
|
||||
1. Maak `ProductList` Client Component
|
||||
2. Gebruik `useQuery` om data te fetchen
|
||||
3. Toon loading state
|
||||
4. Toon error state
|
||||
5. Render product lijst
|
||||
|
||||
**Deel 4: Data Toevoegen met useMutation (30 min)**
|
||||
|
||||
1. Maak `AddProductForm` Client Component
|
||||
2. Gebruik `useMutation` voor POST
|
||||
3. Invalidate query na success
|
||||
4. Toon "Adding..." state
|
||||
|
||||
### Deliverable
|
||||
- Werkende Todo app lokaal
|
||||
- GitHub repository met code
|
||||
- Screenshot van werkende app
|
||||
- Werkende API routes (GET, POST)
|
||||
- ProductList met useQuery
|
||||
- AddProductForm met useMutation
|
||||
- Loading en error states
|
||||
|
||||
---
|
||||
|
||||
## Huiswerk (2 uur)
|
||||
|
||||
### Deploy naar Productie + Uitbreiden
|
||||
### Volledige CRUD Interface
|
||||
|
||||
**Deel 1: Deployment (30 min)**
|
||||
- Push code naar GitHub
|
||||
- Deploy naar Vercel
|
||||
- Configureer environment variables in Vercel
|
||||
- Voeg Vercel URL toe aan Supabase Redirect URLs
|
||||
- Test: app werkt op productie URL
|
||||
**Deel 1: PUT en DELETE Routes (45 min)**
|
||||
|
||||
**Deel 2: Features Uitbreiden (1 uur)**
|
||||
- Filter buttons: Alle / Actief / Voltooid
|
||||
- Sorteer op datum (nieuwste eerst)
|
||||
- Toon alleen todos van ingelogde user (filter op `user_id`)
|
||||
- Loading state tijdens data ophalen
|
||||
- Error state bij problemen
|
||||
- Empty state: "Geen todos gevonden"
|
||||
1. Maak `app/api/products/[id]/route.ts`
|
||||
2. Implementeer PUT (update product)
|
||||
3. Implementeer DELETE (verwijder product)
|
||||
4. Test beide endpoints
|
||||
|
||||
**Deel 3: Polish (30 min)**
|
||||
- Styling verbeteren met Tailwind
|
||||
- Responsive design (mobile friendly)
|
||||
- Kleine animaties (fade in/out)
|
||||
**Deel 2: Update Functionaliteit (45 min)**
|
||||
|
||||
1. Maak edit form in ProductList
|
||||
2. Gebruik useMutation voor PUT
|
||||
3. Inline editing OF modal
|
||||
4. Invalidate query na success
|
||||
|
||||
**Deel 3: Delete Functionaliteit (30 min)**
|
||||
|
||||
1. Voeg delete button toe per product
|
||||
2. Gebruik useMutation voor DELETE
|
||||
3. Voeg confirmation dialog toe
|
||||
4. Invalidate query na success
|
||||
|
||||
**Bonus:** Optimistic Updates
|
||||
- Product direct uit UI verwijderen
|
||||
- Rollback als server faalt
|
||||
|
||||
### Deliverable
|
||||
- Deployed app op Vercel (werkende URL)
|
||||
- Alle features werken in productie
|
||||
- Screenshot van productie app
|
||||
- Complete CRUD API (GET, POST, PUT, DELETE)
|
||||
- UI voor alle operaties
|
||||
- Error handling
|
||||
- Optimistic updates (bonus)
|
||||
|
||||
---
|
||||
|
||||
## Leerdoelen
|
||||
Na deze les kan de student:
|
||||
- Een Next.js project opzetten met `npx create-next-app`
|
||||
- De project structuur begrijpen en navigeren
|
||||
- Een Supabase project aanmaken en configureren
|
||||
- Environment variables correct beheren (lokaal en productie)
|
||||
- De Supabase client installeren en configureren
|
||||
- Tabellen maken via de Supabase UI
|
||||
- CRUD operaties uitvoeren met de Supabase SDK
|
||||
- Authenticatie implementeren met Auth UI
|
||||
- Deployen naar Vercel met environment variables
|
||||
- Het verschil tussen lokale en productie omgeving begrijpen
|
||||
- Uitleggen wanneer Server vs Client Components
|
||||
- De 'use client' directive correct gebruiken
|
||||
- Data fetchen in Server Components met async/await
|
||||
- API routes maken met Route Handlers
|
||||
- GET en POST requests implementeren
|
||||
- React Query installeren en configureren
|
||||
- useQuery gebruiken voor data fetching
|
||||
- useMutation gebruiken voor data mutations
|
||||
- Loading en error states afhandelen
|
||||
- Query invalidation toepassen
|
||||
|
||||
@@ -1,320 +1,372 @@
|
||||
# Les 8: Supabase Basics
|
||||
# Les 8: Database Principles
|
||||
|
||||
---
|
||||
|
||||
## Hoofdstuk
|
||||
**Hoofdstuk 2: Intermediate** (Les 4-9)
|
||||
**Deel 2: Technical Foundations** (Les 5-9)
|
||||
|
||||
## Beschrijving
|
||||
Leer werken met Supabase: een complete backend-as-a-service met database en authenticatie. Je bouwt je eerste full-stack app met data die persistent is.
|
||||
Leer de basisprincipes van relationele databases voordat we Supabase gaan gebruiken. Begrijp tabellen, relaties, keys en normalisatie - essentiële kennis voor elke developer.
|
||||
|
||||
---
|
||||
|
||||
## Te Behandelen
|
||||
|
||||
### Wat is Supabase?
|
||||
### Wat is een Relationele Database?
|
||||
|
||||
**Supabase = Database + Auth in één**
|
||||
- PostgreSQL database (gratis tier: 500MB)
|
||||
- Ingebouwde authenticatie
|
||||
- Real-time subscriptions
|
||||
- File storage
|
||||
- Auto-generated API
|
||||
**Een database is:** Een georganiseerde verzameling van data.
|
||||
|
||||
**Waarom Supabase voor beginners:**
|
||||
- Geen eigen server nodig
|
||||
- Visuele Table Editor (geen SQL kennis nodig)
|
||||
- Simpele JavaScript SDK
|
||||
- Gratis tier is ruim voldoende
|
||||
**Relationeel betekent:** Data is opgeslagen in tabellen die aan elkaar gerelateerd zijn.
|
||||
|
||||
**Vergelijk het met Excel:**
|
||||
- Database = Excel workbook
|
||||
- Tabel = Excel sheet
|
||||
- Kolom = Excel kolom (field)
|
||||
- Rij = Excel rij (record)
|
||||
|
||||
---
|
||||
|
||||
### Supabase Project Aanmaken
|
||||
### Tabellen, Kolommen en Rijen
|
||||
|
||||
**Stap 1:** Ga naar [supabase.com](https://supabase.com) en maak account
|
||||
**Voorbeeld: Users tabel**
|
||||
|
||||
**Stap 2:** Klik "New Project"
|
||||
- Naam: `todo-app`
|
||||
- Database Password: (bewaar deze!)
|
||||
- Region: `West EU (Frankfurt)` (dichtst bij NL)
|
||||
| id | name | email | created_at |
|
||||
|----|------|-------|------------|
|
||||
| 1 | Tim | tim@email.com | 2024-01-15 |
|
||||
| 2 | Anna | anna@email.com | 2024-01-16 |
|
||||
| 3 | Jan | jan@email.com | 2024-01-17 |
|
||||
|
||||
**Stap 3:** Wacht ~2 minuten tot project klaar is
|
||||
|
||||
**Stap 4:** Ga naar Settings → API en kopieer:
|
||||
- `Project URL`
|
||||
- `anon public` key
|
||||
**Terminologie:**
|
||||
- **Tabel:** users
|
||||
- **Kolommen:** id, name, email, created_at
|
||||
- **Rijen:** 3 records (Tim, Anna, Jan)
|
||||
- **Cell:** Eén specifieke waarde (bijv. "tim@email.com")
|
||||
|
||||
---
|
||||
|
||||
### Tabel Maken via Table Editor
|
||||
### Data Types
|
||||
|
||||
**In Supabase Dashboard:**
|
||||
Elke kolom heeft een type:
|
||||
|
||||
1. Ga naar "Table Editor"
|
||||
2. Klik "New Table"
|
||||
3. Naam: `todos`
|
||||
4. Kolommen:
|
||||
| Type | Beschrijving | Voorbeeld |
|
||||
|------|--------------|-----------|
|
||||
| `text` / `varchar` | Tekst | "Tim", "Hello world" |
|
||||
| `integer` / `int` | Hele getallen | 1, 42, -5 |
|
||||
| `decimal` / `numeric` | Decimalen | 19.99, 3.14 |
|
||||
| `boolean` | True/False | true, false |
|
||||
| `timestamp` | Datum + tijd | 2024-01-15 14:30:00 |
|
||||
| `uuid` | Unieke identifier | a1b2c3d4-e5f6-... |
|
||||
|
||||
| Name | Type | Default | Primary |
|
||||
|------|------|---------|---------|
|
||||
| id | int8 | - | ✓ (auto) |
|
||||
| title | text | - | |
|
||||
| completed | bool | false | |
|
||||
| created_at | timestamptz | now() | |
|
||||
|
||||
5. Klik "Save"
|
||||
|
||||
**Test:** Voeg een paar rijen toe via de UI om te zien dat het werkt.
|
||||
**Kies het juiste type:**
|
||||
- Prijs? → `decimal` (niet `integer`, want centen)
|
||||
- Is actief? → `boolean`
|
||||
- Naam? → `text`
|
||||
- Aantal? → `integer`
|
||||
|
||||
---
|
||||
|
||||
### Environment Variables
|
||||
### Primary Keys
|
||||
|
||||
**Wat zijn environment variables?**
|
||||
- Configuratie die NIET in je code hoort
|
||||
- API keys, database URLs, secrets
|
||||
- Verschillend per omgeving (lokaal vs productie)
|
||||
**Wat:** Een kolom die elke rij UNIEK identificeert.
|
||||
|
||||
**Maak `.env.local` in je project root:**
|
||||
```bash
|
||||
# .env.local - NOOIT committen naar Git!
|
||||
NEXT_PUBLIC_SUPABASE_URL=https://xxxxx.supabase.co
|
||||
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.xxxxx
|
||||
**Regels:**
|
||||
- Moet uniek zijn per rij
|
||||
- Mag nooit NULL zijn
|
||||
- Verandert nooit
|
||||
|
||||
**Voorbeeld:**
|
||||
```
|
||||
users
|
||||
------
|
||||
id (PRIMARY KEY) | name | email
|
||||
1 | Tim | tim@email.com
|
||||
2 | Anna | anna@email.com
|
||||
```
|
||||
|
||||
**Maak ook `.env.example` (WEL committen):**
|
||||
```bash
|
||||
# .env.example - template voor anderen
|
||||
NEXT_PUBLIC_SUPABASE_URL=your-supabase-url
|
||||
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
|
||||
**Waarom niet `email` als primary key?**
|
||||
- Emails kunnen veranderen
|
||||
- `id` is stabiel en snel
|
||||
|
||||
---
|
||||
|
||||
### Foreign Keys
|
||||
|
||||
**Wat:** Een kolom die verwijst naar de primary key van een andere tabel.
|
||||
|
||||
**Voorbeeld: Posts tabel**
|
||||
```
|
||||
posts
|
||||
------
|
||||
id | title | user_id (FOREIGN KEY → users.id)
|
||||
1 | "Mijn blog" | 1
|
||||
2 | "Hello world" | 1
|
||||
3 | "Tips" | 2
|
||||
```
|
||||
|
||||
**Check `.gitignore` bevat:**
|
||||
**Wat zegt dit?**
|
||||
- Post 1 en 2 zijn van user 1 (Tim)
|
||||
- Post 3 is van user 2 (Anna)
|
||||
|
||||
---
|
||||
|
||||
### Relatie Types
|
||||
|
||||
**One-to-Many (1:N)** - Meest voorkomend!
|
||||
```
|
||||
.env*.local
|
||||
Eén user → meerdere posts
|
||||
Eén category → meerdere products
|
||||
```
|
||||
|
||||
**One-to-One (1:1)** - Zeldzaam
|
||||
```
|
||||
Eén user → één profile
|
||||
```
|
||||
|
||||
**Many-to-Many (N:N)** - Via tussentabel
|
||||
```
|
||||
Posts ↔ Tags (een post heeft meerdere tags, een tag heeft meerdere posts)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Supabase SDK Installeren
|
||||
### One-to-Many Voorbeeld
|
||||
|
||||
```bash
|
||||
npm install @supabase/supabase-js
|
||||
```
|
||||
users posts
|
||||
------ ------
|
||||
id | name id | title | user_id
|
||||
1 | Tim ←────────── 1 | "Blog 1" | 1
|
||||
2 | Anna ←────┬───── 2 | "Blog 2" | 1
|
||||
└───── 3 | "Tips" | 2
|
||||
```
|
||||
|
||||
**Maak `src/lib/supabase.ts`:**
|
||||
```typescript
|
||||
import { createClient } from '@supabase/supabase-js'
|
||||
**Lees:** Tim heeft 2 posts, Anna heeft 1 post.
|
||||
|
||||
const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL!
|
||||
const supabaseAnonKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
|
||||
---
|
||||
|
||||
export const supabase = createClient(supabaseUrl, supabaseAnonKey)
|
||||
### Many-to-Many met Tussentabel
|
||||
|
||||
```
|
||||
posts post_tags tags
|
||||
------ --------- ------
|
||||
id | title post_id | tag_id id | name
|
||||
1 | "React tips" 1 | 1 1 | "react"
|
||||
2 | "CSS guide" 1 | 2 2 | "frontend"
|
||||
2 | 2 3 | "css"
|
||||
2 | 3
|
||||
```
|
||||
|
||||
**Lees:**
|
||||
- Post 1 heeft tags: react, frontend
|
||||
- Post 2 heeft tags: frontend, css
|
||||
|
||||
---
|
||||
|
||||
### Normalisatie Basics
|
||||
|
||||
**Probleem: Data duplicatie**
|
||||
```
|
||||
orders (SLECHT)
|
||||
------
|
||||
id | customer_name | customer_email | product_name | price
|
||||
1 | Tim | tim@email.com | Laptop | 999
|
||||
2 | Tim | tim@email.com | Phone | 699
|
||||
3 | Anna | anna@email.com | Laptop | 999
|
||||
```
|
||||
|
||||
**Problemen:**
|
||||
- Tim's email staat 2x (als hij verandert: 2 plekken updaten)
|
||||
- "Laptop" en prijs staan 2x
|
||||
|
||||
---
|
||||
|
||||
### Genormaliseerde Versie
|
||||
|
||||
```
|
||||
users products orders
|
||||
------ -------- ------
|
||||
id | name | email id | name | price id | user_id | product_id
|
||||
1 | Tim | tim@... 1 | Laptop | 999 1 | 1 | 1
|
||||
2 | Anna | anna@... 2 | Phone | 699 2 | 1 | 2
|
||||
3 | 2 | 1
|
||||
```
|
||||
|
||||
**Voordelen:**
|
||||
- Elk gegeven staat 1x
|
||||
- Update op 1 plek
|
||||
- Minder opslagruimte
|
||||
|
||||
---
|
||||
|
||||
### NULL Values
|
||||
|
||||
**NULL = "geen waarde" (niet 0, niet "")**
|
||||
|
||||
```
|
||||
users
|
||||
------
|
||||
id | name | phone
|
||||
1 | Tim | 0612345678
|
||||
2 | Anna | NULL ← Geen telefoon bekend
|
||||
```
|
||||
|
||||
**Wanneer NULL toestaan?**
|
||||
- Optionele velden (phone, description)
|
||||
- Niet bij verplichte velden (name, email)
|
||||
|
||||
---
|
||||
|
||||
### Defaults
|
||||
|
||||
**Automatische waarde als je niks opgeeft:**
|
||||
|
||||
```
|
||||
todos
|
||||
------
|
||||
id | title | completed | created_at
|
||||
| | DEFAULT: false | DEFAULT: now()
|
||||
```
|
||||
|
||||
Bij `INSERT INTO todos (title) VALUES ('Test')`:
|
||||
```
|
||||
id | title | completed | created_at
|
||||
1 | Test | false | 2024-01-15 10:30:00
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### CRUD Operaties
|
||||
### Database Schema Tekenen
|
||||
|
||||
**C - Create (toevoegen):**
|
||||
```typescript
|
||||
const { data, error } = await supabase
|
||||
.from('todos')
|
||||
.insert({ title: 'Nieuwe taak' })
|
||||
**Tools:** draw.io, Excalidraw, pen en papier
|
||||
|
||||
**Conventie:**
|
||||
```
|
||||
┌──────────────┐ ┌──────────────┐
|
||||
│ users │ │ posts │
|
||||
├──────────────┤ ├──────────────┤
|
||||
│ id (PK) │───┐ │ id (PK) │
|
||||
│ name │ │ │ title │
|
||||
│ email │ └────→│ user_id (FK) │
|
||||
│ created_at │ │ content │
|
||||
└──────────────┘ │ created_at │
|
||||
└──────────────┘
|
||||
```
|
||||
|
||||
**R - Read (ophalen):**
|
||||
```typescript
|
||||
const { data, error } = await supabase
|
||||
.from('todos')
|
||||
.select('*')
|
||||
.order('created_at', { ascending: false })
|
||||
```
|
||||
|
||||
**U - Update (wijzigen):**
|
||||
```typescript
|
||||
const { data, error } = await supabase
|
||||
.from('todos')
|
||||
.update({ completed: true })
|
||||
.eq('id', todoId)
|
||||
```
|
||||
|
||||
**D - Delete (verwijderen):**
|
||||
```typescript
|
||||
const { error } = await supabase
|
||||
.from('todos')
|
||||
.delete()
|
||||
.eq('id', todoId)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Authenticatie met Auth UI
|
||||
|
||||
**Installeer auth packages:**
|
||||
```bash
|
||||
npm install @supabase/auth-ui-react @supabase/auth-ui-shared
|
||||
```
|
||||
|
||||
**Login component:**
|
||||
```tsx
|
||||
import { Auth } from '@supabase/auth-ui-react'
|
||||
import { ThemeSupa } from '@supabase/auth-ui-shared'
|
||||
import { supabase } from '@/lib/supabase'
|
||||
|
||||
export function LoginForm() {
|
||||
return (
|
||||
<Auth
|
||||
supabaseClient={supabase}
|
||||
appearance={{ theme: ThemeSupa }}
|
||||
providers={[]}
|
||||
magicLink={true}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
**Huidige user checken:**
|
||||
```typescript
|
||||
const { data: { user } } = await supabase.auth.getUser()
|
||||
|
||||
if (user) {
|
||||
// User is ingelogd
|
||||
console.log('Logged in as:', user.email)
|
||||
} else {
|
||||
// Redirect naar login
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Deployment naar Vercel
|
||||
|
||||
**Stap 1: Push naar GitHub**
|
||||
```bash
|
||||
git add .
|
||||
git commit -m "Add Supabase integration"
|
||||
git push
|
||||
```
|
||||
|
||||
**Stap 2: Deploy op Vercel**
|
||||
1. Ga naar [vercel.com](https://vercel.com)
|
||||
2. "Add New Project"
|
||||
3. Import je GitHub repo
|
||||
4. **BELANGRIJK:** Voeg Environment Variables toe!
|
||||
- `NEXT_PUBLIC_SUPABASE_URL`
|
||||
- `NEXT_PUBLIC_SUPABASE_ANON_KEY`
|
||||
5. Klik "Deploy"
|
||||
|
||||
**Stap 3: Supabase Redirect URLs**
|
||||
1. Ga naar Supabase → Authentication → URL Configuration
|
||||
2. Voeg toe bij "Redirect URLs":
|
||||
- `https://jouw-app.vercel.app/**`
|
||||
|
||||
---
|
||||
|
||||
### Lokaal vs Productie
|
||||
|
||||
| Aspect | Lokaal | Productie |
|
||||
|--------|--------|-----------|
|
||||
| URL | `localhost:3000` | `jouw-app.vercel.app` |
|
||||
| Env vars | `.env.local` | Vercel Dashboard |
|
||||
| Database | Supabase (zelfde) | Supabase (zelfde) |
|
||||
| Command | `npm run dev` | Automatisch via Vercel |
|
||||
|
||||
**Let op:** Je gebruikt dezelfde Supabase database voor lokaal en productie. Voor echte projecten zou je aparte databases hebben.
|
||||
PK = Primary Key
|
||||
FK = Foreign Key
|
||||
Pijl = Relatie richting
|
||||
|
||||
---
|
||||
|
||||
## Tools
|
||||
- Supabase
|
||||
- Next.js
|
||||
- OpenCode/WebStorm
|
||||
- Vercel
|
||||
- Git
|
||||
- Pen en papier / Excalidraw / draw.io
|
||||
- Supabase Table Editor (vooruitblik)
|
||||
|
||||
---
|
||||
|
||||
## Lesopdracht (2 uur)
|
||||
|
||||
### Bouw een Todo App met Supabase
|
||||
### Database Design Oefening
|
||||
|
||||
**Deel 1: Supabase Setup (30 min)**
|
||||
**Deel 1: Blog Database Ontwerpen (45 min)**
|
||||
|
||||
1. Maak Supabase account en project
|
||||
2. Maak `todos` tabel via Table Editor
|
||||
3. Kopieer credentials
|
||||
4. Installeer `@supabase/supabase-js`
|
||||
5. Maak `src/lib/supabase.ts`
|
||||
6. Configureer `.env.local`
|
||||
Ontwerp een database voor een blog met:
|
||||
- Users (kunnen posts schrijven)
|
||||
- Posts (hebben een auteur)
|
||||
- Comments (op posts, door users)
|
||||
|
||||
Test: `npm run dev` werkt zonder errors
|
||||
Voor elke tabel:
|
||||
1. Teken de tabel met kolommen
|
||||
2. Bepaal data types
|
||||
3. Markeer Primary Keys
|
||||
4. Markeer Foreign Keys
|
||||
5. Teken de relaties
|
||||
|
||||
**Deel 2: CRUD Interface (1 uur)**
|
||||
**Deel 2: Normalisatie Oefening (30 min)**
|
||||
|
||||
Bouw UI voor todos:
|
||||
1. Lijst van todos tonen
|
||||
2. Form om nieuwe todo toe te voegen
|
||||
3. Checkbox om todo af te vinken
|
||||
4. Delete button per todo
|
||||
Gegeven deze "slechte" tabel:
|
||||
|
||||
Gebruik AI hulp voor de components!
|
||||
```
|
||||
library
|
||||
-------
|
||||
book_title | author_name | author_email | borrower_name | borrowed_date
|
||||
"1984" | "Orwell" | orwell@... | "Tim" | 2024-01-15
|
||||
"1984" | "Orwell" | orwell@... | "Anna" | 2024-01-10
|
||||
"Dune" | "Herbert" | herbert@... | "Tim" | 2024-01-12
|
||||
```
|
||||
|
||||
**Deel 3: Authenticatie (30 min)**
|
||||
Normaliseer naar aparte tabellen:
|
||||
1. Welke entiteiten zie je?
|
||||
2. Maak aparte tabellen
|
||||
3. Voeg relaties toe
|
||||
|
||||
1. Installeer auth packages
|
||||
2. Maak login pagina met Auth UI
|
||||
3. Toon alleen app voor ingelogde users
|
||||
4. Test: login met magic link
|
||||
**Deel 3: Eindproject Schema (45 min)**
|
||||
|
||||
Ontwerp het database schema voor jouw eindproject:
|
||||
1. Welke entiteiten heb je nodig?
|
||||
2. Teken elke tabel met kolommen
|
||||
3. Bepaal relaties
|
||||
4. Documenteer je keuzes
|
||||
|
||||
### Deliverable
|
||||
- Werkende Todo app lokaal
|
||||
- GitHub repository met code
|
||||
- Screenshot van werkende app
|
||||
- Blog database schema (tekening)
|
||||
- Genormaliseerde library database
|
||||
- Eindproject database schema
|
||||
|
||||
---
|
||||
|
||||
## Huiswerk (2 uur)
|
||||
|
||||
### Deploy naar Productie + Uitbreiden
|
||||
### Verdieping en Voorbereiding
|
||||
|
||||
**Deel 1: Deployment (30 min)**
|
||||
**Deel 1: Eindproject Schema Uitwerken (1 uur)**
|
||||
|
||||
1. Push naar GitHub
|
||||
2. Deploy naar Vercel
|
||||
3. Configureer env vars in Vercel
|
||||
4. Voeg Vercel URL toe aan Supabase Redirect URLs
|
||||
5. Test: app werkt op productie URL!
|
||||
Werk je database schema volledig uit:
|
||||
|
||||
**Deel 2: Features Uitbreiden (1 uur)**
|
||||
1. **Per tabel:**
|
||||
- Naam
|
||||
- Alle kolommen met data types
|
||||
- Primary key
|
||||
- Foreign keys
|
||||
- Defaults
|
||||
- Nullable fields
|
||||
|
||||
Voeg toe:
|
||||
1. Filter buttons: Alle / Actief / Voltooid
|
||||
2. Sorteer op datum (nieuwste eerst)
|
||||
3. Loading state tijdens data ophalen
|
||||
4. Error state bij problemen
|
||||
5. Empty state: "Geen todos gevonden"
|
||||
2. **Documenteer:**
|
||||
- Waarom deze structuur?
|
||||
- Welke relaties?
|
||||
- Eventuele alternatieve overwegingen
|
||||
|
||||
**Deel 3: Polish (30 min)**
|
||||
**Deel 2: Supabase Account (30 min)**
|
||||
|
||||
1. Styling verbeteren met Tailwind
|
||||
2. Responsive design (mobile friendly)
|
||||
3. Kleine animaties (fade in/out)
|
||||
Bereid je voor op volgende les:
|
||||
1. Maak account op [supabase.com](https://supabase.com)
|
||||
2. Verken de interface
|
||||
3. Bekijk de Table Editor
|
||||
|
||||
**Deel 3: Reflectie (30 min)**
|
||||
|
||||
Beantwoord deze vragen (kort):
|
||||
1. Wat is het verschil tussen primary en foreign key?
|
||||
2. Waarom normaliseren we data?
|
||||
3. Wanneer gebruik je one-to-many vs many-to-many?
|
||||
4. Welke tabellen heeft jouw eindproject nodig?
|
||||
|
||||
### Deliverable
|
||||
- Deployed app op Vercel (werkende URL!)
|
||||
- Alle features werken in productie
|
||||
- Screenshot van productie app
|
||||
- Volledig uitgewerkt database schema voor eindproject
|
||||
- Supabase account aangemaakt
|
||||
- Reflectie vragen beantwoord
|
||||
|
||||
---
|
||||
|
||||
## Leerdoelen
|
||||
Na deze les kan de student:
|
||||
- Een Supabase project aanmaken en configureren
|
||||
- Tabellen maken via de Table Editor (zonder SQL)
|
||||
- Environment variables correct beheren
|
||||
- De Supabase client installeren en configureren
|
||||
- CRUD operaties uitvoeren met de Supabase SDK
|
||||
- Authenticatie implementeren met Auth UI
|
||||
- Deployen naar Vercel met environment variables
|
||||
- Het verschil tussen lokale en productie omgeving begrijpen
|
||||
- Uitleggen wat een relationele database is
|
||||
- Tabellen, kolommen en rijen beschrijven
|
||||
- De juiste data types kiezen
|
||||
- Primary keys en hun doel uitleggen
|
||||
- Foreign keys en relaties begrijpen
|
||||
- One-to-many en many-to-many relaties herkennen
|
||||
- Het probleem van data duplicatie identificeren
|
||||
- Een database normaliseren
|
||||
- NULL values en defaults begrijpen
|
||||
- Een database schema ontwerpen en tekenen
|
||||
|
||||
@@ -1,302 +1,305 @@
|
||||
# Les 9: AI Agents - Custom GPTs & Claude Projects
|
||||
# Les 9: Supabase Basics
|
||||
|
||||
---
|
||||
|
||||
## Hoofdstuk
|
||||
**Hoofdstuk 2: Intermediate** (Les 4-9)
|
||||
**Deel 2: Technical Foundations** (Les 5-9)
|
||||
|
||||
## Beschrijving
|
||||
Leer werken met AI Agents: gepersonaliseerde AI assistenten die je kunt trainen op jouw specifieke taken en werkwijze.
|
||||
Leer werken met Supabase: een complete backend-as-a-service met database en authenticatie. Pas je database schema uit Les 8 toe en bouw je eerste full-stack app.
|
||||
|
||||
---
|
||||
|
||||
## Te Behandelen
|
||||
|
||||
### Wat zijn AI Agents?
|
||||
### Wat is Supabase?
|
||||
|
||||
**Chatbot vs Agent:**
|
||||
**Supabase = Database + Auth in één**
|
||||
- PostgreSQL database (gratis tier: 500MB)
|
||||
- Ingebouwde authenticatie
|
||||
- Real-time subscriptions
|
||||
- File storage
|
||||
- Auto-generated API
|
||||
|
||||
| Chatbot | Agent |
|
||||
|---------|-------|
|
||||
| Reageert op vragen | Neemt initiatief |
|
||||
| Geen geheugen | Onthoudt context |
|
||||
| Algemene kennis | Specifieke expertise |
|
||||
| Eenmalige interactie | Langere samenwerkingen |
|
||||
|
||||
**Agent = AI met:**
|
||||
- Custom instructies (hoe moet hij zich gedragen)
|
||||
- Eigen kennis (documenten, voorbeelden)
|
||||
- Specifieke taken (waar is hij goed in)
|
||||
**Waarom Supabase voor beginners:**
|
||||
- Geen eigen server nodig
|
||||
- Visuele Table Editor (geen SQL kennis nodig)
|
||||
- Simpele JavaScript SDK
|
||||
- Gratis tier is ruim voldoende
|
||||
|
||||
---
|
||||
|
||||
### Custom GPTs (ChatGPT)
|
||||
### Supabase Project Aanmaken
|
||||
|
||||
**Wat is een Custom GPT?**
|
||||
Een gepersonaliseerde versie van ChatGPT voor specifieke taken.
|
||||
**Stap 1:** Ga naar [supabase.com](https://supabase.com) en maak account
|
||||
|
||||
**Onderdelen:**
|
||||
1. **Instructions:** Hoe moet de GPT zich gedragen?
|
||||
2. **Conversation starters:** Voorbeeld prompts
|
||||
3. **Knowledge:** Upload documenten als context
|
||||
4. **Capabilities:** Web browsing, code interpreter, DALL-E
|
||||
**Stap 2:** Klik "New Project"
|
||||
- Naam: `todo-app`
|
||||
- Database Password: (bewaar deze!)
|
||||
- Region: `West EU (Frankfurt)` (dichtst bij NL)
|
||||
|
||||
**Voorbeeld: Code Reviewer GPT**
|
||||
**Stap 3:** Wacht ~2 minuten tot project klaar is
|
||||
|
||||
*Instructions:*
|
||||
**Stap 4:** Ga naar Settings → API en kopieer:
|
||||
- `Project URL`
|
||||
- `anon public` key
|
||||
|
||||
---
|
||||
|
||||
### Je Database Schema Implementeren
|
||||
|
||||
In Les 8 heb je een database schema ontworpen. Nu gaan we dat implementeren!
|
||||
|
||||
**In Supabase Dashboard → Table Editor:**
|
||||
|
||||
1. Klik "New Table"
|
||||
2. Gebruik je schema uit Les 8
|
||||
3. Voeg kolommen toe met de juiste types
|
||||
4. Definieer Primary Keys en Foreign Keys
|
||||
|
||||
**Voorbeeld: todos tabel**
|
||||
|
||||
| Name | Type | Default | Primary |
|
||||
|------|------|---------|---------|
|
||||
| id | int8 | - | ✓ (auto) |
|
||||
| title | text | - | |
|
||||
| completed | bool | false | |
|
||||
| created_at | timestamptz | now() | |
|
||||
|
||||
---
|
||||
|
||||
### Environment Variables
|
||||
|
||||
**Wat zijn environment variables?**
|
||||
- Configuratie die NIET in je code hoort
|
||||
- API keys, database URLs, secrets
|
||||
- Verschillend per omgeving (lokaal vs productie)
|
||||
|
||||
**Maak `.env.local` in je project root:**
|
||||
```bash
|
||||
# .env.local - NOOIT committen naar Git!
|
||||
NEXT_PUBLIC_SUPABASE_URL=https://xxxxx.supabase.co
|
||||
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.xxxxx
|
||||
```
|
||||
Je bent een strenge code reviewer voor React/TypeScript projecten.
|
||||
|
||||
Bij elke code review check je:
|
||||
1. TypeScript types correct?
|
||||
2. React best practices gevolgd?
|
||||
3. Geen hardcoded values?
|
||||
4. Error handling aanwezig?
|
||||
5. Accessibility (ARIA labels)?
|
||||
|
||||
Geef feedback in dit format:
|
||||
- ✅ Goed: [wat is goed]
|
||||
- ⚠️ Verbeter: [wat kan beter]
|
||||
- ❌ Fix: [wat moet gefixed worden]
|
||||
|
||||
Wees streng maar constructief.
|
||||
**Maak ook `.env.example` (WEL committen):**
|
||||
```bash
|
||||
# .env.example - template voor anderen
|
||||
NEXT_PUBLIC_SUPABASE_URL=your-supabase-url
|
||||
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Claude Projects
|
||||
### Supabase SDK Installeren
|
||||
|
||||
**Wat is een Claude Project?**
|
||||
Een Claude-omgeving met custom context voor een specifiek project.
|
||||
|
||||
**Onderdelen:**
|
||||
1. **Project Knowledge:** Upload relevante documenten
|
||||
2. **Custom Instructions:** Hoe moet Claude zich gedragen
|
||||
3. **Conversation History:** Context blijft bewaard
|
||||
|
||||
**Voordelen:**
|
||||
- Langere context dan ChatGPT
|
||||
- Betere nuance in antwoorden
|
||||
- Artifacts voor code en documenten
|
||||
|
||||
**Voorbeeld: Project voor je Todo App**
|
||||
|
||||
*Custom Instructions:*
|
||||
```
|
||||
Dit is mijn Todo app project.
|
||||
|
||||
Tech stack:
|
||||
- Next.js 14 met App Router
|
||||
- TypeScript
|
||||
- Tailwind CSS
|
||||
- Supabase voor database en auth
|
||||
|
||||
Code conventies:
|
||||
- Functional components
|
||||
- Named exports
|
||||
- Async/await (geen .then)
|
||||
|
||||
Als je code schrijft, volg altijd deze conventies.
|
||||
```bash
|
||||
npm install @supabase/supabase-js
|
||||
```
|
||||
|
||||
*Project Knowledge:*
|
||||
- Upload je belangrijkste component files
|
||||
- Upload je Supabase schema
|
||||
**Maak `src/lib/supabase.ts`:**
|
||||
```typescript
|
||||
import { createClient } from '@supabase/supabase-js'
|
||||
|
||||
---
|
||||
const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL!
|
||||
const supabaseAnonKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
|
||||
|
||||
### Wanneer Welke Gebruiken?
|
||||
|
||||
| Situatie | Tool |
|
||||
|----------|------|
|
||||
| Snelle code review | Custom GPT |
|
||||
| Werken aan specifiek project | Claude Project |
|
||||
| Documentatie genereren | Custom GPT |
|
||||
| Lange context nodig | Claude Project |
|
||||
| Wil delen met anderen | Custom GPT |
|
||||
| Privé project context | Claude Project |
|
||||
|
||||
---
|
||||
|
||||
### Custom GPT Maken
|
||||
|
||||
**Stap 1:** Ga naar chat.openai.com → "Explore GPTs" → "Create"
|
||||
|
||||
**Stap 2:** Vul in:
|
||||
- Naam: "React Code Reviewer"
|
||||
- Beschrijving: "Reviews React/TypeScript code"
|
||||
- Instructions: (zie voorbeeld hierboven)
|
||||
|
||||
**Stap 3:** Test met echte code
|
||||
|
||||
**Stap 4:** Itereer op instructions
|
||||
- Wat mist hij?
|
||||
- Wat doet hij verkeerd?
|
||||
- Pas aan en test opnieuw
|
||||
|
||||
---
|
||||
|
||||
### Claude Project Maken
|
||||
|
||||
**Stap 1:** Ga naar claude.ai → "Projects" → "Create project"
|
||||
|
||||
**Stap 2:** Geef project een naam
|
||||
|
||||
**Stap 3:** Upload Project Knowledge
|
||||
- Drag & drop je belangrijkste files
|
||||
- Of kopieer/plak code snippets
|
||||
|
||||
**Stap 4:** Schrijf Custom Instructions
|
||||
- Beschrijf je tech stack
|
||||
- Beschrijf je conventies
|
||||
- Beschrijf wat je wilt dat Claude doet
|
||||
|
||||
**Stap 5:** Start chatten binnen het project
|
||||
|
||||
---
|
||||
|
||||
### Agent Instructions Schrijven
|
||||
|
||||
**Goede instructions bevatten:**
|
||||
|
||||
1. **Rol:** Wie is de agent?
|
||||
```
|
||||
Je bent een senior React developer die code reviewt.
|
||||
```
|
||||
|
||||
2. **Context:** Wat is de situatie?
|
||||
```
|
||||
Je reviewt code voor een startup met strakke deadlines.
|
||||
Focus op kritieke issues, niet op style preferences.
|
||||
```
|
||||
|
||||
3. **Gedrag:** Hoe moet hij reageren?
|
||||
```
|
||||
Wees direct maar vriendelijk.
|
||||
Geef altijd een voorbeeld van de betere oplossing.
|
||||
```
|
||||
|
||||
4. **Format:** Hoe moet output eruitzien?
|
||||
```
|
||||
Gebruik markdown formatting.
|
||||
Groepeer feedback per categorie.
|
||||
```
|
||||
|
||||
5. **Beperkingen:** Wat moet hij NIET doen?
|
||||
```
|
||||
Herschrijf niet de hele codebase.
|
||||
Focus op de gevraagde code, niet op andere files.
|
||||
export const supabase = createClient(supabaseUrl, supabaseAnonKey)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Praktische Agent Ideeën
|
||||
### CRUD Operaties
|
||||
|
||||
| Agent | Doel |
|
||||
|-------|------|
|
||||
| **Code Reviewer** | Check code op bugs en best practices |
|
||||
| **Doc Generator** | Genereer documentatie voor components |
|
||||
| **Bug Debugger** | Help bij error messages uitleggen |
|
||||
| **Refactor Helper** | Suggesties voor code verbetering |
|
||||
| **Test Writer** | Genereer unit tests |
|
||||
| **Rubber Duck** | Denk hardop mee over problemen |
|
||||
**C - Create (toevoegen):**
|
||||
```typescript
|
||||
const { data, error } = await supabase
|
||||
.from('todos')
|
||||
.insert({ title: 'Nieuwe taak' })
|
||||
```
|
||||
|
||||
**R - Read (ophalen):**
|
||||
```typescript
|
||||
const { data, error } = await supabase
|
||||
.from('todos')
|
||||
.select('*')
|
||||
.order('created_at', { ascending: false })
|
||||
```
|
||||
|
||||
**U - Update (wijzigen):**
|
||||
```typescript
|
||||
const { data, error } = await supabase
|
||||
.from('todos')
|
||||
.update({ completed: true })
|
||||
.eq('id', todoId)
|
||||
```
|
||||
|
||||
**D - Delete (verwijderen):**
|
||||
```typescript
|
||||
const { error } = await supabase
|
||||
.from('todos')
|
||||
.delete()
|
||||
.eq('id', todoId)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Authenticatie met Auth UI
|
||||
|
||||
**Installeer auth packages:**
|
||||
```bash
|
||||
npm install @supabase/auth-ui-react @supabase/auth-ui-shared
|
||||
```
|
||||
|
||||
**Login component:**
|
||||
```tsx
|
||||
import { Auth } from '@supabase/auth-ui-react'
|
||||
import { ThemeSupa } from '@supabase/auth-ui-shared'
|
||||
import { supabase } from '@/lib/supabase'
|
||||
|
||||
export function LoginForm() {
|
||||
return (
|
||||
<Auth
|
||||
supabaseClient={supabase}
|
||||
appearance={{ theme: ThemeSupa }}
|
||||
providers={[]}
|
||||
magicLink={true}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
**Huidige user checken:**
|
||||
```typescript
|
||||
const { data: { user } } = await supabase.auth.getUser()
|
||||
|
||||
if (user) {
|
||||
// User is ingelogd
|
||||
console.log('Logged in as:', user.email)
|
||||
} else {
|
||||
// Redirect naar login
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Deployment naar Vercel
|
||||
|
||||
**Stap 1: Push naar GitHub**
|
||||
```bash
|
||||
git add .
|
||||
git commit -m "Add Supabase integration"
|
||||
git push
|
||||
```
|
||||
|
||||
**Stap 2: Deploy op Vercel**
|
||||
1. Ga naar [vercel.com](https://vercel.com)
|
||||
2. "Add New Project"
|
||||
3. Import je GitHub repo
|
||||
4. **BELANGRIJK:** Voeg Environment Variables toe!
|
||||
- `NEXT_PUBLIC_SUPABASE_URL`
|
||||
- `NEXT_PUBLIC_SUPABASE_ANON_KEY`
|
||||
5. Klik "Deploy"
|
||||
|
||||
**Stap 3: Supabase Redirect URLs**
|
||||
1. Ga naar Supabase → Authentication → URL Configuration
|
||||
2. Voeg toe bij "Redirect URLs":
|
||||
- `https://jouw-app.vercel.app/**`
|
||||
|
||||
---
|
||||
|
||||
## Tools
|
||||
- ChatGPT (Custom GPTs)
|
||||
- Claude Desktop (Projects)
|
||||
- Supabase
|
||||
- Next.js
|
||||
- OpenCode/WebStorm
|
||||
- Vercel
|
||||
- Git
|
||||
|
||||
---
|
||||
|
||||
## Lesopdracht (2 uur)
|
||||
|
||||
### Bouw Je Eerste AI Agents
|
||||
### Bouw een Todo App met Supabase
|
||||
|
||||
**Deel 1: Custom GPT - Code Reviewer (45 min)**
|
||||
**Groepsdiscussie (15 min):**
|
||||
Bespreek klassikaal de database schemas uit Les 8 - wie heeft welke structuur gekozen en waarom?
|
||||
|
||||
1. Ga naar ChatGPT → Create GPT
|
||||
2. Maak "Code Reviewer" met deze checklist:
|
||||
- TypeScript types
|
||||
- React best practices
|
||||
- Error handling
|
||||
- Accessibility
|
||||
- Performance
|
||||
3. Upload sample "goede" code als knowledge
|
||||
4. Test met code uit je Todo app
|
||||
5. Itereer op de instructions
|
||||
**Deel 1: Supabase Setup (30 min)**
|
||||
|
||||
**Deel 2: Claude Project - Todo App Context (45 min)**
|
||||
1. Maak Supabase account en project
|
||||
2. Maak je tabellen via Table Editor (gebaseerd op Les 8 schema)
|
||||
3. Kopieer credentials
|
||||
4. Installeer `@supabase/supabase-js`
|
||||
5. Maak `src/lib/supabase.ts`
|
||||
6. Configureer `.env.local`
|
||||
|
||||
1. Maak nieuw Claude Project
|
||||
2. Upload je Todo app files als knowledge
|
||||
3. Schrijf custom instructions met je tech stack
|
||||
4. Test: vraag Claude om een nieuwe feature te bouwen
|
||||
5. Vergelijk: kent hij je project context?
|
||||
Test: `npm run dev` werkt zonder errors
|
||||
|
||||
**Deel 3: Vergelijking (30 min)**
|
||||
**Deel 2: CRUD Interface (1 uur)**
|
||||
|
||||
Test dezelfde vraag in beide:
|
||||
```
|
||||
Review deze code en geef verbeter suggesties:
|
||||
[plak je TodoList component]
|
||||
```
|
||||
Bouw UI voor todos:
|
||||
1. Lijst van todos tonen
|
||||
2. Form om nieuwe todo toe te voegen
|
||||
3. Checkbox om todo af te vinken
|
||||
4. Delete button per todo
|
||||
|
||||
Documenteer:
|
||||
- Welke geeft betere feedback?
|
||||
- Welke voelt meer "op maat"?
|
||||
- Wanneer zou je welke gebruiken?
|
||||
Gebruik AI hulp voor de components!
|
||||
|
||||
**Deel 3: Authenticatie (30 min)**
|
||||
|
||||
1. Installeer auth packages
|
||||
2. Maak login pagina met Auth UI
|
||||
3. Toon alleen app voor ingelogde users
|
||||
4. Test: login met magic link
|
||||
|
||||
### Deliverable
|
||||
- Werkende Custom GPT (link delen)
|
||||
- Claude Project met project context
|
||||
- Vergelijkings notities
|
||||
- Werkende Todo app lokaal
|
||||
- GitHub repository met code
|
||||
- Screenshot van werkende app
|
||||
|
||||
---
|
||||
|
||||
## Huiswerk (2 uur)
|
||||
|
||||
### Personal Dev Assistant
|
||||
### Deploy naar Productie + Uitbreiden
|
||||
|
||||
**Deel 1: Bouw Je Personal Assistant (1 uur)**
|
||||
**Deel 1: Deployment (30 min)**
|
||||
|
||||
Maak een Custom GPT of Claude Project die:
|
||||
- Jouw coding standards kent
|
||||
- Jouw tech stack begrijpt
|
||||
- Jouw workflow ondersteunt
|
||||
1. Push naar GitHub
|
||||
2. Deploy naar Vercel
|
||||
3. Configureer env vars in Vercel
|
||||
4. Voeg Vercel URL toe aan Supabase Redirect URLs
|
||||
5. Test: app werkt op productie URL!
|
||||
|
||||
**Include in instructions:**
|
||||
- Jouw voorkeuren (tabs vs spaces, etc.)
|
||||
- Jouw tech stack details
|
||||
- Typische taken die je doet
|
||||
- Hoe je feedback wilt krijgen
|
||||
**Deel 2: Features Uitbreiden (1 uur)**
|
||||
|
||||
**Deel 2: Test in Echt Werk (45 min)**
|
||||
Voeg toe:
|
||||
1. Filter buttons: Alle / Actief / Voltooid
|
||||
2. Sorteer op datum (nieuwste eerst)
|
||||
3. Loading state tijdens data ophalen
|
||||
4. Error state bij problemen
|
||||
5. Empty state: "Geen todos gevonden"
|
||||
|
||||
Gebruik je assistant voor echte taken:
|
||||
1. Code review van een component
|
||||
2. Help bij een bug
|
||||
3. Genereer documentatie
|
||||
**Deel 3: Polish (30 min)**
|
||||
|
||||
**Deel 3: Reflectie (15 min)**
|
||||
|
||||
Schrijf korte reflectie (300 woorden):
|
||||
- Hoe helpful was je agent?
|
||||
- Wat zou je verbeteren?
|
||||
- Ga je dit blijven gebruiken?
|
||||
1. Styling verbeteren met Tailwind
|
||||
2. Responsive design (mobile friendly)
|
||||
3. Kleine animaties (fade in/out)
|
||||
|
||||
### Deliverable
|
||||
- Personal Dev Assistant (GPT link of Claude Project screenshot)
|
||||
- 3 voorbeelden van gebruik
|
||||
- Reflectie (300 woorden)
|
||||
- Deployed app op Vercel (werkende URL!)
|
||||
- Alle features werken in productie
|
||||
- Screenshot van productie app
|
||||
|
||||
---
|
||||
|
||||
## Leerdoelen
|
||||
Na deze les kan de student:
|
||||
- Het verschil uitleggen tussen chatbots en AI agents
|
||||
- Custom GPTs bouwen met instructions en knowledge base
|
||||
- Claude Projects opzetten met custom instructions en context
|
||||
- Effectieve agent instructions schrijven
|
||||
- De juiste tool kiezen (Custom GPT vs Claude Project)
|
||||
- Een personal dev assistant maken voor eigen workflow
|
||||
- Een Supabase project aanmaken en configureren
|
||||
- Database schema implementeren via Table Editor
|
||||
- Environment variables correct beheren
|
||||
- De Supabase client installeren en configureren
|
||||
- CRUD operaties uitvoeren met de Supabase SDK
|
||||
- Authenticatie implementeren met Auth UI
|
||||
- Deployen naar Vercel met environment variables
|
||||
- Database principles uit Les 8 toepassen in de praktijk
|
||||
|
||||
@@ -1,278 +1,270 @@
|
||||
# Les 10: Introduction to Cursor
|
||||
# Les 10: AI Tool Selection & Workflows
|
||||
|
||||
---
|
||||
|
||||
## Hoofdstuk
|
||||
**Hoofdstuk 3: Advanced** (Les 10-18)
|
||||
**Deel 3: AI Tooling & Prototyping** (Les 10-12)
|
||||
|
||||
## Beschrijving
|
||||
Kennismaking met Cursor - de professionele AI code editor. Leer de core features en ontdek waarom dit de tool is voor serieuze AI-assisted development.
|
||||
Leer de sterke en zwakke punten van elke AI tool kennen. Ontwikkel een framework om de juiste tool te kiezen voor de juiste taak en bouw je eigen workflow.
|
||||
|
||||
---
|
||||
|
||||
## Te Behandelen
|
||||
|
||||
### Waarom Cursor?
|
||||
### Waarom Tool Selection Belangrijk Is
|
||||
|
||||
**Tot nu toe gebruikten we:**
|
||||
- OpenCode (gratis, goed voor leren)
|
||||
- Claude Desktop (voor agents en projects)
|
||||
Je kent nu meerdere AI tools:
|
||||
- ChatGPT (brainstormen, planning, uitleg)
|
||||
- Claude (lange context, nuance, analyse)
|
||||
- v0.dev (UI prototyping)
|
||||
- OpenCode (code schrijven met project context)
|
||||
|
||||
**Cursor is de volgende stap:**
|
||||
- Purpose-built voor AI-assisted coding
|
||||
- Professionele editor (gebaseerd op VS Code)
|
||||
- Superieure AI integratie
|
||||
- Free tier beschikbaar (voldoende voor de cursus)
|
||||
**Het probleem:** Elke tool heeft sterke en zwakke punten. De juiste tool kiezen bespaart tijd en levert betere resultaten.
|
||||
|
||||
---
|
||||
|
||||
### Free vs Pro
|
||||
### Tool Vergelijking
|
||||
|
||||
| Aspect | Free Tier | Pro ($20/maand) |
|
||||
|--------|-----------|-----------------|
|
||||
| Tab completion | ✅ | ✅ |
|
||||
| CMD+K edits | Beperkt | Onbeperkt |
|
||||
| Chat | Beperkt | Onbeperkt |
|
||||
| Composer | Beperkt | Onbeperkt |
|
||||
| Models | GPT-4, Claude | Alle modellen |
|
||||
|
||||
**Voor deze cursus:** Free tier is voldoende!
|
||||
| Tool | Sterk in | Minder sterk in | Kosten |
|
||||
|------|----------|-----------------|--------|
|
||||
| **ChatGPT** | Brainstormen, uitleg, planning, algemene kennis | Grote codebases, lange context | Gratis / Pro €20/maand |
|
||||
| **Claude** | Lange documenten, nuance, analyse, veiligheid | Soms te voorzichtig, geen images genereren | Gratis / Pro $20/maand |
|
||||
| **v0.dev** | UI components, snel prototypen, Tailwind | Complexe logica, backend | Gratis tier |
|
||||
| **OpenCode** | Code schrijven, project context, terminal | Geen web access, geen images | Gratis |
|
||||
|
||||
---
|
||||
|
||||
### Installatie
|
||||
### Tool Selection Framework
|
||||
|
||||
1. Ga naar [cursor.sh](https://cursor.sh)
|
||||
2. Download voor jouw OS
|
||||
3. Installeer
|
||||
4. Open Cursor
|
||||
5. Sign in met GitHub
|
||||
**Stap 1: Identificeer de taak**
|
||||
- Wat wil je bereiken?
|
||||
- Hoe complex is het?
|
||||
- Hoeveel context is nodig?
|
||||
|
||||
**Eerste keer:**
|
||||
- Cursor vraagt om settings te importeren van VS Code (optioneel)
|
||||
- Accept default keybindings
|
||||
**Stap 2: Kies de juiste tool**
|
||||
|
||||
---
|
||||
|
||||
### Core Features
|
||||
|
||||
#### 1. Tab Completion
|
||||
AI-powered autocomplete die hele blokken code voorspelt.
|
||||
|
||||
**Hoe het werkt:**
|
||||
- Begin met typen
|
||||
- Cursor suggereert code in grijs
|
||||
- Druk Tab om te accepteren
|
||||
- Druk Escape om te negeren
|
||||
|
||||
**Tip:** Schrijf een comment over wat je wilt, en Tab completion vult de code in.
|
||||
|
||||
```typescript
|
||||
// Function that calculates the total price with tax
|
||||
// [Tab completion vult de functie in]
|
||||
```
|
||||
Als je wilt... Gebruik...
|
||||
─────────────────────────────────────────────────
|
||||
Brainstormen over een idee → ChatGPT
|
||||
Een lange codebase analyseren → Claude
|
||||
Snel een UI component maken → v0.dev
|
||||
Code schrijven met project context → OpenCode
|
||||
Een complex document begrijpen → Claude
|
||||
Uitleg krijgen over een concept → ChatGPT
|
||||
React component met styling → v0.dev
|
||||
Feature implementeren in project → OpenCode
|
||||
```
|
||||
|
||||
#### 2. CMD+K (Inline Editing)
|
||||
Selecteer code en vraag AI om het aan te passen.
|
||||
---
|
||||
|
||||
**Hoe het werkt:**
|
||||
1. Selecteer code (of zet cursor op een regel)
|
||||
2. Druk CMD+K (Mac) of Ctrl+K (Windows)
|
||||
3. Typ je instructie
|
||||
4. Enter om te genereren
|
||||
5. Accept of Reject de wijziging
|
||||
### Workflow Patterns
|
||||
|
||||
**Voorbeelden:**
|
||||
- "Add error handling"
|
||||
- "Convert to TypeScript"
|
||||
- "Make this responsive"
|
||||
- "Add loading state"
|
||||
|
||||
#### 3. Chat (Sidebar)
|
||||
Converseer met AI over je code.
|
||||
|
||||
**Hoe het werkt:**
|
||||
1. CMD+Shift+L opent Chat
|
||||
2. Stel je vraag
|
||||
3. AI heeft context van je open file
|
||||
|
||||
**Voorbeelden:**
|
||||
- "Explain what this function does"
|
||||
- "How can I optimize this?"
|
||||
- "What's wrong with this code?"
|
||||
|
||||
#### 4. @ Mentions
|
||||
Refereer naar files, folders, of documentatie.
|
||||
|
||||
**Syntax:**
|
||||
- `@filename.tsx` - specifieke file
|
||||
- `@folder/` - hele folder
|
||||
- `@Docs` - officiële docs zoeken
|
||||
- `@Web` - web zoeken
|
||||
|
||||
**Voorbeeld:**
|
||||
**Pattern 1: Planning → Prototyping → Implementation**
|
||||
```
|
||||
@components/Button.tsx - How can I add a loading prop to this?
|
||||
1. ChatGPT: Brainstorm features, maak planning
|
||||
2. v0.dev: Genereer UI prototypes
|
||||
3. OpenCode: Implementeer met project context
|
||||
```
|
||||
|
||||
#### 5. Composer Mode
|
||||
Multi-file generatie in één keer.
|
||||
**Pattern 2: Research → Design → Build**
|
||||
```
|
||||
1. ChatGPT/Claude: Research beste aanpak
|
||||
2. v0.dev: Design components
|
||||
3. OpenCode: Bouw en integreer
|
||||
```
|
||||
|
||||
**Hoe het werkt:**
|
||||
1. CMD+I opent Composer
|
||||
2. Beschrijf wat je wilt bouwen
|
||||
3. AI genereert meerdere files tegelijk
|
||||
4. Review en accept changes
|
||||
|
||||
**Wanneer gebruiken:**
|
||||
- Nieuwe features met meerdere components
|
||||
- Refactoring over meerdere files
|
||||
- Boilerplate code genereren
|
||||
**Pattern 3: Quick Iteration**
|
||||
```
|
||||
1. v0.dev: Snel component genereren
|
||||
2. OpenCode: Aanpassen en integreren
|
||||
3. Repeat
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Workflow Vergelijking
|
||||
### Praktijk: Dezelfde Taak, Drie Tools
|
||||
|
||||
| Taak | OpenCode | Cursor |
|
||||
|------|----------|--------|
|
||||
| Snelle fix | Chat | CMD+K |
|
||||
| Nieuwe component | Chat | Tab completion + CMD+K |
|
||||
| Multi-file feature | Meerdere chats | Composer |
|
||||
| Code uitleg | Chat | Chat + @ mentions |
|
||||
| Refactoring | Chat | CMD+K of Composer |
|
||||
**Opdracht:** Bouw een Contact Form component
|
||||
|
||||
**Met ChatGPT:**
|
||||
```
|
||||
Prompt: Ik wil een contact form maken met React en Tailwind.
|
||||
Velden: naam, email, bericht. Validatie nodig.
|
||||
Geef me de code en leg uit hoe het werkt.
|
||||
```
|
||||
→ Krijg: Uitleg + code, maar zonder project context
|
||||
|
||||
**Met v0.dev:**
|
||||
```
|
||||
Prompt: Modern contact form with name, email, message fields.
|
||||
Tailwind styling, validation, responsive design.
|
||||
```
|
||||
→ Krijg: Visueel prototype, direct te gebruiken
|
||||
|
||||
**Met OpenCode:**
|
||||
```
|
||||
Prompt: Maak een ContactForm component in src/components/
|
||||
met naam, email en bericht velden. Gebruik onze bestaande
|
||||
Input en Button components. Voeg Zod validatie toe.
|
||||
```
|
||||
→ Krijg: Geïntegreerde code die past in je project
|
||||
|
||||
---
|
||||
|
||||
### Tips voor Beginners
|
||||
### Wanneer Combineer Je Tools?
|
||||
|
||||
1. **Start met Tab completion**
|
||||
- Gewoon typen en kijken wat er gebeurt
|
||||
- Comments zijn je vriend
|
||||
**Scenario 1: Nieuwe feature bouwen**
|
||||
1. ChatGPT: "Hoe zou je een dark mode toggle implementeren in React?"
|
||||
2. v0.dev: "Dark mode toggle component with smooth transition"
|
||||
3. OpenCode: "Integreer deze toggle in onze navbar, sla preference op in localStorage"
|
||||
|
||||
2. **CMD+K voor snelle edits**
|
||||
- Selecteer precies wat je wilt aanpassen
|
||||
- Wees specifiek in je instructie
|
||||
**Scenario 2: Bug oplossen**
|
||||
1. OpenCode: Vraag om bug te identificeren
|
||||
2. Claude: Als de foutmelding complex is, vraag om uitleg
|
||||
3. OpenCode: Implementeer de fix
|
||||
|
||||
3. **Chat voor vragen**
|
||||
- Als je iets niet begrijpt
|
||||
- Als je opties wilt vergelijken
|
||||
|
||||
4. **@ mentions voor context**
|
||||
- AI weet niet automatisch over andere files
|
||||
- Voeg relevante files toe met @
|
||||
**Scenario 3: Nieuwe technologie leren**
|
||||
1. ChatGPT: "Leg uit hoe React Server Components werken"
|
||||
2. v0.dev: "Example of React Server Component with data fetching"
|
||||
3. OpenCode: "Help me dit toe te passen in mijn Next.js project"
|
||||
|
||||
---
|
||||
|
||||
### Keyboard Shortcuts Cheat Sheet
|
||||
### Anti-Patterns (Wat Niet Te Doen)
|
||||
|
||||
| Actie | Mac | Windows |
|
||||
|-------|-----|---------|
|
||||
| Tab completion accept | Tab | Tab |
|
||||
| Inline edit | CMD+K | Ctrl+K |
|
||||
| Open Chat | CMD+Shift+L | Ctrl+Shift+L |
|
||||
| Open Composer | CMD+I | Ctrl+I |
|
||||
| Accept suggestion | CMD+Y | Ctrl+Y |
|
||||
| Reject suggestion | CMD+N | Ctrl+N |
|
||||
**❌ Verkeerde tool voor de taak:**
|
||||
- ChatGPT vragen om een hele app te bouwen → te weinig context
|
||||
- v0.dev vragen om complexe backend logica → niet zijn sterke punt
|
||||
- OpenCode vragen om design inspiratie → kan geen images maken
|
||||
|
||||
**❌ Heen en weer kopiëren zonder begrip:**
|
||||
- Kopieer niet blind code van ChatGPT naar je project
|
||||
- Begrijp eerst WAT de code doet
|
||||
|
||||
**❌ Dezelfde prompt in elke tool:**
|
||||
- Pas je prompt aan per tool
|
||||
- v0.dev wil visuele beschrijvingen
|
||||
- OpenCode wil project-specifieke context
|
||||
|
||||
---
|
||||
|
||||
## Tools
|
||||
- Cursor
|
||||
- GitHub
|
||||
- ChatGPT
|
||||
- Claude
|
||||
- v0.dev
|
||||
- OpenCode/WebStorm
|
||||
|
||||
---
|
||||
|
||||
## Lesopdracht (2 uur)
|
||||
|
||||
### Cursor Verkennen
|
||||
### Tool Comparison Challenge
|
||||
|
||||
**Deel 1: Setup (20 min)**
|
||||
**Deel 1: Dezelfde Taak, Drie Tools (1 uur)**
|
||||
|
||||
1. Download en installeer Cursor
|
||||
2. Sign in met GitHub
|
||||
3. Open je Todo app project
|
||||
4. Verken de interface
|
||||
Bouw een "Contact Form" component met alle drie de tools:
|
||||
|
||||
**Deel 2: Tab Completion (30 min)**
|
||||
1. **ChatGPT (20 min)**
|
||||
- Vraag om code + uitleg
|
||||
- Noteer: hoe lang duurde het, kwaliteit output, wat miste?
|
||||
|
||||
Maak nieuwe file `src/components/LoadingSpinner.tsx`:
|
||||
1. Typ comment: `// Loading spinner component with size prop`
|
||||
2. Laat Tab completion de rest doen
|
||||
3. Itereer met meer comments
|
||||
4. Noteer: hoe goed is de completion?
|
||||
2. **v0.dev (20 min)**
|
||||
- Genereer visueel prototype
|
||||
- Noteer: hoe snel, hoe mooi, hoe aanpasbaar?
|
||||
|
||||
**Deel 3: CMD+K Oefenen (30 min)**
|
||||
3. **OpenCode (20 min)**
|
||||
- Integreer in bestaand project
|
||||
- Noteer: hoe goed past het, hoeveel aanpassing nodig?
|
||||
|
||||
Open je TodoList component:
|
||||
1. Selecteer de list rendering code
|
||||
2. CMD+K → "Add loading state with skeleton"
|
||||
3. Selecteer een button
|
||||
4. CMD+K → "Add disabled state while loading"
|
||||
5. Selecteer een function
|
||||
6. CMD+K → "Add try-catch with error toast"
|
||||
**Deel 2: Analyse (30 min)**
|
||||
|
||||
Noteer wat werkt en wat niet.
|
||||
Vul dit schema in:
|
||||
|
||||
**Deel 4: Chat + @ Mentions (20 min)**
|
||||
| Aspect | ChatGPT | v0.dev | OpenCode |
|
||||
|--------|---------|--------|----------|
|
||||
| Tijd tot werkend component | | | |
|
||||
| Kwaliteit code | | | |
|
||||
| Visueel design | | | |
|
||||
| Past in project | | | |
|
||||
| Hoeveel aanpassing nodig | | | |
|
||||
| Totaalscore (1-10) | | | |
|
||||
|
||||
1. Open Chat (CMD+Shift+L)
|
||||
2. Vraag: "@TodoList.tsx What could I improve in this component?"
|
||||
3. Vraag: "@lib/supabase.ts How do I add real-time subscriptions?"
|
||||
4. Probeer @Docs voor Next.js documentatie
|
||||
**Deel 3: Workflow Documentatie (30 min)**
|
||||
|
||||
**Deel 5: Composer Proberen (20 min)**
|
||||
|
||||
1. Open Composer (CMD+I)
|
||||
2. Vraag: "Create a Settings page with dark mode toggle and notification preferences. Use our existing component style."
|
||||
3. Review de gegenereerde files
|
||||
4. Accept of reject
|
||||
- Maak `docs/WORKFLOW.md` in je project
|
||||
- Documenteer je ideale workflow per taaktype
|
||||
- Inclusief template prompts voor elke tool
|
||||
|
||||
### Deliverable
|
||||
- Screenshot van werkende Tab completion
|
||||
- 3 voorbeelden van CMD+K edits
|
||||
- Notities: wat werkt wel/niet goed
|
||||
- Screenshot van alle 3 contact forms
|
||||
- Ingevuld vergelijkingsschema
|
||||
- `docs/WORKFLOW.md` bestand
|
||||
|
||||
---
|
||||
|
||||
## Huiswerk (2 uur)
|
||||
|
||||
### Bouw Feature met Cursor
|
||||
### Bouw Je Tool Selection Cheat Sheet
|
||||
|
||||
**Deel 1: Feature Bouwen (1.5 uur)**
|
||||
**Deel 1: Cheat Sheet Maken (1 uur)**
|
||||
|
||||
Voeg "Due Dates" toe aan je Todo app:
|
||||
1. Elk todo kan een due date hebben
|
||||
2. Toon due date in de lijst
|
||||
3. Sorteer op due date
|
||||
4. Markeer overdue items in rood
|
||||
Maak een persoonlijke "Tool Selection Cheat Sheet" (1 pagina):
|
||||
|
||||
**Gebruik ALLE Cursor features:**
|
||||
- Tab completion voor nieuwe code
|
||||
- CMD+K voor aanpassingen
|
||||
- Chat voor vragen
|
||||
- Composer voor multi-file changes
|
||||
```markdown
|
||||
# Mijn AI Tool Cheat Sheet
|
||||
|
||||
**Deel 2: Reflectie (30 min)**
|
||||
## Wanneer gebruik ik wat?
|
||||
|
||||
Schrijf vergelijking (400 woorden):
|
||||
- Cursor vs OpenCode: wat is beter?
|
||||
- Welke feature gebruik je het meest?
|
||||
- Is free tier voldoende?
|
||||
- Ga je overstappen?
|
||||
### ChatGPT
|
||||
- ✅ Gebruik voor: [jouw ervaring]
|
||||
- ❌ Niet voor: [jouw ervaring]
|
||||
- 💡 Beste prompt tip: [jouw tip]
|
||||
|
||||
### Claude
|
||||
- ✅ Gebruik voor: [jouw ervaring]
|
||||
- ❌ Niet voor: [jouw ervaring]
|
||||
- 💡 Beste prompt tip: [jouw tip]
|
||||
|
||||
### v0.dev
|
||||
- ✅ Gebruik voor: [jouw ervaring]
|
||||
- ❌ Niet voor: [jouw ervaring]
|
||||
- 💡 Beste prompt tip: [jouw tip]
|
||||
|
||||
### OpenCode
|
||||
- ✅ Gebruik voor: [jouw ervaring]
|
||||
- ❌ Niet voor: [jouw ervaring]
|
||||
- 💡 Beste prompt tip: [jouw tip]
|
||||
```
|
||||
|
||||
**Deel 2: Testen op Nieuwe Taken (45 min)**
|
||||
|
||||
Test je cheat sheet op 2 nieuwe taken:
|
||||
1. Bouw een "Testimonial Card" component
|
||||
2. Voeg een "Dark Mode Toggle" toe
|
||||
|
||||
Per taak: kies tools op basis van cheat sheet, voer uit, update cheat sheet.
|
||||
|
||||
**Deel 3: Reflectie (15 min)**
|
||||
|
||||
Schrijf korte reflectie (400 woorden):
|
||||
- Welke tool is jouw favoriet en waarom?
|
||||
- Wanneer combineer je tools?
|
||||
- Wat ga je anders doen na deze les?
|
||||
|
||||
### Deliverable
|
||||
- Werkende Due Dates feature
|
||||
- GitHub commit met de changes
|
||||
- Tool Selection Cheat Sheet (1 pagina)
|
||||
- 2 gebouwde components
|
||||
- Reflectie (400 woorden)
|
||||
|
||||
---
|
||||
|
||||
## Leerdoelen
|
||||
Na deze les kan de student:
|
||||
- Cursor installeren en configureren
|
||||
- Tab completion effectief gebruiken
|
||||
- CMD+K gebruiken voor inline edits
|
||||
- Chat gebruiken met @ mentions voor context
|
||||
- Composer mode gebruiken voor multi-file generatie
|
||||
- Het verschil beoordelen tussen Cursor en OpenCode
|
||||
- De juiste Cursor feature kiezen per taak
|
||||
- De sterke en zwakke punten van elke AI tool benoemen
|
||||
- De juiste tool kiezen voor een specifieke taak
|
||||
- Meerdere tools combineren in een effectieve workflow
|
||||
- Een persoonlijke workflow documenteren
|
||||
- Template prompts schrijven per tool
|
||||
- Kritisch evalueren welke tool wanneer het beste werkt
|
||||
|
||||
@@ -1,448 +1,237 @@
|
||||
# Les 11: Project Setup & Repository Structure
|
||||
# Les 11: Hands-on: Van Idee naar Prototype
|
||||
|
||||
---
|
||||
|
||||
## Hoofdstuk
|
||||
**Hoofdstuk 3: Advanced** (Les 10-18)
|
||||
**Deel 3: AI Tooling & Prototyping** (Les 10-12)
|
||||
|
||||
## Beschrijving
|
||||
Zet je eindproject professioneel op met de juiste structuur, documentatie, en AI-configuratie. Je past alles toe wat je hebt geleerd en maakt je project klaar voor Cursor.
|
||||
Pas alles wat je hebt geleerd toe in een hands-on sessie. Ga van een vaag idee naar een werkend prototype met behulp van je AI workflow.
|
||||
|
||||
---
|
||||
|
||||
## Te Behandelen
|
||||
|
||||
### Waarom Goede Structuur Belangrijk Is
|
||||
### Van Idee naar Feature Breakdown
|
||||
|
||||
**Voor AI:**
|
||||
- AI begrijpt beter wat je project doet
|
||||
- Betere code suggestions
|
||||
- Minder hallucinaties
|
||||
**Het probleem:** Je hebt een idee, maar waar begin je?
|
||||
|
||||
**Voor jezelf:**
|
||||
- Makkelijker navigeren
|
||||
- Sneller features bouwen
|
||||
- Betere samenwerking
|
||||
**Stap 1: Beschrijf je idee in 1-2 zinnen**
|
||||
```
|
||||
"Ik wil een app waar je kunt bijhouden welke planten water nodig hebben."
|
||||
```
|
||||
|
||||
**Stap 2: Vraag AI om feature breakdown**
|
||||
```
|
||||
Prompt: Ik wil een plant watering tracker app bouwen.
|
||||
Wat zijn de minimale features voor een werkend prototype?
|
||||
Denk aan: wat moet een gebruiker kunnen doen?
|
||||
```
|
||||
|
||||
**Stap 3: Prioriteer (MVP denken)**
|
||||
- Wat is essentieel? → In prototype
|
||||
- Wat is nice-to-have? → Later
|
||||
|
||||
---
|
||||
|
||||
### Eindproject Aanmaken
|
||||
### Component Thinking
|
||||
|
||||
```bash
|
||||
# Kies een goede naam voor je project
|
||||
npx create-next-app@latest ai-recipe-generator
|
||||
# of: smart-budget-buddy
|
||||
# of: travel-planner-ai
|
||||
# of: jouw-eigen-idee
|
||||
**Vraag jezelf af:**
|
||||
- Welke "blokken" zie ik op het scherm?
|
||||
- Welke blokken worden herhaald?
|
||||
- Welke blokken komen op meerdere pagina's?
|
||||
|
||||
# Beantwoord de vragen:
|
||||
# ✔ Would you like to use TypeScript? → Yes
|
||||
# ✔ Would you like to use ESLint? → Yes
|
||||
# ✔ Would you like to use Tailwind CSS? → Yes
|
||||
# ✔ Would you like to use `src/` directory? → Yes
|
||||
# ✔ Would you like to use App Router? → Yes
|
||||
# ✔ Would you like to customize the default import alias? → No
|
||||
**Voorbeeld: Plant Tracker**
|
||||
```
|
||||
Herhaalde componenten:
|
||||
- PlantCard (naam, foto, laatste water datum)
|
||||
- WaterButton (markeer als water gegeven)
|
||||
|
||||
cd ai-recipe-generator
|
||||
Pagina componenten:
|
||||
- PlantList (toont alle PlantCards)
|
||||
- AddPlantForm (nieuw plant toevoegen)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### De Ideale Folder Structuur
|
||||
### MVP (Minimum Viable Product) Denken
|
||||
|
||||
**Wat is MVP?**
|
||||
De simpelste versie van je app die nog steeds waarde levert.
|
||||
|
||||
**❌ Niet MVP:**
|
||||
- Alle features tegelijk
|
||||
- Perfect design
|
||||
- Edge cases afhandelen
|
||||
- Login systeem
|
||||
|
||||
**✅ Wel MVP:**
|
||||
- Core functionaliteit werkt
|
||||
- Basis styling
|
||||
- Happy path werkt
|
||||
- Hardcoded data is oké
|
||||
|
||||
---
|
||||
|
||||
### De Prototype Workflow
|
||||
|
||||
```
|
||||
ai-recipe-generator/
|
||||
├── .cursor/
|
||||
│ └── rules/
|
||||
│ └── general.mdc # Cursor instructies
|
||||
├── docs/
|
||||
│ ├── PROJECT-BRIEF.md # Project beschrijving
|
||||
│ ├── PROMPT-LOG.md # AI prompts logboek
|
||||
│ └── AI-DECISIONS.md # Architectuur beslissingen
|
||||
├── src/
|
||||
│ ├── app/
|
||||
│ │ ├── api/ # API routes (voor AI)
|
||||
│ │ ├── layout.tsx
|
||||
│ │ └── page.tsx
|
||||
│ ├── components/
|
||||
│ │ ├── ui/ # Herbruikbare UI components
|
||||
│ │ └── features/ # Feature-specifieke components
|
||||
│ ├── lib/
|
||||
│ │ └── supabase.ts # Supabase client
|
||||
│ └── types/
|
||||
│ └── index.ts # TypeScript types
|
||||
├── .env.example # Template voor env vars
|
||||
├── .env.local # Echte env vars (niet committen!)
|
||||
├── .gitignore
|
||||
└── README.md
|
||||
```
|
||||
|
||||
**Maak de folders aan:**
|
||||
```bash
|
||||
mkdir -p .cursor/rules
|
||||
mkdir -p docs
|
||||
mkdir -p src/components/ui
|
||||
mkdir -p src/components/features
|
||||
mkdir -p src/lib
|
||||
mkdir -p src/types
|
||||
1. IDEE (1-2 zinnen)
|
||||
↓
|
||||
2. FEATURES (AI breakdown)
|
||||
↓
|
||||
3. PRIORITEER (wat is MVP?)
|
||||
↓
|
||||
4. COMPONENTS (welke blokken?)
|
||||
↓
|
||||
5. BOUWEN (tool per stap)
|
||||
↓
|
||||
6. ITEREREN (feedback → aanpassen)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### .cursorrules Files
|
||||
### Voorbeeld: Weer Widget Prototype
|
||||
|
||||
**.cursor/rules/general.mdc:**
|
||||
```markdown
|
||||
# Project: AI Recipe Generator
|
||||
**Stap 1: Idee**
|
||||
"Simpele weer widget met 3-daagse forecast"
|
||||
|
||||
## Tech Stack
|
||||
- Next.js 14 met App Router
|
||||
- TypeScript (strict mode)
|
||||
- Tailwind CSS voor styling
|
||||
- Supabase voor database en auth
|
||||
- Vercel AI SDK voor chat features
|
||||
|
||||
## Code Conventies
|
||||
- Gebruik functionele React components
|
||||
- Gebruik named exports (geen default exports)
|
||||
- Destructure props in function signature
|
||||
- Gebruik async/await (geen .then() chains)
|
||||
- Schrijf TypeScript types voor alle props en data
|
||||
|
||||
## File Naming
|
||||
- Components: PascalCase (Button.tsx, RecipeCard.tsx)
|
||||
- Utilities: camelCase (formatDate.ts, fetchRecipes.ts)
|
||||
- Types: PascalCase met 'Type' suffix (RecipeType.ts)
|
||||
|
||||
## Styling
|
||||
- Alleen Tailwind classes, geen inline styles
|
||||
- Mobile-first approach
|
||||
- Gebruik consistent spacing (4, 8, 16, 24, 32)
|
||||
|
||||
## Supabase
|
||||
- Client in src/lib/supabase.ts
|
||||
- Gebruik typed queries waar mogelijk
|
||||
- Handle errors expliciet
|
||||
|
||||
## AI Features
|
||||
- API routes in src/app/api/
|
||||
- Gebruik Vercel AI SDK useChat hook
|
||||
- Stream responses voor betere UX
|
||||
**Stap 2: AI Feature Breakdown**
|
||||
```
|
||||
Vraag aan ChatGPT:
|
||||
"Wat zijn de minimale features voor een weer widget met 3-daagse forecast?"
|
||||
|
||||
Antwoord:
|
||||
- Huidige temperatuur tonen
|
||||
- Weer icoon (zon, regen, etc.)
|
||||
- 3-daagse forecast (dag + temp + icoon)
|
||||
- Locatie tonen
|
||||
```
|
||||
|
||||
**Stap 3: MVP Selectie**
|
||||
- ✅ Huidige temperatuur
|
||||
- ✅ Weer icoon
|
||||
- ✅ 3 dagen forecast
|
||||
- ❌ Locatie selectie (later)
|
||||
- ❌ Animated icons (later)
|
||||
|
||||
**Stap 4: Components**
|
||||
```
|
||||
WeatherWidget/
|
||||
├── CurrentWeather (temp + icoon)
|
||||
├── ForecastDay (dag + temp + icoon)
|
||||
└── ForecastList (3x ForecastDay)
|
||||
```
|
||||
|
||||
**Stap 5: Bouwen**
|
||||
1. v0.dev: "Weather widget with current temp and 3 day forecast, minimal design"
|
||||
2. OpenCode: "Integreer dit in mijn project, maak components in src/components/weather/"
|
||||
|
||||
**Stap 6: Itereren**
|
||||
- Wat werkt niet?
|
||||
- Wat kan beter?
|
||||
- Vraag AI om verbeteringen
|
||||
|
||||
---
|
||||
|
||||
### docs/ Folder
|
||||
### Mini-Project Ideeën
|
||||
|
||||
#### docs/PROJECT-BRIEF.md
|
||||
```markdown
|
||||
# Project Brief: AI Recipe Generator
|
||||
|
||||
## Projectnaam
|
||||
AI Recipe Generator
|
||||
|
||||
## Tagline
|
||||
"Ontdek recepten op basis van wat je in huis hebt"
|
||||
|
||||
## Probleem
|
||||
Mensen hebben vaak ingrediënten in huis maar weten niet wat ze
|
||||
ermee kunnen maken. Ze verspillen voedsel of bestellen onnodig.
|
||||
|
||||
## Oplossing
|
||||
Een app waar je ingrediënten invoert en AI receptsuggesties genereert.
|
||||
Je kunt chatten met de AI voor variaties en tips.
|
||||
|
||||
## Doelgroep
|
||||
- Studenten met beperkt budget
|
||||
- Thuiskoks die inspiratie zoeken
|
||||
- Mensen die voedselverspilling willen verminderen
|
||||
|
||||
## Core Features
|
||||
1. Ingrediënten invoeren
|
||||
2. AI genereert recepten op basis van ingrediënten
|
||||
3. Chat interface voor follow-up vragen
|
||||
4. Recepten opslaan als favoriet
|
||||
5. Login om favorieten te bewaren
|
||||
|
||||
## Nice-to-have Features
|
||||
- Dieetwensen (vegetarisch, glutenvrij, etc.)
|
||||
- Boodschappenlijst genereren
|
||||
- Recept delen
|
||||
|
||||
## Tech Stack
|
||||
- Frontend: Next.js, TypeScript, Tailwind CSS
|
||||
- Backend: Supabase (database, auth)
|
||||
- AI: Vercel AI SDK met OpenAI
|
||||
- Deployment: Vercel
|
||||
```
|
||||
|
||||
#### docs/PROMPT-LOG.md
|
||||
```markdown
|
||||
# Prompt Log
|
||||
|
||||
Dit document bevat de belangrijkste prompts die ik heb gebruikt.
|
||||
|
||||
## Template per prompt:
|
||||
|
||||
### [Datum] - [Onderwerp]
|
||||
**Doel:** Wat wilde ik bereiken?
|
||||
**Prompt:**
|
||||
\`\`\`
|
||||
De exacte prompt die ik gebruikte
|
||||
\`\`\`
|
||||
**Resultaat:** Wat was het resultaat? Werkte het?
|
||||
**Geleerd:** Wat heb ik hiervan geleerd?
|
||||
|
||||
---
|
||||
|
||||
## Prompts
|
||||
|
||||
### [Datum] - Project Setup
|
||||
**Doel:** Basis project structuur opzetten
|
||||
**Prompt:**
|
||||
\`\`\`
|
||||
[Nog in te vullen tijdens development]
|
||||
\`\`\`
|
||||
**Resultaat:**
|
||||
**Geleerd:**
|
||||
|
||||
---
|
||||
|
||||
(Voeg minimaal 10 prompts toe tijdens je project)
|
||||
```
|
||||
|
||||
#### docs/AI-DECISIONS.md
|
||||
```markdown
|
||||
# AI Decisions Log
|
||||
|
||||
Dit document bevat architectuur- en designbeslissingen gemaakt met AI hulp.
|
||||
|
||||
## Template per beslissing:
|
||||
|
||||
### [Datum] - [Beslissing titel]
|
||||
**Context:** Wat was de situatie?
|
||||
**Vraag aan AI:** Wat heb ik gevraagd?
|
||||
**Opties:** Welke opties werden voorgesteld?
|
||||
**Keuze:** Wat heb ik gekozen en waarom?
|
||||
**Trade-offs:** Wat zijn de voor- en nadelen?
|
||||
|
||||
---
|
||||
|
||||
## Beslissingen
|
||||
|
||||
### [Datum] - Database Schema
|
||||
**Context:** Ik moet bepalen hoe ik recepten opsla.
|
||||
**Vraag aan AI:** "Wat is een goede database structuur voor een recept app?"
|
||||
**Opties:**
|
||||
1. Één tabel met JSON voor ingrediënten
|
||||
2. Genormaliseerde tabellen (recipes, ingredients, recipe_ingredients)
|
||||
**Keuze:** Optie 1 - één tabel met JSON
|
||||
**Trade-offs:**
|
||||
- Pro: Simpeler, sneller te implementeren
|
||||
- Con: Minder flexibel voor complexe queries
|
||||
|
||||
---
|
||||
|
||||
(Voeg minimaal 5 beslissingen toe tijdens je project)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Environment Variables
|
||||
|
||||
**.env.example (WEL committen):**
|
||||
```bash
|
||||
# Supabase
|
||||
NEXT_PUBLIC_SUPABASE_URL=your-supabase-url
|
||||
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
|
||||
|
||||
# OpenAI (voor Vercel AI SDK)
|
||||
OPENAI_API_KEY=your-openai-key
|
||||
```
|
||||
|
||||
**.env.local (NIET committen):**
|
||||
```bash
|
||||
# Supabase
|
||||
NEXT_PUBLIC_SUPABASE_URL=https://xxxxx.supabase.co
|
||||
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.xxxxx
|
||||
|
||||
# OpenAI
|
||||
OPENAI_API_KEY=sk-xxxxx
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### README.md Best Practices
|
||||
|
||||
```markdown
|
||||
# AI Recipe Generator
|
||||
|
||||
Ontdek recepten op basis van wat je in huis hebt.
|
||||
|
||||
## Features
|
||||
- Voer ingrediënten in die je hebt
|
||||
- AI genereert receptsuggesties
|
||||
- Chat voor follow-up vragen
|
||||
- Sla favoriete recepten op
|
||||
|
||||
## Tech Stack
|
||||
- Next.js 14 (App Router)
|
||||
- TypeScript
|
||||
- Tailwind CSS
|
||||
- Supabase
|
||||
- Vercel AI SDK
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Prerequisites
|
||||
- Node.js 18+
|
||||
- npm of yarn
|
||||
- Supabase account
|
||||
- OpenAI API key
|
||||
|
||||
### Installation
|
||||
|
||||
1. Clone de repository:
|
||||
\`\`\`bash
|
||||
git clone https://github.com/jouw-username/ai-recipe-generator.git
|
||||
cd ai-recipe-generator
|
||||
\`\`\`
|
||||
|
||||
2. Installeer dependencies:
|
||||
\`\`\`bash
|
||||
npm install
|
||||
\`\`\`
|
||||
|
||||
3. Kopieer environment variables:
|
||||
\`\`\`bash
|
||||
cp .env.example .env.local
|
||||
\`\`\`
|
||||
|
||||
4. Vul je credentials in `.env.local`
|
||||
|
||||
5. Start development server:
|
||||
\`\`\`bash
|
||||
npm run dev
|
||||
\`\`\`
|
||||
|
||||
6. Open [http://localhost:3000](http://localhost:3000)
|
||||
|
||||
## Scripts
|
||||
- `npm run dev` - Start development server
|
||||
- `npm run build` - Build voor productie
|
||||
- `npm run lint` - Run ESLint
|
||||
|
||||
## Deployment
|
||||
Deze app is gedeployed op Vercel: [link naar productie]
|
||||
|
||||
## Author
|
||||
[Jouw naam]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### GitHub Repository Aanmaken
|
||||
|
||||
```bash
|
||||
# Initialiseer Git (als dat nog niet is gebeurd)
|
||||
git init
|
||||
|
||||
# Maak eerste commit
|
||||
git add .
|
||||
git commit -m "Initial Next.js setup with project structure"
|
||||
|
||||
# Maak repository op GitHub.com, dan:
|
||||
git remote add origin https://github.com/jouw-username/ai-recipe-generator.git
|
||||
git branch -M main
|
||||
git push -u origin main
|
||||
```
|
||||
| Project | Core Feature | Complexiteit |
|
||||
|---------|-------------|--------------|
|
||||
| **Weer Widget** | 3-daagse forecast | ⭐ |
|
||||
| **Quiz App** | 3 vragen + score | ⭐ |
|
||||
| **Recipe Card** | Ingrediënten toggle | ⭐ |
|
||||
| **Pomodoro Timer** | Start/stop + countdown | ⭐⭐ |
|
||||
| **Expense Tracker** | Lijst + totaal | ⭐⭐ |
|
||||
|
||||
---
|
||||
|
||||
## Tools
|
||||
- Next.js
|
||||
- Cursor
|
||||
- Git & GitHub
|
||||
- Supabase
|
||||
- ChatGPT (voor planning)
|
||||
- v0.dev (voor prototypes)
|
||||
- OpenCode/WebStorm (voor implementation)
|
||||
|
||||
---
|
||||
|
||||
## Lesopdracht (2 uur)
|
||||
|
||||
### Richt je Eindproject Repository In
|
||||
### Bouw Je Mini-Prototype
|
||||
|
||||
**Deel 1: Project Aanmaken (20 min)**
|
||||
- Kies je eindproject (Recipe Generator / Budget Buddy / Travel Planner / eigen idee)
|
||||
- Run `npx create-next-app@latest [project-naam]`
|
||||
- Open in Cursor
|
||||
**Groepsdiscussie (15 min):**
|
||||
Bespreek klassikaal de Tool Selection reflecties uit Les 10 - welke workflows werken het beste?
|
||||
|
||||
**Deel 2: Folder Structuur (20 min)**
|
||||
- Maak alle folders aan volgens de structuur
|
||||
- Maak alle bestanden aan
|
||||
- Test: folder structuur is compleet
|
||||
**Deel 1: Planning (30 min)**
|
||||
|
||||
**Deel 3: .cursorrules (30 min)**
|
||||
- Schrijf `general.mdc` met jouw project details
|
||||
- Pas de tech stack, conventies, en styling regels aan
|
||||
- Test: open een file en vraag Cursor iets - volgt hij je regels?
|
||||
1. Kies een project uit de lijst (of bedenk eigen simpel idee)
|
||||
2. Schrijf je idee in 1-2 zinnen
|
||||
3. Vraag ChatGPT om feature breakdown
|
||||
4. Selecteer MVP features (max 3)
|
||||
5. Schets de components op papier
|
||||
|
||||
**Deel 4: Documentatie (30 min)**
|
||||
- Vul PROJECT-BRIEF.md volledig in
|
||||
- Maak templates klaar in PROMPT-LOG.md en AI-DECISIONS.md
|
||||
- Schrijf complete README.md
|
||||
**Deel 2: Bouwen (1 uur)**
|
||||
|
||||
**Deel 5: Git (20 min)**
|
||||
- Initialiseer Git
|
||||
- Maak GitHub repository
|
||||
- Push alles
|
||||
1. Genereer UI in v0.dev
|
||||
2. Open project in OpenCode
|
||||
3. Integreer en pas aan
|
||||
4. Zorg dat het werkt (happy path)
|
||||
|
||||
**Focus op WORKFLOW, niet perfectie!**
|
||||
|
||||
**Deel 3: Documentatie (15 min)**
|
||||
|
||||
Maak `docs/PROTOTYPE-LOG.md`:
|
||||
- Je idee
|
||||
- Feature breakdown
|
||||
- MVP keuzes
|
||||
- Prompts die werkten
|
||||
- Wat ging fout en hoe opgelost
|
||||
|
||||
### Deliverable
|
||||
- GitHub repository URL
|
||||
- Volledig ingevulde PROJECT-BRIEF.md
|
||||
- Werkende .cursorrules file
|
||||
- Screenshot van Cursor die je regels volgt
|
||||
- Werkend prototype (kan simpel zijn)
|
||||
- `docs/PROTOTYPE-LOG.md` met je proces
|
||||
- Screenshot van werkend prototype
|
||||
|
||||
---
|
||||
|
||||
## Huiswerk (2 uur)
|
||||
|
||||
### Verfijn Setup & Start Bouwen
|
||||
### Verbeter en Reflecteer
|
||||
|
||||
**Deel 1: Extra .cursorrules (30 min)**
|
||||
- Maak `components.mdc` met component conventies
|
||||
- Maak `api.mdc` met API route conventies
|
||||
- Test beide in Cursor
|
||||
**Deel 1: Prototype Verbeteren (1 uur)**
|
||||
|
||||
**Deel 2: Basis Components (1 uur)**
|
||||
Maak 3-5 basis UI components in `src/components/ui/`:
|
||||
- Button.tsx
|
||||
- Card.tsx
|
||||
- Input.tsx
|
||||
- (optioneel: Modal.tsx, Toast.tsx)
|
||||
1. Fix eventuele bugs
|
||||
2. Voeg 1 extra feature toe
|
||||
3. Verbeter styling
|
||||
4. Handle 1 edge case
|
||||
|
||||
Gebruik Cursor met je .cursorrules!
|
||||
Log effectieve prompts in PROMPT-LOG.md
|
||||
**Deel 2: Peer Review (30 min)**
|
||||
|
||||
**Deel 3: Supabase Setup (30 min)**
|
||||
- Maak nieuw Supabase project voor eindopdracht
|
||||
- Configureer `.env.local` en `.env.example`
|
||||
- Bespreek met AI welke tabellen je nodig hebt
|
||||
- Maak eerste tabel aan
|
||||
- Documenteer in AI-DECISIONS.md
|
||||
- Deel je prototype met een klasgenoot
|
||||
- Krijg feedback
|
||||
- Geef feedback op hun prototype
|
||||
|
||||
**Deel 3: Reflectie (30 min)**
|
||||
|
||||
Schrijf "Lessons Learned" document (300 woorden):
|
||||
- Wat ging goed in je workflow?
|
||||
- Waar liep je vast?
|
||||
- Welke tool was het meest nuttig?
|
||||
- Wat doe je volgende keer anders?
|
||||
- Hoe voelde het om met AI te bouwen vs alleen?
|
||||
|
||||
### Deliverable
|
||||
- Minimaal 2 .cursorrules files
|
||||
- Minimaal 3 UI components
|
||||
- Supabase project gekoppeld
|
||||
- Eerste entries in PROMPT-LOG.md en AI-DECISIONS.md
|
||||
- Verbeterd prototype
|
||||
- Peer review feedback (gegeven en ontvangen)
|
||||
- Lessons Learned document (300 woorden)
|
||||
|
||||
---
|
||||
|
||||
## Leerdoelen
|
||||
Na deze les kan de student:
|
||||
- Een professionele project structuur opzetten
|
||||
- .cursorrules files schrijven die Cursor instrueren
|
||||
- Documentatie files aanmaken (PROJECT-BRIEF, PROMPT-LOG, AI-DECISIONS)
|
||||
- Environment variables correct beheren
|
||||
- Een GitHub repository aanmaken en pushen
|
||||
- De basis leggen voor AI-assisted development met goede context
|
||||
- Van een vaag idee naar concrete features gaan
|
||||
- AI gebruiken voor feature breakdown
|
||||
- MVP denken toepassen (essentieel vs nice-to-have)
|
||||
- Een app opdelen in components
|
||||
- De complete workflow doorlopen (idee → prototype)
|
||||
- Het bouwproces documenteren
|
||||
- Reflecteren op wat werkt en wat niet
|
||||
|
||||
@@ -1,363 +1,261 @@
|
||||
# Les 12: MCP & Context Management
|
||||
# Les 12: Introduction to Cursor
|
||||
|
||||
---
|
||||
|
||||
## Hoofdstuk
|
||||
**Hoofdstuk 3: Advanced** (Les 10-18)
|
||||
**Deel 3: AI Tooling & Prototyping** (Les 10-12)
|
||||
|
||||
## Beschrijving
|
||||
Leer over MCP (Model Context Protocol) en hoe je context effectief beheert voor betere AI-assisted development.
|
||||
Kennismaking met Cursor - de professionele AI code editor. Leer de core features en ontdek waarom dit de tool is voor serieuze AI-assisted development.
|
||||
|
||||
---
|
||||
|
||||
## Te Behandelen
|
||||
|
||||
### Wat is MCP?
|
||||
### Groepsdiscussie (15 min)
|
||||
Bespreek klassikaal de prototype ervaringen uit Les 11 - welke workflow patterns werkten goed? Wat ging fout en hoe loste je dat op?
|
||||
|
||||
**MCP = Model Context Protocol**
|
||||
### Waarom Cursor?
|
||||
|
||||
Een protocol van Anthropic waarmee AI tools veilig kunnen verbinden met externe data bronnen.
|
||||
**Tot nu toe gebruikten we:**
|
||||
- OpenCode (gratis, goed voor leren)
|
||||
- Claude Desktop (voor agents en projects)
|
||||
|
||||
**Zonder MCP:**
|
||||
- Je kopieert handmatig data naar Claude
|
||||
- Context gaat verloren tussen sessies
|
||||
- Geen toegang tot live data
|
||||
|
||||
**Met MCP:**
|
||||
- Claude kan direct je files lezen
|
||||
- Toegang tot databases, APIs, GitHub
|
||||
- Real-time data in je conversations
|
||||
**Cursor is de volgende stap:**
|
||||
- Purpose-built voor AI-assisted coding
|
||||
- Professionele editor (gebaseerd op VS Code)
|
||||
- Superieure AI integratie
|
||||
- Free tier beschikbaar (voldoende voor de cursus)
|
||||
|
||||
---
|
||||
|
||||
### MCP Servers
|
||||
### Free vs Pro
|
||||
|
||||
MCP werkt met "servers" - kleine programma's die specifieke data bronnen ontsluiten.
|
||||
| Aspect | Free Tier | Pro ($20/maand) |
|
||||
|--------|-----------|-----------------|
|
||||
| Tab completion | ✅ | ✅ |
|
||||
| CMD+K edits | Beperkt | Onbeperkt |
|
||||
| Chat | Beperkt | Onbeperkt |
|
||||
| Composer | Beperkt | Onbeperkt |
|
||||
| Models | GPT-4, Claude | Alle modellen |
|
||||
|
||||
**Populaire MCP Servers:**
|
||||
|
||||
| Server | Wat het doet |
|
||||
|--------|--------------|
|
||||
| **filesystem** | Lees/schrijf lokale files |
|
||||
| **github** | Toegang tot repos, issues, PRs |
|
||||
| **postgres** | Direct database queries |
|
||||
| **slack** | Berichten en channels |
|
||||
| **brave-search** | Web zoeken |
|
||||
**Voor deze cursus:** Free tier is voldoende!
|
||||
|
||||
---
|
||||
|
||||
### Claude Desktop + MCP Configureren
|
||||
### Installatie
|
||||
|
||||
**Stap 1:** Open Claude Desktop settings
|
||||
1. Ga naar [cursor.sh](https://cursor.sh)
|
||||
2. Download voor jouw OS
|
||||
3. Installeer
|
||||
4. Open Cursor
|
||||
5. Sign in met GitHub
|
||||
|
||||
**Stap 2:** Ga naar "Developer" → "Edit Config"
|
||||
|
||||
**Stap 3:** Voeg MCP servers toe in `claude_desktop_config.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"filesystem": {
|
||||
"command": "npx",
|
||||
"args": [
|
||||
"-y",
|
||||
"@modelcontextprotocol/server-filesystem",
|
||||
"/Users/jouw-username/projects/ai-recipe-generator"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Stap 4:** Herstart Claude Desktop
|
||||
|
||||
**Stap 5:** Je ziet nu een 🔧 icoon in Claude - dit toont actieve MCP servers
|
||||
**Eerste keer:**
|
||||
- Cursor vraagt om settings te importeren van VS Code (optioneel)
|
||||
- Accept default keybindings
|
||||
|
||||
---
|
||||
|
||||
### Filesystem MCP Testen
|
||||
### Core Features
|
||||
|
||||
Met filesystem MCP kan Claude:
|
||||
- Je project files lezen
|
||||
- File structuur bekijken
|
||||
- Code analyseren
|
||||
#### 1. Tab Completion
|
||||
AI-powered autocomplete die hele blokken code voorspelt.
|
||||
|
||||
**Test prompt:**
|
||||
```
|
||||
Analyseer mijn project structuur en geef me een overzicht
|
||||
van de belangrijkste files en hun functies.
|
||||
**Hoe het werkt:**
|
||||
- Begin met typen
|
||||
- Cursor suggereert code in grijs
|
||||
- Druk Tab om te accepteren
|
||||
- Druk Escape om te negeren
|
||||
|
||||
**Tip:** Schrijf een comment over wat je wilt, en Tab completion vult de code in.
|
||||
|
||||
```typescript
|
||||
// Function that calculates the total price with tax
|
||||
// [Tab completion vult de functie in]
|
||||
```
|
||||
|
||||
Claude kan nu direct je files lezen zonder dat je ze kopieert!
|
||||
#### 2. CMD+K (Inline Editing)
|
||||
Selecteer code en vraag AI om het aan te passen.
|
||||
|
||||
**Hoe het werkt:**
|
||||
1. Selecteer code (of zet cursor op een regel)
|
||||
2. Druk CMD+K (Mac) of Ctrl+K (Windows)
|
||||
3. Typ je instructie
|
||||
4. Enter om te genereren
|
||||
5. Accept of Reject de wijziging
|
||||
|
||||
**Voorbeelden:**
|
||||
- "Add error handling"
|
||||
- "Convert to TypeScript"
|
||||
- "Make this responsive"
|
||||
- "Add loading state"
|
||||
|
||||
#### 3. Chat (Sidebar)
|
||||
Converseer met AI over je code.
|
||||
|
||||
**Hoe het werkt:**
|
||||
1. CMD+Shift+L opent Chat
|
||||
2. Stel je vraag
|
||||
3. AI heeft context van je open file
|
||||
|
||||
**Voorbeelden:**
|
||||
- "Explain what this function does"
|
||||
- "How can I optimize this?"
|
||||
- "What's wrong with this code?"
|
||||
|
||||
#### 4. @ Mentions
|
||||
Refereer naar files, folders, of documentatie.
|
||||
|
||||
**Syntax:**
|
||||
- `@filename.tsx` - specifieke file
|
||||
- `@folder/` - hele folder
|
||||
- `@Docs` - officiële docs zoeken
|
||||
- `@Web` - web zoeken
|
||||
|
||||
**Voorbeeld:**
|
||||
```
|
||||
@components/Button.tsx - How can I add a loading prop to this?
|
||||
```
|
||||
|
||||
#### 5. Composer Mode
|
||||
Multi-file generatie in één keer.
|
||||
|
||||
**Hoe het werkt:**
|
||||
1. CMD+I opent Composer
|
||||
2. Beschrijf wat je wilt bouwen
|
||||
3. AI genereert meerdere files tegelijk
|
||||
4. Review en accept changes
|
||||
|
||||
**Wanneer gebruiken:**
|
||||
- Nieuwe features met meerdere components
|
||||
- Refactoring over meerdere files
|
||||
- Boilerplate code genereren
|
||||
|
||||
---
|
||||
|
||||
### GitHub MCP
|
||||
### Workflow Vergelijking
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"github": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@modelcontextprotocol/server-github"],
|
||||
"env": {
|
||||
"GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_xxxxx"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Wat kun je doen:**
|
||||
- "Toon mijn open issues"
|
||||
- "Maak een nieuwe branch"
|
||||
- "Wat zijn de recente commits?"
|
||||
| Taak | OpenCode | Cursor |
|
||||
|------|----------|--------|
|
||||
| Snelle fix | Chat | CMD+K |
|
||||
| Nieuwe component | Chat | Tab completion + CMD+K |
|
||||
| Multi-file feature | Meerdere chats | Composer |
|
||||
| Code uitleg | Chat | Chat + @ mentions |
|
||||
| Refactoring | Chat | CMD+K of Composer |
|
||||
|
||||
---
|
||||
|
||||
## Context Management
|
||||
### Keyboard Shortcuts Cheat Sheet
|
||||
|
||||
### Wat is Context?
|
||||
|
||||
**Context = alle informatie die AI heeft tijdens een conversatie**
|
||||
|
||||
- Je vraag
|
||||
- Eerdere berichten
|
||||
- Geüploade files
|
||||
- MCP data
|
||||
|
||||
**Beperking:** AI heeft een "context window" - maximale hoeveelheid tokens.
|
||||
|
||||
| Model | Context Window |
|
||||
|-------|----------------|
|
||||
| GPT-4 | ~128K tokens |
|
||||
| Claude 3.5 | ~200K tokens |
|
||||
| Claude 3 Opus | ~200K tokens |
|
||||
|
||||
**1 token ≈ 4 karakters** (of ~¾ woord)
|
||||
|
||||
---
|
||||
|
||||
### Waarom Context Belangrijk Is
|
||||
|
||||
**Meer context = beter begrip**
|
||||
|
||||
Met context over je project kan AI:
|
||||
- Consistente code genereren
|
||||
- Bestaande patterns volgen
|
||||
- Juiste imports gebruiken
|
||||
|
||||
**Te veel context = problemen**
|
||||
- Langzamere responses
|
||||
- Hogere kosten
|
||||
- AI raakt "afgeleid"
|
||||
|
||||
---
|
||||
|
||||
### Context Strategieën
|
||||
|
||||
**1. Start Breed, Narrow Down**
|
||||
```
|
||||
Begin: "Bekijk mijn hele project structuur"
|
||||
Dan: "Focus op de components folder"
|
||||
Dan: "Specifiek TodoList.tsx"
|
||||
```
|
||||
|
||||
**2. Alleen Relevante Files**
|
||||
- Niet je hele codebase delen
|
||||
- Focus op files die relevant zijn voor de taak
|
||||
|
||||
**3. @ Mentions in Cursor**
|
||||
```
|
||||
@components/Button.tsx @lib/utils.ts
|
||||
Hoe kan ik een loading state toevoegen aan de Button?
|
||||
```
|
||||
|
||||
**4. Fresh Start bij Nieuwe Taken**
|
||||
- Nieuwe chat voor nieuwe onderwerpen
|
||||
- Voorkomt context pollution
|
||||
|
||||
---
|
||||
|
||||
### .cursorignore
|
||||
|
||||
Net als .gitignore, maar voor Cursor's AI indexing.
|
||||
|
||||
**Maak `.cursorignore` in je project root:**
|
||||
```
|
||||
# Dependencies
|
||||
node_modules/
|
||||
|
||||
# Build outputs
|
||||
.next/
|
||||
dist/
|
||||
build/
|
||||
|
||||
# Large files
|
||||
*.log
|
||||
*.lock
|
||||
|
||||
# Sensitive
|
||||
.env.local
|
||||
```
|
||||
|
||||
**Waarom:**
|
||||
- Snellere indexing
|
||||
- Geen irrelevante suggestions
|
||||
- Betere focus op je code
|
||||
|
||||
---
|
||||
|
||||
### Context Optimalisatie Checklist
|
||||
|
||||
✅ **Goede project documentatie**
|
||||
- README met overview
|
||||
- Duidelijke folder structuur
|
||||
- Comments in complexe code
|
||||
|
||||
✅ **Semantische naming**
|
||||
- `fetchUserData()` niet `getData()`
|
||||
- `UserProfileCard.tsx` niet `Card1.tsx`
|
||||
|
||||
✅ **Kleine, focused files**
|
||||
- Max ~300 regels per file
|
||||
- Eén verantwoordelijkheid per file
|
||||
|
||||
✅ **Proper imports**
|
||||
- Absolute imports (`@/components/...`)
|
||||
- Georganiseerde imports
|
||||
|
||||
---
|
||||
|
||||
### Context in Cursor vs Claude Desktop
|
||||
|
||||
| Aspect | Cursor | Claude Desktop + MCP |
|
||||
|--------|--------|---------------------|
|
||||
| Automatische context | Open files | MCP servers |
|
||||
| File access | @ mentions | Filesystem MCP |
|
||||
| Project begrip | .cursorrules | Project Knowledge |
|
||||
| Beste voor | Coding | Research, planning |
|
||||
|
||||
**Combineer ze:**
|
||||
- Claude Desktop + MCP voor planning en grote analyses
|
||||
- Cursor voor daadwerkelijk coderen
|
||||
| Actie | Mac | Windows |
|
||||
|-------|-----|---------|
|
||||
| Tab completion accept | Tab | Tab |
|
||||
| Inline edit | CMD+K | Ctrl+K |
|
||||
| Open Chat | CMD+Shift+L | Ctrl+Shift+L |
|
||||
| Open Composer | CMD+I | Ctrl+I |
|
||||
| Accept suggestion | CMD+Y | Ctrl+Y |
|
||||
| Reject suggestion | CMD+N | Ctrl+N |
|
||||
|
||||
---
|
||||
|
||||
## Tools
|
||||
- Claude Desktop
|
||||
- MCP servers
|
||||
- Cursor
|
||||
- .cursorignore
|
||||
- GitHub
|
||||
|
||||
---
|
||||
|
||||
## Lesopdracht (2 uur)
|
||||
|
||||
### MCP Setup & Context Optimalisatie
|
||||
### Cursor Verkennen
|
||||
|
||||
**Deel 1: Claude Desktop MCP Setup (45 min)**
|
||||
**Deel 1: Setup (20 min)**
|
||||
|
||||
1. Open Claude Desktop settings
|
||||
2. Configureer filesystem MCP voor je eindproject folder
|
||||
3. Herstart Claude Desktop
|
||||
4. Verifieer: vraag Claude om je project te analyseren
|
||||
1. Download en installeer Cursor
|
||||
2. Sign in met GitHub
|
||||
3. Open je Todo app project
|
||||
4. Verken de interface
|
||||
|
||||
Test prompts:
|
||||
- "Wat is de structuur van mijn project?"
|
||||
- "Welke dependencies gebruik ik?"
|
||||
- "Analyseer mijn TodoList component"
|
||||
**Deel 2: Tab Completion (30 min)**
|
||||
|
||||
**Deel 2: GitHub MCP (optioneel) (30 min)**
|
||||
Maak nieuwe file `src/components/LoadingSpinner.tsx`:
|
||||
1. Typ comment: `// Loading spinner component with size prop`
|
||||
2. Laat Tab completion de rest doen
|
||||
3. Itereer met meer comments
|
||||
4. Noteer: hoe goed is de completion?
|
||||
|
||||
1. Maak GitHub Personal Access Token
|
||||
2. Configureer GitHub MCP
|
||||
3. Test met je eindproject repo
|
||||
**Deel 3: CMD+K Oefenen (30 min)**
|
||||
|
||||
Test prompts:
|
||||
- "Toon mijn recente commits"
|
||||
- "Wat zijn mijn open issues?"
|
||||
Open je TodoList component:
|
||||
1. Selecteer de list rendering code
|
||||
2. CMD+K → "Add loading state with skeleton"
|
||||
3. Selecteer een button
|
||||
4. CMD+K → "Add disabled state while loading"
|
||||
5. Selecteer een function
|
||||
6. CMD+K → "Add try-catch with error toast"
|
||||
|
||||
**Deel 3: Context Optimalisatie (45 min)**
|
||||
Noteer wat werkt en wat niet.
|
||||
|
||||
1. Maak `.cursorignore` voor je project
|
||||
2. Voeg node_modules, .next, etc. toe
|
||||
3. Herindexeer project in Cursor
|
||||
**Deel 4: Chat + @ Mentions (20 min)**
|
||||
|
||||
4. Test context kwaliteit:
|
||||
- Vraag Cursor iets over je project
|
||||
- Zijn de antwoorden accuraat?
|
||||
- Gebruikt hij de juiste patterns?
|
||||
1. Open Chat (CMD+Shift+L)
|
||||
2. Vraag: "@TodoList.tsx What could I improve in this component?"
|
||||
3. Vraag: "@lib/supabase.ts How do I add real-time subscriptions?"
|
||||
4. Probeer @Docs voor Next.js documentatie
|
||||
|
||||
5. Verbeter indien nodig:
|
||||
- Voeg comments toe aan complexe code
|
||||
- Verbeter naming
|
||||
- Split grote files
|
||||
**Deel 5: Composer Proberen (20 min)**
|
||||
|
||||
1. Open Composer (CMD+I)
|
||||
2. Vraag: "Create a Settings page with dark mode toggle and notification preferences. Use our existing component style."
|
||||
3. Review de gegenereerde files
|
||||
4. Accept of reject
|
||||
|
||||
### Deliverable
|
||||
- Werkende MCP configuratie (screenshot)
|
||||
- .cursorignore file
|
||||
- Notities over context kwaliteit
|
||||
- Screenshot van werkende Tab completion
|
||||
- 3 voorbeelden van CMD+K edits
|
||||
- Notities: wat werkt wel/niet goed
|
||||
|
||||
---
|
||||
|
||||
## Huiswerk (2 uur)
|
||||
|
||||
### Context Deep Dive
|
||||
### Bouw Feature met Cursor
|
||||
|
||||
**Deel 1: MCP Experimenteren (1 uur)**
|
||||
**Deel 1: Feature Bouwen (1.5 uur)**
|
||||
|
||||
Kies en configureer nog een MCP server:
|
||||
- brave-search (voor web zoeken)
|
||||
- sqlite (voor lokale databases)
|
||||
- Of een andere uit de [MCP registry](https://github.com/modelcontextprotocol/servers)
|
||||
Voeg "Due Dates" toe aan je Todo app:
|
||||
1. Elk todo kan een due date hebben
|
||||
2. Toon due date in de lijst
|
||||
3. Sorteer op due date
|
||||
4. Markeer overdue items in rood
|
||||
|
||||
Test uitgebreid:
|
||||
- Wat kun je ermee?
|
||||
- Wanneer is het nuttig?
|
||||
- Wat zijn beperkingen?
|
||||
**Gebruik ALLE Cursor features:**
|
||||
- Tab completion voor nieuwe code
|
||||
- CMD+K voor aanpassingen
|
||||
- Chat voor vragen
|
||||
- Composer voor multi-file changes
|
||||
|
||||
**Deel 2: Context Playbook (1 uur)**
|
||||
**Deel 2: Reflectie (30 min)**
|
||||
|
||||
Schrijf een persoonlijk "Context Management Playbook" (1 pagina):
|
||||
|
||||
```markdown
|
||||
# Mijn Context Management Playbook
|
||||
|
||||
## Wanneer gebruik ik wat?
|
||||
|
||||
### Claude Desktop + MCP
|
||||
- [situaties]
|
||||
|
||||
### Cursor met @ mentions
|
||||
- [situaties]
|
||||
|
||||
## Mijn .cursorignore template
|
||||
- [wat ignore ik altijd]
|
||||
|
||||
## Context strategieën
|
||||
- [wat werkt voor mij]
|
||||
|
||||
## Red flags
|
||||
- [wanneer is context slecht]
|
||||
|
||||
## Optimalisatie tips
|
||||
- [mijn beste tips]
|
||||
```
|
||||
Schrijf vergelijking (400 woorden):
|
||||
- Cursor vs OpenCode: wat is beter?
|
||||
- Welke feature gebruik je het meest?
|
||||
- Is free tier voldoende?
|
||||
- Ga je overstappen?
|
||||
|
||||
### Deliverable
|
||||
- Extra MCP server geconfigureerd
|
||||
- Context Management Playbook (1 pagina)
|
||||
- Documentatie in AI-DECISIONS.md over je context keuzes
|
||||
- Werkende Due Dates feature
|
||||
- GitHub commit met de changes
|
||||
- Reflectie (400 woorden)
|
||||
|
||||
---
|
||||
|
||||
## Leerdoelen
|
||||
Na deze les kan de student:
|
||||
- MCP begrijpen en uitleggen
|
||||
- MCP servers configureren in Claude Desktop
|
||||
- Filesystem en GitHub MCP gebruiken
|
||||
- Context windows en token limits begrijpen
|
||||
- .cursorignore effectief gebruiken
|
||||
- Context strategieën toepassen
|
||||
- De juiste tool kiezen voor context management
|
||||
- Cursor installeren en configureren
|
||||
- Tab completion effectief gebruiken
|
||||
- CMD+K gebruiken voor inline edits
|
||||
- Chat gebruiken met @ mentions voor context
|
||||
- Composer mode gebruiken voor multi-file generatie
|
||||
- Het verschil beoordelen tussen Cursor en OpenCode
|
||||
- De juiste Cursor feature kiezen per taak
|
||||
|
||||
@@ -1,284 +1,287 @@
|
||||
# Les 13: Mastering Cursor
|
||||
# Les 13: AI Agents & Custom GPTs
|
||||
|
||||
---
|
||||
|
||||
## Hoofdstuk
|
||||
**Hoofdstuk 3: Advanced** (Les 10-18)
|
||||
**Deel 4: Advanced AI Features** (Les 13-18)
|
||||
|
||||
## Beschrijving
|
||||
Verdieping in Cursor's geavanceerde features. Leer model keuze, Composer Mode, @ mentions, en .cursorrules optimaal gebruiken.
|
||||
Leer werken met AI agents en custom GPTs. Bouw je eigen gespecialiseerde AI assistenten en begrijp hoe agents autonome taken kunnen uitvoeren.
|
||||
|
||||
---
|
||||
|
||||
## Te Behandelen
|
||||
|
||||
### Model Keuze
|
||||
### Groepsdiscussie (15 min)
|
||||
Bespreek klassikaal de Cursor reflecties uit Les 12 - welke features werken het beste voor welke taken?
|
||||
|
||||
**Wanneer welk model?**
|
||||
### Wat zijn AI Agents?
|
||||
|
||||
| Model | Gebruik voor | Kosten |
|
||||
|-------|-------------|--------|
|
||||
| **Haiku** | Simpele taken, autocomplete | Goedkoop |
|
||||
| **Sonnet** | Dagelijks werk, de meeste taken | Medium |
|
||||
| **Opus** | Complexe architectuur, multi-file | Duur |
|
||||
**Definitie:** AI systemen die autonoom taken kunnen uitvoeren, niet alleen antwoorden geven.
|
||||
|
||||
**Vuistregels:**
|
||||
- Tab completion: Haiku (automatisch)
|
||||
- CMD+K: Sonnet (default)
|
||||
- Composer: Sonnet of Opus
|
||||
- Complexe debugging: Opus
|
||||
**Verschil Chat vs Agent:**
|
||||
|
||||
| Aspect | Chat | Agent |
|
||||
|--------|------|-------|
|
||||
| Gedrag | Beantwoordt vragen | Voert taken uit |
|
||||
| Autonomie | Wacht op input | Kan zelf beslissingen nemen |
|
||||
| Tools | Alleen tekst | Kan tools gebruiken |
|
||||
| Voorbeeld | "Hoe maak ik X?" | "Maak X voor mij" |
|
||||
|
||||
---
|
||||
|
||||
### Composer Mode Diepgaand
|
||||
### Claude Projects
|
||||
|
||||
**Wat is Composer?**
|
||||
Multi-file generatie in één keer. Cursor plant en voert wijzigingen uit over meerdere bestanden.
|
||||
**Wat is een Claude Project?**
|
||||
- Verzameling van context specifiek voor één doel
|
||||
- Blijft behouden over conversaties
|
||||
- Kan bestanden bevatten
|
||||
|
||||
**Wanneer Composer gebruiken:**
|
||||
- Nieuwe feature met meerdere components
|
||||
- Refactoring over meerdere files
|
||||
- Boilerplate generatie
|
||||
- Complexe wijzigingen
|
||||
**Wanneer gebruiken:**
|
||||
- Terugkerend werk aan hetzelfde project
|
||||
- Consistente coding style nodig
|
||||
- Documentatie die AI moet kennen
|
||||
|
||||
**Composer Workflow:**
|
||||
1. CMD+I opent Composer
|
||||
2. Beschrijf je doel duidelijk
|
||||
3. Voeg context toe met @ mentions
|
||||
4. Laat Cursor plannen
|
||||
5. Review het plan
|
||||
6. Accept of reject per file
|
||||
7. Itereer met feedback
|
||||
**Project aanmaken:**
|
||||
1. Ga naar claude.ai → Projects
|
||||
2. Klik "New Project"
|
||||
3. Voeg project knowledge toe (files, instructies)
|
||||
4. Start conversaties binnen het project
|
||||
|
||||
**Voorbeeld prompt:**
|
||||
**Voorbeeld Project Instructions:**
|
||||
```
|
||||
Create a user profile page with:
|
||||
- @components/ui/ style components
|
||||
- Profile header with avatar
|
||||
- Edit form with validation
|
||||
- Save to @lib/supabase.ts
|
||||
- Loading and error states
|
||||
Je bent een expert React/Next.js developer.
|
||||
|
||||
Technologie stack:
|
||||
- Next.js 14 met App Router
|
||||
- TypeScript strict mode
|
||||
- Tailwind CSS
|
||||
- Supabase voor backend
|
||||
|
||||
Coding conventions:
|
||||
- Functional components met TypeScript
|
||||
- Named exports (geen default exports)
|
||||
- Error handling met try/catch
|
||||
- Nederlandse comments in code
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### @ Mentions Systeem
|
||||
### Custom GPTs
|
||||
|
||||
**Alle types:**
|
||||
**Wat zijn Custom GPTs?**
|
||||
Gespecialiseerde ChatGPT versies met:
|
||||
- Specifieke instructies
|
||||
- Eigen kennis (uploaded files)
|
||||
- Optioneel: Actions (API calls)
|
||||
|
||||
| Mention | Wat het doet | Voorbeeld |
|
||||
|---------|--------------|-----------|
|
||||
| `@file.tsx` | Specifieke file | `@Button.tsx` |
|
||||
| `@folder/` | Hele folder | `@components/` |
|
||||
| `@codebase` | Zoek in codebase | `@codebase auth logic` |
|
||||
| `@Docs` | Officiële docs | `@Docs Next.js routing` |
|
||||
| `@Web` | Web zoeken | `@Web Supabase auth setup` |
|
||||
**Wanneer een Custom GPT maken:**
|
||||
- Repetitieve taken met dezelfde context
|
||||
- Specifieke expertise nodig
|
||||
- Delen met anderen
|
||||
|
||||
**Best practices:**
|
||||
- Wees specifiek met file mentions
|
||||
- Gebruik folder mentions voor context
|
||||
- @Docs voor up-to-date informatie
|
||||
- Combineer mentions voor betere context
|
||||
|
||||
---
|
||||
|
||||
### .cursorrules Advanced
|
||||
|
||||
**Meerdere rules files:**
|
||||
**Custom GPT maken:**
|
||||
1. Ga naar chat.openai.com/gpts
|
||||
2. Klik "Create"
|
||||
3. Configureer in "Create" tab OF gebruik "Configure"
|
||||
|
||||
**Voorbeeld: Code Review GPT**
|
||||
```
|
||||
.cursor/
|
||||
└── rules/
|
||||
├── general.mdc # Project-brede regels
|
||||
├── components.mdc # Component conventies
|
||||
├── api.mdc # API route regels
|
||||
└── testing.mdc # Test conventies
|
||||
```
|
||||
Instructions:
|
||||
Je bent een code reviewer gespecialiseerd in React/Next.js.
|
||||
|
||||
**Effectieve rules schrijven:**
|
||||
Bij elke code review check je:
|
||||
1. TypeScript best practices
|
||||
2. React hooks correct gebruik
|
||||
3. Performance (unnecessary re-renders)
|
||||
4. Accessibility basics
|
||||
5. Error handling
|
||||
|
||||
```markdown
|
||||
# Component Rules
|
||||
|
||||
## Structure
|
||||
Alle components moeten volgen:
|
||||
1. Props interface bovenaan
|
||||
2. Component function
|
||||
3. Named export onderaan
|
||||
|
||||
## Example
|
||||
\`\`\`tsx
|
||||
interface ButtonProps {
|
||||
label: string
|
||||
onClick: () => void
|
||||
variant?: 'primary' | 'secondary'
|
||||
}
|
||||
|
||||
export function Button({ label, onClick, variant = 'primary' }: ButtonProps) {
|
||||
return (
|
||||
<button onClick={onClick} className={...}>
|
||||
{label}
|
||||
</button>
|
||||
)
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
## DON'Ts
|
||||
- Geen default exports
|
||||
- Geen inline styles
|
||||
- Geen any types
|
||||
Geef feedback in dit format:
|
||||
- ✅ Goed: [wat goed is]
|
||||
- ⚠️ Suggestie: [verbeterpunten]
|
||||
- ❌ Issue: [problemen die gefixed moeten worden]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Codebase Indexing
|
||||
### Agent Capabilities
|
||||
|
||||
**Hoe Cursor indexeert:**
|
||||
- Scant alle files in je project
|
||||
- Bouwt semantic understanding
|
||||
- Gebruikt voor autocomplete en context
|
||||
**Wat kunnen agents:**
|
||||
- Code schrijven en testen
|
||||
- Files aanmaken en bewerken
|
||||
- Terminal commands uitvoeren
|
||||
- Web searches doen
|
||||
- Meerdere stappen plannen
|
||||
|
||||
**Optimaliseren:**
|
||||
1. Goede `.cursorignore` (node_modules, .next, etc.)
|
||||
2. Semantische naming
|
||||
3. Duidelijke file structuur
|
||||
4. Comments waar nodig
|
||||
**Cursor als Agent:**
|
||||
- Composer mode plant en voert multi-file changes uit
|
||||
- @ mentions geven context
|
||||
- Tab completion voorspelt volgende stappen
|
||||
|
||||
**Re-indexeren:**
|
||||
CMD+Shift+P → "Reindex"
|
||||
**Claude als Agent (met MCP):**
|
||||
- Kan tools gebruiken
|
||||
- Filesystem access
|
||||
- Database queries
|
||||
- External APIs
|
||||
|
||||
---
|
||||
|
||||
### Cost Management
|
||||
### Best Practices voor Agent Instructies
|
||||
|
||||
**Token gebruik monitoren:**
|
||||
- Cursor toont token count in chat
|
||||
- Check monthly usage in settings
|
||||
**Wees specifiek:**
|
||||
```
|
||||
❌ "Help me met mijn project"
|
||||
✅ "Review de auth logic in src/lib/auth.ts en check voor security issues"
|
||||
```
|
||||
|
||||
**Bespaartips:**
|
||||
1. Gebruik Haiku voor simpele taken
|
||||
2. Beperk context (niet hele codebase)
|
||||
3. Wees specifiek in prompts
|
||||
4. Fresh chat voor nieuwe onderwerpen
|
||||
**Geef constraints:**
|
||||
```
|
||||
❌ "Maak het beter"
|
||||
✅ "Refactor naar max 50 regels, behoud dezelfde functionaliteit"
|
||||
```
|
||||
|
||||
**Free tier strategie:**
|
||||
- Focus op Tab completion (onbeperkt)
|
||||
- Gebruik CMD+K spaarzaam
|
||||
- Composer alleen voor grote taken
|
||||
**Definieer output format:**
|
||||
```
|
||||
Geef je antwoord in dit format:
|
||||
1. Samenvatting (1 zin)
|
||||
2. Gevonden issues (bullet points)
|
||||
3. Voorgestelde fix (code)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Prompt Templates
|
||||
|
||||
**Code Generation Template:**
|
||||
```
|
||||
Context: [beschrijf je project/stack]
|
||||
Taak: [wat moet er gemaakt worden]
|
||||
Requirements:
|
||||
- [requirement 1]
|
||||
- [requirement 2]
|
||||
Constraints:
|
||||
- [constraint 1]
|
||||
Output: [gewenst format]
|
||||
```
|
||||
|
||||
**Debugging Template:**
|
||||
```
|
||||
Error message:
|
||||
[plak error]
|
||||
|
||||
Relevante code:
|
||||
[plak code]
|
||||
|
||||
Wat ik verwacht:
|
||||
[gewenst gedrag]
|
||||
|
||||
Wat er gebeurt:
|
||||
[actueel gedrag]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Tools
|
||||
- Cursor
|
||||
- Claude models (Haiku/Sonnet/Opus)
|
||||
- .cursorrules
|
||||
- ChatGPT Custom GPTs
|
||||
- Claude Projects
|
||||
- Cursor (Composer mode)
|
||||
|
||||
---
|
||||
|
||||
## Lesopdracht (2 uur)
|
||||
|
||||
### Multi-Step Form Wizard
|
||||
### Bouw Je Eigen AI Assistant
|
||||
|
||||
**Bouw met Composer:**
|
||||
**Deel 1: Claude Project (45 min)**
|
||||
|
||||
| Stap | Features |
|
||||
|------|----------|
|
||||
| 1 | Personal info (naam, email) |
|
||||
| 2 | Preferences (theme, notifications) |
|
||||
| 3 | Review & confirm |
|
||||
| 4 | Success animation |
|
||||
Maak een Claude Project voor je eindproject:
|
||||
1. Ga naar claude.ai → Projects → New Project
|
||||
2. Schrijf project instructions:
|
||||
- Tech stack
|
||||
- Coding conventions
|
||||
- Project specifieke regels
|
||||
3. Upload relevante files (schema, README)
|
||||
4. Test met 3 verschillende vragen
|
||||
|
||||
**Requirements:**
|
||||
- Progress indicator
|
||||
- Per-stap validatie
|
||||
- localStorage persistence
|
||||
- TypeScript strict
|
||||
- Tailwind styling
|
||||
- Mobile responsive
|
||||
**Deel 2: Custom GPT (45 min)**
|
||||
|
||||
**Process:**
|
||||
Maak een Custom GPT voor code review:
|
||||
1. Ga naar chat.openai.com/gpts
|
||||
2. Klik "Create"
|
||||
3. Schrijf instructions voor jouw stack
|
||||
4. Test met code uit je project
|
||||
|
||||
**Deel 1: Composer Setup (30 min)**
|
||||
1. Open Composer (CMD+I)
|
||||
2. Schrijf comprehensive prompt
|
||||
3. Include @ mentions naar relevante files
|
||||
4. Kies Sonnet of Opus
|
||||
**Deel 3: Vergelijking (30 min)**
|
||||
|
||||
**Deel 2: Generatie & Review (45 min)**
|
||||
1. Laat Composer genereren
|
||||
2. Review elke file
|
||||
3. Accept wat goed is
|
||||
4. Reject wat niet past
|
||||
|
||||
**Deel 3: Refinement (45 min)**
|
||||
1. Gebruik CMD+K voor kleine fixes
|
||||
2. Chat voor vragen
|
||||
3. Itereer tot het werkt
|
||||
Test dezelfde taak met beide:
|
||||
- "Review deze component op best practices"
|
||||
- Noteer verschillen in output
|
||||
- Welke is beter voor welk doel?
|
||||
|
||||
### Deliverable
|
||||
- Werkende form wizard
|
||||
- Notities: welk model wanneer, hoeveel iteraties
|
||||
- Claude Project URL
|
||||
- Custom GPT (als je ChatGPT Plus hebt) of instructies doc
|
||||
- Vergelijkingsnotities
|
||||
|
||||
---
|
||||
|
||||
## Huiswerk (2 uur)
|
||||
|
||||
### Perfecte .cursorrules
|
||||
### Optimaliseer Je AI Assistants
|
||||
|
||||
**Deel 1: Research (30 min)**
|
||||
- Zoek 3-5 .cursorrules voorbeelden online
|
||||
- Analyseer wat ze effectief maakt
|
||||
**Deel 1: Iteratie (1 uur)**
|
||||
|
||||
**Deel 2: Write Comprehensive Rules (1 uur)**
|
||||
Verbeter je Claude Project:
|
||||
1. Test met 5 verschillende taken
|
||||
2. Noteer waar instructies tekortschieten
|
||||
3. Pas instructies aan
|
||||
4. Test opnieuw
|
||||
|
||||
Maak complete .cursorrules voor je eindproject:
|
||||
Documenteer in `docs/AI-ASSISTANTS.md`:
|
||||
- Originele instructies
|
||||
- Wat niet werkte
|
||||
- Verbeterde instructies
|
||||
- Resultaat verschil
|
||||
|
||||
**Deel 2: Prompt Library (30 min)**
|
||||
|
||||
Maak een persoonlijke prompt library:
|
||||
```markdown
|
||||
# [Project Naam]
|
||||
# Mijn Prompt Templates
|
||||
|
||||
## Tech Stack
|
||||
[Jouw stack]
|
||||
## Code Generation
|
||||
[template]
|
||||
|
||||
## Code Conventions
|
||||
[Jouw conventies]
|
||||
## Debugging
|
||||
[template]
|
||||
|
||||
## File Naming
|
||||
[Jouw regels]
|
||||
## Code Review
|
||||
[template]
|
||||
|
||||
## Component Structure
|
||||
[Jouw patterns]
|
||||
|
||||
## Styling
|
||||
[Tailwind regels]
|
||||
|
||||
## API Routes
|
||||
[Route conventies]
|
||||
|
||||
## Error Handling
|
||||
[Error patterns]
|
||||
|
||||
## DON'Ts
|
||||
[Wat te vermijden]
|
||||
## Refactoring
|
||||
[template]
|
||||
```
|
||||
|
||||
**Deel 3: Test (30 min)**
|
||||
1. Start nieuw component
|
||||
2. Vraag Cursor om het te bouwen
|
||||
3. Check: volgt Cursor je regels?
|
||||
4. Itereer indien nodig
|
||||
**Deel 3: Reflectie (30 min)**
|
||||
|
||||
Schrijf reflectie (300 woorden):
|
||||
- Welke AI assistant gebruik je waarvoor?
|
||||
- Wat is het verschil tussen Claude Projects en Custom GPTs?
|
||||
- Hoe heeft dit je workflow verbeterd?
|
||||
|
||||
### Deliverable
|
||||
- Complete .cursorrules file
|
||||
- Screenshot van Cursor die regels volgt
|
||||
- Korte analyse: wat werkt goed, wat niet
|
||||
- Geoptimaliseerde AI assistant instructies
|
||||
- Prompt library document
|
||||
- Reflectie (300 woorden)
|
||||
|
||||
---
|
||||
|
||||
## Leerdoelen
|
||||
Na deze les kan de student:
|
||||
- Het juiste Claude model kiezen per taak
|
||||
- Composer Mode effectief gebruiken voor multi-file features
|
||||
- @ mentions strategisch inzetten voor context
|
||||
- Geavanceerde .cursorrules files schrijven
|
||||
- Codebase indexing optimaliseren
|
||||
- Token gebruik monitoren en kosten beheren
|
||||
- Het verschil uitleggen tussen chat en agent
|
||||
- Een Claude Project aanmaken en configureren
|
||||
- Een Custom GPT maken met specifieke instructies
|
||||
- Effectieve agent instructies schrijven
|
||||
- Prompt templates gebruiken voor consistente resultaten
|
||||
- De juiste AI assistant kiezen per taak
|
||||
|
||||
@@ -1,211 +1,438 @@
|
||||
# Les 14: Debugging & Code Review met AI
|
||||
|
||||
> 📋 **Lesmateriaal nog niet uitgewerkt**
|
||||
>
|
||||
> De volgende bestanden worden gegenereerd wanneer deze les wordt uitgewerkt:
|
||||
> - Les14-Slide-Overzicht.md
|
||||
> - Les14-Lesplan.md
|
||||
> - Les14-Bijlage-A-Lesopdracht.md
|
||||
> - Les14-Bijlage-B-Huiswerkopdracht.md
|
||||
# Les 14: Project Setup & Repository Structure
|
||||
|
||||
---
|
||||
|
||||
## Hoofdstuk
|
||||
**Hoofdstuk 3: Advanced** (Les 10-18)
|
||||
**Deel 4: Advanced AI Features** (Les 13-18)
|
||||
|
||||
## Beschrijving
|
||||
Leer hoe je AI effectief inzet voor debugging en code review. Begrijp foutmeldingen, los problemen op, en verbeter je code kwaliteit.
|
||||
Leer professionele project setup en repository structuur. Begrijp hoe een goed georganiseerd project AI tools effectiever maakt en samenwerking vergemakkelijkt.
|
||||
|
||||
---
|
||||
|
||||
## Te Behandelen
|
||||
|
||||
### Waarom AI voor Debugging?
|
||||
- AI begrijpt error messages vaak beter dan Google
|
||||
- Kan context van jouw code meenemen
|
||||
- Suggereert oplossingen specifiek voor jouw situatie
|
||||
- Leert je patterns herkennen
|
||||
### Groepsdiscussie (15 min)
|
||||
Bespreek klassikaal de AI assistant reflecties uit Les 13 - welke instructies werkten goed en welke niet?
|
||||
|
||||
### Error Messages Begrijpen
|
||||
### Waarom Project Structuur Belangrijk Is
|
||||
|
||||
**Typische JavaScript/React errors:**
|
||||
- `TypeError: Cannot read properties of undefined`
|
||||
- `ReferenceError: x is not defined`
|
||||
- `SyntaxError: Unexpected token`
|
||||
- `Hydration error` (Next.js specifiek)
|
||||
**Voor jezelf:**
|
||||
- Sneller code terugvinden
|
||||
- Makkelijker onderhouden
|
||||
- Minder bugs door consistentie
|
||||
|
||||
**Hoe AI vragen:**
|
||||
**Voor AI tools:**
|
||||
- Betere context understanding
|
||||
- Consistentere code generation
|
||||
- Cursor/Claude begrijpt je project beter
|
||||
|
||||
**Voor samenwerking:**
|
||||
- Anderen begrijpen je code sneller
|
||||
- Standaard conventies = minder discussie
|
||||
- Onboarding nieuwe developers eenvoudiger
|
||||
|
||||
---
|
||||
|
||||
### Next.js 14 Project Structuur
|
||||
|
||||
**Aanbevolen structuur:**
|
||||
```
|
||||
Ik krijg deze error:
|
||||
[plak error message]
|
||||
|
||||
In deze code:
|
||||
[plak relevante code]
|
||||
|
||||
Wat gaat er mis en hoe los ik het op?
|
||||
project-root/
|
||||
├── src/
|
||||
│ ├── app/ # Next.js App Router
|
||||
│ │ ├── (auth)/ # Route group voor auth pagina's
|
||||
│ │ │ ├── login/
|
||||
│ │ │ └── register/
|
||||
│ │ ├── api/ # API routes
|
||||
│ │ │ └── chat/
|
||||
│ │ ├── dashboard/
|
||||
│ │ ├── layout.tsx
|
||||
│ │ ├── page.tsx
|
||||
│ │ └── globals.css
|
||||
│ │
|
||||
│ ├── components/ # React components
|
||||
│ │ ├── ui/ # Basis UI components
|
||||
│ │ │ ├── Button.tsx
|
||||
│ │ │ ├── Input.tsx
|
||||
│ │ │ └── Card.tsx
|
||||
│ │ ├── layout/ # Layout components
|
||||
│ │ │ ├── Header.tsx
|
||||
│ │ │ ├── Footer.tsx
|
||||
│ │ │ └── Sidebar.tsx
|
||||
│ │ └── features/ # Feature-specifieke components
|
||||
│ │ ├── auth/
|
||||
│ │ └── dashboard/
|
||||
│ │
|
||||
│ ├── lib/ # Utilities en configuraties
|
||||
│ │ ├── supabase.ts # Supabase client
|
||||
│ │ ├── utils.ts # Helper functies
|
||||
│ │ └── constants.ts # App constanten
|
||||
│ │
|
||||
│ ├── hooks/ # Custom React hooks
|
||||
│ │ ├── useAuth.ts
|
||||
│ │ └── useTodos.ts
|
||||
│ │
|
||||
│ └── types/ # TypeScript types
|
||||
│ ├── database.ts
|
||||
│ └── api.ts
|
||||
│
|
||||
├── public/ # Static assets
|
||||
│ ├── images/
|
||||
│ └── favicon.ico
|
||||
│
|
||||
├── docs/ # Documentatie
|
||||
│ ├── PROMPT-LOG.md
|
||||
│ ├── AI-DECISIONS.md
|
||||
│ └── PROJECT-BRIEF.md
|
||||
│
|
||||
├── .cursorrules # Cursor AI configuratie
|
||||
├── .env.local # Environment variables (niet in git!)
|
||||
├── .env.example # Template voor env vars
|
||||
├── .gitignore
|
||||
├── package.json
|
||||
├── tsconfig.json
|
||||
├── tailwind.config.ts
|
||||
└── README.md
|
||||
```
|
||||
|
||||
### Debugging Workflow met AI
|
||||
---
|
||||
|
||||
**Stap 1: Isoleer het probleem**
|
||||
- Waar treedt de error op?
|
||||
- Wat was de laatste wijziging?
|
||||
- Kan je het reproduceren?
|
||||
### Component Organisatie
|
||||
|
||||
**Stap 2: Verzamel context**
|
||||
- Error message (volledig!)
|
||||
- Relevante code
|
||||
- Wat je verwacht vs wat er gebeurt
|
||||
**UI Components (src/components/ui/):**
|
||||
- Herbruikbare, generieke components
|
||||
- Geen business logic
|
||||
- Props-driven
|
||||
- Voorbeelden: Button, Input, Modal, Card
|
||||
|
||||
**Stap 3: Vraag AI**
|
||||
- Wees specifiek
|
||||
- Geef context
|
||||
- Vraag om uitleg, niet alleen fix
|
||||
**Layout Components (src/components/layout/):**
|
||||
- Structurele components
|
||||
- Meestal één per type
|
||||
- Voorbeelden: Header, Footer, Sidebar, Navigation
|
||||
|
||||
**Stap 4: Begrijp de oplossing**
|
||||
- Vraag door als je het niet snapt
|
||||
- Leer het pattern voor volgende keer
|
||||
**Feature Components (src/components/features/):**
|
||||
- Business logic bevattend
|
||||
- Specifiek voor één feature
|
||||
- Groepeer per feature/domein
|
||||
|
||||
### Console.log Debugging
|
||||
- Strategisch plaatsen
|
||||
- Variabele waarden checken
|
||||
- Flow van code volgen
|
||||
- AI kan helpen met waar te loggen
|
||||
---
|
||||
|
||||
### Browser DevTools Basics
|
||||
- Console tab: errors en logs
|
||||
- Network tab: API calls checken
|
||||
- Elements tab: HTML/CSS inspecteren
|
||||
- React DevTools: component state bekijken
|
||||
### File Naming Conventions
|
||||
|
||||
### Code Review met AI
|
||||
|
||||
**Wat kan AI reviewen:**
|
||||
- Code kwaliteit en leesbaarheid
|
||||
- Potentiële bugs
|
||||
- Performance issues
|
||||
- Security problemen
|
||||
- Best practices
|
||||
|
||||
**Goede review prompt:**
|
||||
**Components:**
|
||||
```
|
||||
Review deze code op:
|
||||
1. Bugs of edge cases die ik mis
|
||||
2. Performance verbeteringen
|
||||
3. Leesbaarheid
|
||||
4. Best practices voor React/Next.js
|
||||
|
||||
[plak code]
|
||||
✅ Button.tsx # PascalCase
|
||||
✅ UserProfile.tsx
|
||||
❌ button.tsx
|
||||
❌ user-profile.tsx
|
||||
```
|
||||
|
||||
### Veelvoorkomende Issues die AI Vindt
|
||||
- Missing error handling
|
||||
- Memory leaks (useEffect cleanup)
|
||||
- Onnodig re-renders
|
||||
- Hardcoded values
|
||||
- Missing loading/error states
|
||||
- Accessibility issues
|
||||
**Hooks:**
|
||||
```
|
||||
✅ useAuth.ts # camelCase met 'use' prefix
|
||||
✅ useTodos.ts
|
||||
❌ UseAuth.ts
|
||||
❌ auth-hook.ts
|
||||
```
|
||||
|
||||
### Refactoring met AI
|
||||
- "Hoe kan ik deze code simplificeren?"
|
||||
- "Extract dit naar een custom hook"
|
||||
- "Maak dit component meer herbruikbaar"
|
||||
**Utilities:**
|
||||
```
|
||||
✅ formatDate.ts # camelCase
|
||||
✅ utils.ts
|
||||
✅ constants.ts
|
||||
```
|
||||
|
||||
### Wanneer NIET AI Vertrouwen
|
||||
- Als je de oplossing niet begrijpt
|
||||
- Bij security-gerelateerde code (dubbel check!)
|
||||
- Bij verouderde info (check versie docs)
|
||||
**Types:**
|
||||
```
|
||||
✅ database.ts # camelCase
|
||||
✅ User.types.ts # optioneel: .types suffix
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### .cursorrules Setup
|
||||
|
||||
**Maak .cursorrules in project root:**
|
||||
```markdown
|
||||
# Project: [Jouw Project Naam]
|
||||
|
||||
## Tech Stack
|
||||
- Next.js 14 met App Router
|
||||
- TypeScript (strict mode)
|
||||
- Tailwind CSS
|
||||
- Supabase
|
||||
- React Query
|
||||
|
||||
## File Structure
|
||||
- Components in src/components/
|
||||
- UI components in src/components/ui/
|
||||
- API routes in src/app/api/
|
||||
|
||||
## Code Conventions
|
||||
- Functional components only
|
||||
- Named exports (geen default exports)
|
||||
- Props interface boven component
|
||||
- Nederlandse comments
|
||||
|
||||
## Naming
|
||||
- Components: PascalCase (Button.tsx)
|
||||
- Hooks: camelCase met use prefix (useAuth.ts)
|
||||
- Utils: camelCase (formatDate.ts)
|
||||
|
||||
## Styling
|
||||
- Tailwind CSS classes
|
||||
- Geen inline styles
|
||||
- Responsive mobile-first
|
||||
|
||||
## TypeScript
|
||||
- Strict mode
|
||||
- Geen any types
|
||||
- Interfaces voor props
|
||||
- Types voor data
|
||||
|
||||
## Don'ts
|
||||
- Geen console.log in productie
|
||||
- Geen hardcoded strings
|
||||
- Geen unused imports
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Git Best Practices
|
||||
|
||||
**Commit Message Format:**
|
||||
```
|
||||
type: korte beschrijving
|
||||
|
||||
Types:
|
||||
- feat: nieuwe feature
|
||||
- fix: bug fix
|
||||
- refactor: code verbetering
|
||||
- docs: documentatie
|
||||
- style: formatting
|
||||
- test: tests toevoegen
|
||||
```
|
||||
|
||||
**Voorbeelden:**
|
||||
```bash
|
||||
git commit -m "feat: add user authentication with Supabase"
|
||||
git commit -m "fix: resolve hydration error in TodoList"
|
||||
git commit -m "docs: update README with setup instructions"
|
||||
```
|
||||
|
||||
**.gitignore essentials:**
|
||||
```
|
||||
# Dependencies
|
||||
node_modules/
|
||||
|
||||
# Environment
|
||||
.env*.local
|
||||
|
||||
# Next.js
|
||||
.next/
|
||||
out/
|
||||
|
||||
# IDE
|
||||
.idea/
|
||||
.vscode/
|
||||
|
||||
# OS
|
||||
.DS_Store
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Environment Variables
|
||||
|
||||
**Structuur:**
|
||||
```bash
|
||||
# .env.local (NOOIT committen!)
|
||||
NEXT_PUBLIC_SUPABASE_URL=https://xxx.supabase.co
|
||||
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJhbGci...
|
||||
OPENAI_API_KEY=sk-...
|
||||
|
||||
# .env.example (WEL committen)
|
||||
NEXT_PUBLIC_SUPABASE_URL=your-supabase-url
|
||||
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
|
||||
OPENAI_API_KEY=your-openai-key
|
||||
```
|
||||
|
||||
**Regels:**
|
||||
- `NEXT_PUBLIC_` prefix = zichtbaar in browser
|
||||
- Zonder prefix = alleen server-side
|
||||
- Nooit secrets in `NEXT_PUBLIC_` vars
|
||||
|
||||
---
|
||||
|
||||
### README.md Template
|
||||
|
||||
```markdown
|
||||
# Project Naam
|
||||
|
||||
Korte beschrijving van je project.
|
||||
|
||||
## Features
|
||||
- Feature 1
|
||||
- Feature 2
|
||||
- Feature 3
|
||||
|
||||
## Tech Stack
|
||||
- Next.js 14
|
||||
- TypeScript
|
||||
- Tailwind CSS
|
||||
- Supabase
|
||||
- Vercel AI SDK
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Prerequisites
|
||||
- Node.js 18+
|
||||
- npm of yarn
|
||||
- Supabase account
|
||||
|
||||
### Installation
|
||||
|
||||
1. Clone de repository
|
||||
```bash
|
||||
git clone https://github.com/username/project.git
|
||||
cd project
|
||||
```
|
||||
|
||||
2. Installeer dependencies
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
3. Maak .env.local (zie .env.example)
|
||||
|
||||
4. Start development server
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
## Environment Variables
|
||||
Zie `.env.example` voor benodigde variabelen.
|
||||
|
||||
## Deployment
|
||||
Deployed op Vercel: [productie-url]
|
||||
|
||||
## Documentatie
|
||||
- [PROMPT-LOG.md](docs/PROMPT-LOG.md)
|
||||
- [AI-DECISIONS.md](docs/AI-DECISIONS.md)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Tools
|
||||
- Cursor
|
||||
- Browser DevTools
|
||||
- React DevTools
|
||||
- Console/Terminal
|
||||
- Git
|
||||
- GitHub
|
||||
|
||||
---
|
||||
|
||||
## Lesopdracht (2 uur)
|
||||
|
||||
### Debugging Challenge
|
||||
### Setup Je Eindproject
|
||||
|
||||
Je krijgt een project met opzettelijke bugs. Los ze op met AI hulp.
|
||||
**Deel 1: Project Structuur (45 min)**
|
||||
|
||||
**Deel 1: Setup (10 min)**
|
||||
- Clone het buggy project (wordt gedeeld)
|
||||
- Run `npm install` en `npm run dev`
|
||||
- Zie alle errors!
|
||||
1. Maak nieuw Next.js project:
|
||||
```bash
|
||||
npx create-next-app@latest mijn-eindproject --typescript --tailwind --app
|
||||
```
|
||||
|
||||
**Deel 2: Bug Hunting (1 uur 20 min)**
|
||||
2. Maak de mappenstructuur:
|
||||
- src/components/ui/
|
||||
- src/components/layout/
|
||||
- src/components/features/
|
||||
- src/lib/
|
||||
- src/hooks/
|
||||
- src/types/
|
||||
- docs/
|
||||
|
||||
Los de volgende bugs op (met AI hulp):
|
||||
3. Maak placeholder files:
|
||||
- src/lib/supabase.ts
|
||||
- src/lib/utils.ts
|
||||
|
||||
| Bug | Symptoom |
|
||||
|-----|----------|
|
||||
| 1 | App crashed bij opstarten |
|
||||
| 2 | Data wordt niet geladen |
|
||||
| 3 | Form submit werkt niet |
|
||||
| 4 | Styling is broken op mobile |
|
||||
| 5 | Infinite loop bij useEffect |
|
||||
| 6 | Button click doet niets |
|
||||
**Deel 2: Configuratie (30 min)**
|
||||
|
||||
**Per bug:**
|
||||
- Identificeer de error message
|
||||
- Vraag AI om hulp met context
|
||||
- Implementeer de fix
|
||||
- Documenteer wat je geleerd hebt
|
||||
1. Maak .cursorrules met jouw conventies
|
||||
2. Maak .env.example
|
||||
3. Update .gitignore
|
||||
4. Maak README.md met template
|
||||
|
||||
**Deel 3: Documentatie (30 min)**
|
||||
- Voeg toe aan je `PROMPT-LOG.md`:
|
||||
- De prompts die je gebruikte
|
||||
- Wat werkte wel/niet
|
||||
**Deel 3: Git Setup (25 min)**
|
||||
|
||||
1. git init
|
||||
2. Initial commit met goede message
|
||||
3. Push naar GitHub
|
||||
4. Check: .env.local NIET gecommit?
|
||||
|
||||
**Deel 4: Documentatie Start (20 min)**
|
||||
|
||||
Maak in docs/:
|
||||
- PROJECT-BRIEF.md (beschrijving eindproject)
|
||||
- PROMPT-LOG.md (leeg template)
|
||||
- AI-DECISIONS.md (leeg template)
|
||||
|
||||
### Deliverable
|
||||
- Alle 6 bugs gefixed
|
||||
- PROMPT-LOG.md bijgewerkt
|
||||
- Korte notities per bug: wat was het probleem, hoe opgelost
|
||||
- GitHub repository met correcte structuur
|
||||
- .cursorrules file
|
||||
- README.md
|
||||
- docs/ folder met templates
|
||||
|
||||
---
|
||||
|
||||
## Huiswerk (2 uur)
|
||||
|
||||
### Code Review Je Eigen Project
|
||||
### Bouw Project Foundation
|
||||
|
||||
**Deel 1: Self-Review met AI (1 uur)**
|
||||
- Kies 3 belangrijke files uit je eindproject
|
||||
- Laat AI ze reviewen met een goede prompt
|
||||
- Documenteer bevindingen in `AI-DECISIONS.md`
|
||||
**Deel 1: Base Components (1 uur)**
|
||||
|
||||
**Per file noteer:**
|
||||
- Welke issues AI vond
|
||||
- Welke je hebt gefixed
|
||||
- Welke je bewust negeert (en waarom)
|
||||
Maak basis UI components met AI hulp:
|
||||
- src/components/ui/Button.tsx
|
||||
- src/components/ui/Input.tsx
|
||||
- src/components/ui/Card.tsx
|
||||
- src/components/layout/Header.tsx
|
||||
- src/components/layout/Footer.tsx
|
||||
|
||||
**Deel 2: Refactoring (45 min)**
|
||||
- Kies 1 component dat te complex is
|
||||
- Vraag AI om refactoring suggesties
|
||||
- Implementeer de verbeteringen
|
||||
- Vergelijk before/after
|
||||
Requirements:
|
||||
- TypeScript interfaces voor props
|
||||
- Tailwind styling
|
||||
- Responsive design
|
||||
- Volg je .cursorrules
|
||||
|
||||
**Deel 3: Debugging Checklist (15 min)**
|
||||
- Maak persoonlijke debugging checklist
|
||||
- Wat check je eerst bij errors?
|
||||
- Welke prompts werken goed voor jou?
|
||||
**Deel 2: Supabase Setup (30 min)**
|
||||
|
||||
1. Maak Supabase project (of hergebruik van Les 9)
|
||||
2. Configureer src/lib/supabase.ts
|
||||
3. Voeg env vars toe aan .env.local
|
||||
4. Test connectie
|
||||
|
||||
**Deel 3: Eerste Feature (30 min)**
|
||||
|
||||
Kies je eindproject en implementeer 1 basisfeature:
|
||||
- Recipe Generator: ingredient input form
|
||||
- Budget Buddy: expense entry form
|
||||
- Travel Planner: destination search
|
||||
|
||||
Commit en push!
|
||||
|
||||
### Deliverable
|
||||
- AI-DECISIONS.md met review bevindingen
|
||||
- 1 gerefactored component
|
||||
- Persoonlijke debugging checklist
|
||||
- Werkende UI components
|
||||
- Supabase connectie
|
||||
- 1 basic feature
|
||||
- Alle commits met goede messages
|
||||
|
||||
---
|
||||
|
||||
## Leerdoelen
|
||||
Na deze les kan de student:
|
||||
- Error messages lezen en begrijpen
|
||||
- Effectieve debugging prompts schrijven voor AI
|
||||
- Browser DevTools gebruiken voor debugging
|
||||
- Code laten reviewen door AI
|
||||
- Feedback van AI kritisch evalueren
|
||||
- Refactoring uitvoeren met AI suggesties
|
||||
- Documenteren wat geleerd is van debugging sessies
|
||||
- Een professionele project structuur opzetten
|
||||
- File naming conventions toepassen
|
||||
- Een effectieve .cursorrules file schrijven
|
||||
- Git best practices volgen
|
||||
- Environment variables correct beheren
|
||||
- Een README.md schrijven
|
||||
- Project documentatie structureren
|
||||
|
||||
@@ -1,329 +1,336 @@
|
||||
# Les 15: Vercel AI SDK - AI Features in je App
|
||||
# Les 15: MCP & Context Management
|
||||
|
||||
---
|
||||
|
||||
## Hoofdstuk
|
||||
**Hoofdstuk 3: Advanced** (Les 10-18)
|
||||
**Deel 4: Advanced AI Features** (Les 13-18)
|
||||
|
||||
## Beschrijving
|
||||
Bouw AI-powered features in je apps met de Vercel AI SDK. Leer hoe je chat interfaces, streaming responses en AI-gegenereerde content implementeert.
|
||||
Leer werken met Model Context Protocol (MCP) en geavanceerd context management. Begrijp hoe je AI tools maximale context geeft voor betere resultaten.
|
||||
|
||||
---
|
||||
|
||||
## Te Behandelen
|
||||
|
||||
### Waarom Vercel AI SDK?
|
||||
### Groepsdiscussie (15 min)
|
||||
Bespreek klassikaal de project setup ervaringen uit Les 14 - welke structuur conventies werken goed en welke niet?
|
||||
|
||||
**Het probleem:** Direct API calls naar OpenAI/Anthropic zijn complex:
|
||||
- Streaming handmatig implementeren
|
||||
- Error handling
|
||||
- State management
|
||||
### Wat is Context?
|
||||
|
||||
**De oplossing:** Vercel AI SDK
|
||||
- Simpele React hooks
|
||||
- Built-in streaming
|
||||
- Provider-agnostic (OpenAI, Anthropic, etc.)
|
||||
- Edge-ready
|
||||
**Context = wat de AI weet over jouw situatie**
|
||||
|
||||
**Soorten context:**
|
||||
- **Code context:** welke files, welke functies
|
||||
- **Project context:** tech stack, conventies
|
||||
- **Taak context:** wat je probeert te bereiken
|
||||
- **Historische context:** eerdere conversatie
|
||||
|
||||
**Meer context = betere antwoorden**
|
||||
|
||||
---
|
||||
|
||||
### Installatie & Setup
|
||||
### Model Context Protocol (MCP)
|
||||
|
||||
```bash
|
||||
npm install ai @ai-sdk/openai
|
||||
# of voor Anthropic:
|
||||
npm install ai @ai-sdk/anthropic
|
||||
**Wat is MCP?**
|
||||
- Open protocol van Anthropic
|
||||
- Standaard manier om AI models context te geven
|
||||
- Verbindt AI met externe tools en data
|
||||
|
||||
**Waarom MCP?**
|
||||
- AI kan nu "tools gebruiken"
|
||||
- Toegang tot je filesystem
|
||||
- Database queries uitvoeren
|
||||
- Web searches doen
|
||||
- En meer...
|
||||
|
||||
**Hoe werkt het:**
|
||||
```
|
||||
|
||||
**Environment variable:**
|
||||
```bash
|
||||
# .env.local
|
||||
OPENAI_API_KEY=sk-xxxxx
|
||||
Jij → vraag → AI → MCP → Tool → resultaat → AI → antwoord → Jij
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Core Hooks
|
||||
### MCP in de Praktijk
|
||||
|
||||
#### useChat - Voor Conversaties
|
||||
**Cursor gebruikt MCP onder de hood:**
|
||||
- `@file` mentions = file context via MCP
|
||||
- `@codebase` = codebase search via MCP
|
||||
- `@Docs` = documentation lookup via MCP
|
||||
- `@Web` = web search via MCP
|
||||
|
||||
```tsx
|
||||
'use client'
|
||||
import { useChat } from 'ai/react'
|
||||
**Claude Desktop met MCP:**
|
||||
- Kan tools uitvoeren
|
||||
- Filesystem access
|
||||
- Terminal commands
|
||||
- Database queries
|
||||
|
||||
export function ChatComponent() {
|
||||
const { messages, input, handleInputChange, handleSubmit, isLoading } = useChat()
|
||||
---
|
||||
|
||||
return (
|
||||
<div className="flex flex-col h-screen">
|
||||
<div className="flex-1 overflow-y-auto p-4">
|
||||
{messages.map(m => (
|
||||
<div key={m.id} className={m.role === 'user' ? 'text-right' : 'text-left'}>
|
||||
<span className="inline-block p-2 rounded-lg bg-gray-100">
|
||||
{m.content}
|
||||
</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
### Context Management Strategieën
|
||||
|
||||
<form onSubmit={handleSubmit} className="p-4 border-t">
|
||||
<input
|
||||
value={input}
|
||||
onChange={handleInputChange}
|
||||
placeholder="Type a message..."
|
||||
className="w-full p-2 border rounded"
|
||||
/>
|
||||
<button type="submit" disabled={isLoading}>
|
||||
{isLoading ? 'Sending...' : 'Send'}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
**1. Expliciete Context**
|
||||
Geef context direct in je prompt:
|
||||
```
|
||||
Context: Next.js 14 project met TypeScript en Supabase.
|
||||
Dit is een e-commerce app voor verkoop van boeken.
|
||||
|
||||
Vraag: Hoe implementeer ik een winkelwagen?
|
||||
```
|
||||
|
||||
#### useCompletion - Voor Single Completions
|
||||
**2. File Context**
|
||||
Gebruik @ mentions om relevante files toe te voegen:
|
||||
```
|
||||
@src/types/product.ts
|
||||
@src/lib/supabase.ts
|
||||
Hoe maak ik een addToCart functie?
|
||||
```
|
||||
|
||||
```tsx
|
||||
import { useCompletion } from 'ai/react'
|
||||
**3. Project Context**
|
||||
Gebruik .cursorrules of Claude Project instructions:
|
||||
```
|
||||
# In .cursorrules
|
||||
Dit project is een e-commerce platform.
|
||||
Alle prices zijn in cents (niet euros).
|
||||
```
|
||||
|
||||
export function SummaryComponent() {
|
||||
const { completion, input, handleInputChange, handleSubmit, isLoading } = useCompletion()
|
||||
**4. Fresh Context**
|
||||
Begin nieuwe chat voor nieuw onderwerp:
|
||||
- Voorkomt context vervuiling
|
||||
- AI raakt niet in de war met oude info
|
||||
|
||||
return (
|
||||
<div>
|
||||
<form onSubmit={handleSubmit}>
|
||||
<textarea
|
||||
value={input}
|
||||
onChange={handleInputChange}
|
||||
placeholder="Paste text to summarize..."
|
||||
/>
|
||||
<button type="submit">Summarize</button>
|
||||
</form>
|
||||
{completion && <p>{completion}</p>}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
---
|
||||
|
||||
### @ Mentions Strategisch Gebruiken
|
||||
|
||||
**Cursor @ mentions:**
|
||||
|
||||
| Mention | Wanneer | Voorbeeld |
|
||||
|---------|---------|-----------|
|
||||
| `@file.tsx` | Specifieke file context | `@Button.tsx hoe voeg ik loading toe?` |
|
||||
| `@folder/` | Hele folder context | `@components/ welke patterns gebruik ik?` |
|
||||
| `@codebase` | Zoeken in project | `@codebase waar handle ik auth?` |
|
||||
| `@Docs` | Officiële documentatie | `@Docs Next.js App Router` |
|
||||
| `@Web` | Live web search | `@Web Supabase RLS policies` |
|
||||
|
||||
**Best practice:** Combineer mentions voor rijke context:
|
||||
```
|
||||
@src/components/auth/LoginForm.tsx
|
||||
@src/lib/supabase.ts
|
||||
@Docs Supabase Auth
|
||||
|
||||
Hoe voeg ik Google OAuth toe aan mijn login?
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### API Routes
|
||||
### Claude Projects voor Persistente Context
|
||||
|
||||
**app/api/chat/route.ts:**
|
||||
```typescript
|
||||
import { openai } from '@ai-sdk/openai'
|
||||
import { streamText } from 'ai'
|
||||
**Wat kun je toevoegen aan een Project:**
|
||||
- Instructies (system prompt)
|
||||
- Files (code, docs, schema's)
|
||||
- Kennis die over sessies heen blijft
|
||||
|
||||
export async function POST(req: Request) {
|
||||
const { messages } = await req.json()
|
||||
**Project Instructions Template:**
|
||||
```markdown
|
||||
# Project: [Naam]
|
||||
|
||||
const result = streamText({
|
||||
model: openai('gpt-4o-mini'),
|
||||
system: 'You are a helpful cooking assistant. Suggest recipes based on ingredients.',
|
||||
messages,
|
||||
})
|
||||
## Tech Stack
|
||||
- Next.js 14 met App Router
|
||||
- TypeScript strict
|
||||
- Tailwind CSS
|
||||
- Supabase
|
||||
|
||||
return result.toDataStreamResponse()
|
||||
}
|
||||
## Code Conventies
|
||||
[jouw conventies]
|
||||
|
||||
## Database Schema
|
||||
[beschrijf je schema]
|
||||
|
||||
## Current Focus
|
||||
[waar werk je nu aan]
|
||||
```
|
||||
|
||||
**Met custom system prompt:**
|
||||
```typescript
|
||||
const result = streamText({
|
||||
model: openai('gpt-4o-mini'),
|
||||
system: `You are a recipe assistant for the AI Recipe Generator app.
|
||||
|
||||
When the user provides ingredients:
|
||||
1. Suggest 2-3 recipes they could make
|
||||
2. List required additional ingredients (if any)
|
||||
3. Provide brief cooking instructions
|
||||
|
||||
Be concise and practical.`,
|
||||
messages,
|
||||
})
|
||||
```
|
||||
**Tip:** Upload je database schema, README, en belangrijke types files.
|
||||
|
||||
---
|
||||
|
||||
### Streaming Responses
|
||||
### Context Windows en Limieten
|
||||
|
||||
**Waarom streaming?**
|
||||
- Betere UX (user ziet direct resultaat)
|
||||
- Snellere perceived performance
|
||||
- Geen wachten op complete response
|
||||
**Wat is een context window?**
|
||||
- Maximum hoeveelheid tekst die AI kan "zien"
|
||||
- Gemeten in tokens (±4 karakters per token)
|
||||
|
||||
**Hoe het werkt:**
|
||||
1. Server stuurt tokens één voor één
|
||||
2. Client rendert elke token direct
|
||||
3. User ziet "typing" effect
|
||||
**Limieten per model:**
|
||||
| Model | Context Window |
|
||||
|-------|---------------|
|
||||
| GPT-4o | 128K tokens |
|
||||
| Claude 3 Sonnet | 200K tokens |
|
||||
| Claude 3 Opus | 200K tokens |
|
||||
|
||||
**Loading indicator:**
|
||||
```tsx
|
||||
{isLoading && (
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="animate-pulse">●</div>
|
||||
<span>AI is thinking...</span>
|
||||
</div>
|
||||
)}
|
||||
```
|
||||
**Praktisch:**
|
||||
- Lange conversaties → context vol
|
||||
- Veel file mentions → context vol
|
||||
- Start fresh chat wanneer nodig
|
||||
|
||||
**Signs van vol context:**
|
||||
- AI vergeet eerdere instructies
|
||||
- Antwoorden worden minder relevant
|
||||
- AI herhaalt zichzelf
|
||||
|
||||
---
|
||||
|
||||
### Integratie met Supabase
|
||||
### Context Hygiene
|
||||
|
||||
**Conversations opslaan:**
|
||||
**Do's:**
|
||||
- Geef alleen relevante context
|
||||
- Wees specifiek in file mentions
|
||||
- Start nieuwe chat voor nieuw onderwerp
|
||||
- Gebruik project-level context voor consistentie
|
||||
|
||||
```typescript
|
||||
// Maak tabel in Supabase:
|
||||
// conversations: id, user_id, created_at
|
||||
// messages: id, conversation_id, role, content, created_at
|
||||
|
||||
// Na elke message:
|
||||
async function saveMessage(conversationId: string, role: string, content: string) {
|
||||
await supabase.from('messages').insert({
|
||||
conversation_id: conversationId,
|
||||
role,
|
||||
content
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
**In je component:**
|
||||
```tsx
|
||||
const { messages, input, handleSubmit } = useChat({
|
||||
onFinish: async (message) => {
|
||||
await saveMessage(conversationId, message.role, message.content)
|
||||
}
|
||||
})
|
||||
```
|
||||
**Don'ts:**
|
||||
- Hele codebase als context geven
|
||||
- Oude irrelevante chats voortzetten
|
||||
- Te veel files tegelijk mentionen
|
||||
- Context herhalen die AI al heeft
|
||||
|
||||
---
|
||||
|
||||
### Error Handling
|
||||
### Debugging met Context
|
||||
|
||||
```tsx
|
||||
const { messages, error, reload } = useChat()
|
||||
**Wanneer AI verkeerde antwoorden geeft:**
|
||||
|
||||
{error && (
|
||||
<div className="p-4 bg-red-100 text-red-700 rounded">
|
||||
<p>Something went wrong. Please try again.</p>
|
||||
<button onClick={reload}>Retry</button>
|
||||
</div>
|
||||
)}
|
||||
1. **Check context:** Heeft AI de juiste files?
|
||||
2. **Check instructies:** Zijn project rules geladen?
|
||||
3. **Fresh start:** Begin nieuwe chat
|
||||
4. **Explicieter:** Voeg meer context toe in prompt
|
||||
|
||||
**Debug prompt:**
|
||||
```
|
||||
Ik merk dat je antwoord niet klopt.
|
||||
Heb je toegang tot @src/lib/auth.ts?
|
||||
Dit is de huidige implementatie: [plak code]
|
||||
Kun je opnieuw kijken?
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Cost Management
|
||||
|
||||
**Model keuze:**
|
||||
| Model | Kosten | Gebruik voor |
|
||||
|-------|--------|--------------|
|
||||
| gpt-4o-mini | Goedkoop | Meeste taken |
|
||||
| gpt-4o | Duur | Complexe reasoning |
|
||||
| claude-3-haiku | Goedkoop | Simpele taken |
|
||||
| claude-3-sonnet | Medium | Balans |
|
||||
|
||||
**Bespaartips:**
|
||||
1. Gebruik gpt-4o-mini als default
|
||||
2. Korte system prompts
|
||||
3. Beperk conversation history
|
||||
4. Caching waar mogelijk
|
||||
|
||||
---
|
||||
|
||||
## Tools
|
||||
- Vercel AI SDK (`ai` package)
|
||||
- Next.js API Routes
|
||||
- OpenAI API / Anthropic API
|
||||
- Cursor
|
||||
- Supabase
|
||||
- Cursor (@ mentions)
|
||||
- Claude Projects
|
||||
- ChatGPT
|
||||
|
||||
---
|
||||
|
||||
## Lesopdracht (2 uur)
|
||||
|
||||
### Bouw een AI Chat Component
|
||||
### Context Management Oefenen
|
||||
|
||||
**Deel 1: Setup (20 min)**
|
||||
1. `npm install ai @ai-sdk/openai`
|
||||
2. Voeg `OPENAI_API_KEY` toe aan `.env.local`
|
||||
3. Maak `app/api/chat/route.ts`
|
||||
**Deel 1: @ Mentions Mastery (45 min)**
|
||||
|
||||
**Deel 2: Basic Chat (40 min)**
|
||||
1. Maak `components/Chat.tsx`
|
||||
2. Implementeer `useChat` hook
|
||||
3. Bouw chat UI met Tailwind
|
||||
4. Test streaming werkt
|
||||
Voer deze taken uit in Cursor:
|
||||
|
||||
**Deel 3: System Prompt (30 min)**
|
||||
1. Schrijf system prompt voor je eindproject:
|
||||
- Recipe Generator: cooking assistant
|
||||
- Budget Buddy: financial advisor
|
||||
- Travel Planner: travel expert
|
||||
2. Test met relevante vragen
|
||||
1. **Single file context:**
|
||||
- Open je TodoList component
|
||||
- Vraag: "@TodoList.tsx Hoe kan ik infinite scroll toevoegen?"
|
||||
- Noteer kwaliteit antwoord
|
||||
|
||||
**Deel 4: Supabase Integratie (30 min)**
|
||||
1. Maak `messages` tabel
|
||||
2. Sla berichten op met `onFinish`
|
||||
3. Laad history bij page load
|
||||
2. **Multi-file context:**
|
||||
- Vraag: "@src/components/ @src/types/ Welke types mis ik?"
|
||||
- Noteer hoe context helpt
|
||||
|
||||
3. **Docs context:**
|
||||
- Vraag: "@Docs Supabase realtime Hoe voeg ik real-time updates toe aan mijn todo app?"
|
||||
- Noteer of antwoord up-to-date is
|
||||
|
||||
4. **Codebase search:**
|
||||
- Vraag: "@codebase Waar handle ik error states?"
|
||||
- Noteer of het de juiste plekken vindt
|
||||
|
||||
**Deel 2: Claude Project Setup (30 min)**
|
||||
|
||||
1. Maak Claude Project voor je eindproject
|
||||
2. Schrijf comprehensive instructions
|
||||
3. Upload 3-5 belangrijke files:
|
||||
- Database schema/types
|
||||
- Main component
|
||||
- Supabase client
|
||||
4. Test met 3 vragen
|
||||
|
||||
**Deel 3: Context Vergelijking (45 min)**
|
||||
|
||||
Voer dezelfde taak uit met:
|
||||
1. Geen context (nieuwe chat, geen mentions)
|
||||
2. File context (@mentions)
|
||||
3. Project context (Claude Project)
|
||||
|
||||
Taak: "Implementeer een search feature voor todos"
|
||||
|
||||
Noteer:
|
||||
- Kwaliteit code
|
||||
- Relevantie voor jouw project
|
||||
- Hoeveel aanpassing nodig
|
||||
|
||||
### Deliverable
|
||||
- Werkende AI chat met streaming
|
||||
- Custom system prompt
|
||||
- Messages opgeslagen in Supabase
|
||||
- Notities over @ mentions effectiviteit
|
||||
- Claude Project met instructions
|
||||
- Context vergelijkingsnotities
|
||||
|
||||
---
|
||||
|
||||
## Huiswerk (2 uur)
|
||||
|
||||
### Bouw AI Feature voor Eindproject
|
||||
### Optimaliseer Je Context Strategie
|
||||
|
||||
**Deel 1: Core AI Feature (1 uur)**
|
||||
**Deel 1: .cursorrules Perfectioneren (30 min)**
|
||||
|
||||
Implementeer de AI chat die past bij je eindproject:
|
||||
Update je .cursorrules met:
|
||||
- Specifieke file structure info
|
||||
- Naming conventions met voorbeelden
|
||||
- Common patterns in je project
|
||||
- DON'Ts specifiek voor jouw situatie
|
||||
|
||||
| Project | AI Feature |
|
||||
|---------|-----------|
|
||||
| Recipe Generator | "Wat kan ik maken met kip en rijst?" |
|
||||
| Budget Buddy | "Analyseer mijn uitgaven deze maand" |
|
||||
| Travel Planner | "Plan een weekend Barcelona" |
|
||||
**Deel 2: Claude Project Uitbreiden (45 min)**
|
||||
|
||||
- Custom system prompt
|
||||
- Context uit je database meegeven
|
||||
1. Upload alle relevante project files
|
||||
2. Test met complexe vragen:
|
||||
- "Hoe implementeer ik feature X?"
|
||||
- "Review mijn auth implementatie"
|
||||
- "Wat ontbreekt er nog?"
|
||||
3. Itereer op instructions
|
||||
|
||||
**Deel 2: UX Polish (30 min)**
|
||||
**Deel 3: Context Documentation (45 min)**
|
||||
|
||||
Voeg toe:
|
||||
- Streaming indicator
|
||||
- Suggested prompts / quick actions
|
||||
- Copy response button
|
||||
- Clear chat button
|
||||
- Error handling
|
||||
Maak `docs/CONTEXT-GUIDE.md`:
|
||||
```markdown
|
||||
# Context Guide voor [Project]
|
||||
|
||||
**Deel 3: Documentatie (30 min)**
|
||||
## Cursor @ Mentions
|
||||
- Voor UI changes: @src/components/
|
||||
- Voor data logic: @src/lib/ @src/hooks/
|
||||
- Voor types: @src/types/
|
||||
|
||||
Maak `docs/AI-FEATURE.md`:
|
||||
- Welke AI feature heb je gebouwd?
|
||||
- Wat doet de system prompt?
|
||||
- Hoe integreert het met Supabase?
|
||||
- Welke model keuzes heb je gemaakt?
|
||||
## Claude Project
|
||||
- Project URL: [link]
|
||||
- Uploaded files: [lijst]
|
||||
- Best practices: [jouw learnings]
|
||||
|
||||
## Common Prompts
|
||||
[verzameling werkende prompts]
|
||||
```
|
||||
|
||||
### Deliverable
|
||||
- AI feature in eindproject
|
||||
- Deployed preview
|
||||
- AI-FEATURE.md documentatie
|
||||
- Geoptimaliseerde .cursorrules
|
||||
- Complete Claude Project
|
||||
- docs/CONTEXT-GUIDE.md
|
||||
|
||||
---
|
||||
|
||||
## Leerdoelen
|
||||
Na deze les kan de student:
|
||||
- Vercel AI SDK installeren en configureren
|
||||
- `useChat` en `useCompletion` hooks gebruiken
|
||||
- Streaming responses implementeren
|
||||
- API routes opzetten voor AI providers
|
||||
- Custom system prompts schrijven
|
||||
- Chat history opslaan in Supabase
|
||||
- Error handling en loading states implementeren
|
||||
- Kostenbewust omgaan met AI APIs
|
||||
- Uitleggen wat context is en waarom het belangrijk is
|
||||
- Model Context Protocol (MCP) begrijpen
|
||||
- @ mentions strategisch gebruiken in Cursor
|
||||
- Een Claude Project opzetten met effectieve instructions
|
||||
- Context windows en limieten begrijpen
|
||||
- Context management best practices toepassen
|
||||
- Debuggen wanneer AI verkeerde antwoorden geeft door context issues
|
||||
|
||||
@@ -1,227 +1,340 @@
|
||||
# Les 16: Deployment & Production
|
||||
# Les 16: Mastering Cursor
|
||||
|
||||
---
|
||||
|
||||
## Hoofdstuk
|
||||
**Hoofdstuk 3: Advanced** (Les 10-18)
|
||||
**Deel 4: Advanced AI Features** (Les 13-18)
|
||||
|
||||
## Beschrijving
|
||||
Deploy je eindproject naar productie. Leer environment variables, Vercel deployment, en basis performance optimalisatie.
|
||||
Verdieping in Cursor's geavanceerde features. Leer model keuze, Composer Mode, @ mentions, en .cursorrules optimaal gebruiken.
|
||||
|
||||
---
|
||||
|
||||
## Te Behandelen
|
||||
|
||||
### Vercel Deployment Flow
|
||||
### Groepsdiscussie (15 min)
|
||||
Bespreek klassikaal de context management ervaringen uit Les 15 - welke strategieën werkten het beste?
|
||||
|
||||
**Hoe Vercel werkt:**
|
||||
1. Connect GitHub repository
|
||||
2. Push naar main → automatische deploy
|
||||
3. Push naar andere branch → preview URL
|
||||
4. Alles automatisch (build, SSL, CDN)
|
||||
### Model Keuze
|
||||
|
||||
**Waarom Vercel voor Next.js:**
|
||||
- Gemaakt door dezelfde makers
|
||||
- Zero-config deployment
|
||||
- Gratis tier ruim voldoende
|
||||
- Automatische HTTPS
|
||||
- Global CDN
|
||||
**Wanneer welk model?**
|
||||
|
||||
| Model | Gebruik voor | Kosten |
|
||||
|-------|-------------|--------|
|
||||
| **Haiku** | Simpele taken, autocomplete | Goedkoop |
|
||||
| **Sonnet** | Dagelijks werk, de meeste taken | Medium |
|
||||
| **Opus** | Complexe architectuur, multi-file | Duur |
|
||||
|
||||
**Vuistregels:**
|
||||
- Tab completion: Haiku (automatisch)
|
||||
- CMD+K: Sonnet (default)
|
||||
- Composer: Sonnet of Opus
|
||||
- Complexe debugging: Opus
|
||||
|
||||
---
|
||||
|
||||
### Environment Variables in Vercel
|
||||
### Composer Mode Diepgaand
|
||||
|
||||
**Lokaal (.env.local) vs Productie (Vercel Dashboard):**
|
||||
**Wat is Composer?**
|
||||
Multi-file generatie in één keer. Cursor plant en voert wijzigingen uit over meerdere bestanden.
|
||||
|
||||
| Waar | Bestand/Locatie | Voorbeeld |
|
||||
|------|-----------------|-----------|
|
||||
| Lokaal | `.env.local` | Development |
|
||||
| Vercel | Dashboard → Settings → Env Vars | Production |
|
||||
**Wanneer Composer gebruiken:**
|
||||
- Nieuwe feature met meerdere components
|
||||
- Refactoring over meerdere files
|
||||
- Boilerplate generatie
|
||||
- Complexe wijzigingen
|
||||
|
||||
**Stap voor stap:**
|
||||
1. Ga naar je Vercel project
|
||||
2. Settings → Environment Variables
|
||||
3. Voeg toe:
|
||||
- `NEXT_PUBLIC_SUPABASE_URL`
|
||||
- `NEXT_PUBLIC_SUPABASE_ANON_KEY`
|
||||
- `OPENAI_API_KEY`
|
||||
4. Selecteer environment (Production, Preview, Development)
|
||||
5. Save & Redeploy
|
||||
**Composer Workflow:**
|
||||
1. CMD+I opent Composer
|
||||
2. Beschrijf je doel duidelijk
|
||||
3. Voeg context toe met @ mentions
|
||||
4. Laat Cursor plannen
|
||||
5. Review het plan
|
||||
6. Accept of reject per file
|
||||
7. Itereer met feedback
|
||||
|
||||
**Let op:**
|
||||
- `NEXT_PUBLIC_` prefix = zichtbaar in browser
|
||||
- Zonder prefix = alleen server-side (API routes)
|
||||
**Voorbeeld prompt:**
|
||||
```
|
||||
Create a user profile page with:
|
||||
- @components/ui/ style components
|
||||
- Profile header with avatar
|
||||
- Edit form with validation
|
||||
- Save to @lib/supabase.ts
|
||||
- Loading and error states
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Supabase Productie Setup
|
||||
### @ Mentions Systeem
|
||||
|
||||
**Redirect URLs configureren:**
|
||||
1. Ga naar Supabase → Authentication → URL Configuration
|
||||
2. Voeg toe bij "Redirect URLs":
|
||||
- `https://jouw-app.vercel.app/**`
|
||||
- `https://jouw-app.vercel.app`
|
||||
**Alle types:**
|
||||
|
||||
**Waarom:**
|
||||
- Auth redirects werken alleen naar toegestane URLs
|
||||
- Wildcards (`**`) voor sub-routes
|
||||
| Mention | Wat het doet | Voorbeeld |
|
||||
|---------|--------------|-----------|
|
||||
| `@file.tsx` | Specifieke file | `@Button.tsx` |
|
||||
| `@folder/` | Hele folder | `@components/` |
|
||||
| `@codebase` | Zoek in codebase | `@codebase auth logic` |
|
||||
| `@Docs` | Officiële docs | `@Docs Next.js routing` |
|
||||
| `@Web` | Web zoeken | `@Web Supabase auth setup` |
|
||||
|
||||
**Best practices:**
|
||||
- Wees specifiek met file mentions
|
||||
- Gebruik folder mentions voor context
|
||||
- @Docs voor up-to-date informatie
|
||||
- Combineer mentions voor betere context
|
||||
|
||||
---
|
||||
|
||||
### Deployment Checklist
|
||||
### .cursorrules Advanced
|
||||
|
||||
**Voor deployment:**
|
||||
- [ ] `npm run build` werkt lokaal
|
||||
- [ ] Geen TypeScript errors
|
||||
- [ ] Environment variables gedocumenteerd in `.env.example`
|
||||
- [ ] `.gitignore` bevat `.env*.local`
|
||||
- [ ] README up-to-date
|
||||
**Meerdere rules files:**
|
||||
|
||||
**Na deployment:**
|
||||
- [ ] App laadt correct
|
||||
- [ ] Auth werkt (login/logout)
|
||||
- [ ] Data wordt opgehaald uit Supabase
|
||||
- [ ] AI features werken (indien van toepassing)
|
||||
- [ ] Geen console errors
|
||||
```
|
||||
.cursor/
|
||||
└── rules/
|
||||
├── general.mdc # Project-brede regels
|
||||
├── components.mdc # Component conventies
|
||||
├── api.mdc # API route regels
|
||||
└── testing.mdc # Test conventies
|
||||
```
|
||||
|
||||
**Effectieve rules schrijven:**
|
||||
|
||||
```markdown
|
||||
# Component Rules
|
||||
|
||||
## Structure
|
||||
Alle components moeten volgen:
|
||||
1. Props interface bovenaan
|
||||
2. Component function
|
||||
3. Named export onderaan
|
||||
|
||||
## Example
|
||||
\`\`\`tsx
|
||||
interface ButtonProps {
|
||||
label: string
|
||||
onClick: () => void
|
||||
variant?: 'primary' | 'secondary'
|
||||
}
|
||||
|
||||
export function Button({ label, onClick, variant = 'primary' }: ButtonProps) {
|
||||
return (
|
||||
<button onClick={onClick} className={...}>
|
||||
{label}
|
||||
</button>
|
||||
)
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
## DON'Ts
|
||||
- Geen default exports
|
||||
- Geen inline styles
|
||||
- Geen any types
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Performance Basics
|
||||
### Codebase Indexing
|
||||
|
||||
**Lighthouse Audit:**
|
||||
1. Open Chrome DevTools
|
||||
2. Tab "Lighthouse"
|
||||
3. Klik "Analyze page load"
|
||||
4. Aim for score >80 in elke categorie
|
||||
**Hoe Cursor indexeert:**
|
||||
- Scant alle files in je project
|
||||
- Bouwt semantic understanding
|
||||
- Gebruikt voor autocomplete en context
|
||||
|
||||
**Quick wins:**
|
||||
- Gebruik Next.js `Image` component (niet `<img>`)
|
||||
- Lazy load components die niet direct nodig zijn
|
||||
- Verwijder ongebruikte dependencies
|
||||
**Optimaliseren:**
|
||||
1. Goede `.cursorignore` (node_modules, .next, etc.)
|
||||
2. Semantische naming
|
||||
3. Duidelijke file structuur
|
||||
4. Comments waar nodig
|
||||
|
||||
**Re-indexeren:**
|
||||
CMD+Shift+P → "Reindex"
|
||||
|
||||
---
|
||||
|
||||
### Security Checklist
|
||||
### Cost Management
|
||||
|
||||
**Belangrijk voor productie:**
|
||||
- [ ] API keys nooit in client-side code
|
||||
- [ ] Supabase RLS enabled (Row Level Security)
|
||||
- [ ] Error messages geven geen gevoelige info
|
||||
- [ ] HTTPS (automatisch via Vercel)
|
||||
**Token gebruik monitoren:**
|
||||
- Cursor toont token count in chat
|
||||
- Check monthly usage in settings
|
||||
|
||||
**Bespaartips:**
|
||||
1. Gebruik Haiku voor simpele taken
|
||||
2. Beperk context (niet hele codebase)
|
||||
3. Wees specifiek in prompts
|
||||
4. Fresh chat voor nieuwe onderwerpen
|
||||
|
||||
**Free tier strategie:**
|
||||
- Focus op Tab completion (onbeperkt)
|
||||
- Gebruik CMD+K spaarzaam
|
||||
- Composer alleen voor grote taken
|
||||
|
||||
---
|
||||
|
||||
### Monitoring Basics
|
||||
### Debugging met Cursor
|
||||
|
||||
**Vercel Dashboard toont:**
|
||||
- Deployments history
|
||||
- Function logs
|
||||
- Analytics (optioneel)
|
||||
**AI-Assisted Debugging:**
|
||||
|
||||
**Supabase Dashboard toont:**
|
||||
- Database usage
|
||||
- Auth logs
|
||||
- API requests
|
||||
**Stap 1: Error identificeren**
|
||||
```
|
||||
@file-met-error.tsx
|
||||
Ik krijg deze error: [plak error]
|
||||
Wat gaat er mis?
|
||||
```
|
||||
|
||||
**Stap 2: Context toevoegen**
|
||||
```
|
||||
@file-met-error.tsx
|
||||
@gerelateerde-file.ts
|
||||
De error treedt op wanneer ik X doe.
|
||||
Console log toont: [data]
|
||||
```
|
||||
|
||||
**Stap 3: Fix implementeren**
|
||||
- Selecteer code met error
|
||||
- CMD+K → "Fix this error: [beschrijving]"
|
||||
- Review en test
|
||||
|
||||
---
|
||||
|
||||
### Refactoring met Cursor
|
||||
|
||||
**Pattern 1: Extract Component**
|
||||
```
|
||||
Selecteer JSX block → CMD+K
|
||||
"Extract this into a separate component called ProductCard"
|
||||
```
|
||||
|
||||
**Pattern 2: Extract Hook**
|
||||
```
|
||||
Selecteer state + useEffect → CMD+K
|
||||
"Extract this into a custom hook called useProductData"
|
||||
```
|
||||
|
||||
**Pattern 3: Improve Performance**
|
||||
```
|
||||
@Component.tsx
|
||||
"Optimize this component:
|
||||
- Add memoization waar nodig
|
||||
- Fix unnecessary re-renders
|
||||
- Improve loading performance"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Tools
|
||||
- Vercel
|
||||
- GitHub
|
||||
- Supabase
|
||||
- Chrome DevTools (Lighthouse)
|
||||
- Cursor
|
||||
- Claude models (Haiku/Sonnet/Opus)
|
||||
- .cursorrules
|
||||
|
||||
---
|
||||
|
||||
## Lesopdracht (2 uur)
|
||||
|
||||
### Deploy Je Eindproject
|
||||
### Multi-Step Form Wizard
|
||||
|
||||
**Deel 1: Pre-Deployment Check (30 min)**
|
||||
**Bouw met Composer:**
|
||||
|
||||
Run door de checklist:
|
||||
1. `npm run build` - fix eventuele errors
|
||||
2. Check TypeScript errors
|
||||
3. Maak/update `.env.example`
|
||||
4. Update README met project info
|
||||
| Stap | Features |
|
||||
|------|----------|
|
||||
| 1 | Personal info (naam, email) |
|
||||
| 2 | Preferences (theme, notifications) |
|
||||
| 3 | Review & confirm |
|
||||
| 4 | Success animation |
|
||||
|
||||
**Deel 2: Vercel Deployment (30 min)**
|
||||
**Requirements:**
|
||||
- Progress indicator
|
||||
- Per-stap validatie
|
||||
- localStorage persistence
|
||||
- TypeScript strict
|
||||
- Tailwind styling
|
||||
- Mobile responsive
|
||||
|
||||
1. Ga naar [vercel.com](https://vercel.com)
|
||||
2. "Add New Project"
|
||||
3. Import je GitHub repository
|
||||
4. Voeg environment variables toe
|
||||
5. Deploy!
|
||||
**Process:**
|
||||
|
||||
**Deel 3: Supabase Config (20 min)**
|
||||
**Deel 1: Composer Setup (30 min)**
|
||||
1. Open Composer (CMD+I)
|
||||
2. Schrijf comprehensive prompt
|
||||
3. Include @ mentions naar relevante files
|
||||
4. Kies Sonnet of Opus
|
||||
|
||||
1. Voeg Vercel URL toe aan Supabase redirect URLs
|
||||
2. Test auth in productie
|
||||
3. Verifieer data access
|
||||
**Deel 2: Generatie & Review (45 min)**
|
||||
1. Laat Composer genereren
|
||||
2. Review elke file
|
||||
3. Accept wat goed is
|
||||
4. Reject wat niet past
|
||||
|
||||
**Deel 4: Testing & Lighthouse (40 min)**
|
||||
|
||||
1. Test alle features in productie:
|
||||
- Login/logout
|
||||
- CRUD operaties
|
||||
- AI chat (indien aanwezig)
|
||||
2. Run Lighthouse audit
|
||||
3. Fix issues tot score >80
|
||||
4. Screenshot resultaat
|
||||
**Deel 3: Refinement (45 min)**
|
||||
1. Gebruik CMD+K voor kleine fixes
|
||||
2. Chat voor vragen
|
||||
3. Itereer tot het werkt
|
||||
|
||||
### Deliverable
|
||||
- Werkende productie URL
|
||||
- Lighthouse screenshot (score >80)
|
||||
- Test rapport: wat werkt, wat niet
|
||||
- Werkende form wizard
|
||||
- Notities: welk model wanneer, hoeveel iteraties
|
||||
|
||||
---
|
||||
|
||||
## Huiswerk (2 uur)
|
||||
|
||||
### Polish & Documentatie
|
||||
### Perfecte .cursorrules
|
||||
|
||||
**Deel 1: Bug Fixes (1 uur)**
|
||||
**Deel 1: Research (30 min)**
|
||||
- Zoek 3-5 .cursorrules voorbeelden online
|
||||
- Analyseer wat ze effectief maakt
|
||||
|
||||
1. Test je app grondig in productie
|
||||
2. Fix gevonden bugs
|
||||
3. Test edge cases:
|
||||
- Lege states
|
||||
- Error states
|
||||
- Loading states
|
||||
4. Redeploy
|
||||
**Deel 2: Write Comprehensive Rules (1 uur)**
|
||||
|
||||
**Deel 2: Performance Optimization (30 min)**
|
||||
Maak complete .cursorrules voor je eindproject:
|
||||
|
||||
1. Run Lighthouse opnieuw
|
||||
2. Fix top 3 performance issues
|
||||
3. Document wat je hebt verbeterd
|
||||
```markdown
|
||||
# [Project Naam]
|
||||
|
||||
**Deel 3: Documentatie Afronden (30 min)**
|
||||
## Tech Stack
|
||||
[Jouw stack]
|
||||
|
||||
Update je `README.md`:
|
||||
- Werkende productie URL
|
||||
- Features lijst
|
||||
- Tech stack
|
||||
- Setup instructies
|
||||
- Screenshots
|
||||
## Code Conventions
|
||||
[Jouw conventies]
|
||||
|
||||
Update `docs/`:
|
||||
- PROMPT-LOG.md (minimaal 10 entries)
|
||||
- AI-DECISIONS.md (minimaal 5 entries)
|
||||
## File Naming
|
||||
[Jouw regels]
|
||||
|
||||
## Component Structure
|
||||
[Jouw patterns]
|
||||
|
||||
## Styling
|
||||
[Tailwind regels]
|
||||
|
||||
## API Routes
|
||||
[Route conventies]
|
||||
|
||||
## Error Handling
|
||||
[Error patterns]
|
||||
|
||||
## DON'Ts
|
||||
[Wat te vermijden]
|
||||
```
|
||||
|
||||
**Deel 3: Test (30 min)**
|
||||
1. Start nieuw component
|
||||
2. Vraag Cursor om het te bouwen
|
||||
3. Check: volgt Cursor je regels?
|
||||
4. Itereer indien nodig
|
||||
|
||||
### Deliverable
|
||||
- Geoptimaliseerde productie app
|
||||
- Complete documentatie
|
||||
- Lighthouse score >85
|
||||
- Complete .cursorrules file
|
||||
- Screenshot van Cursor die regels volgt
|
||||
- Korte analyse: wat werkt goed, wat niet
|
||||
|
||||
---
|
||||
|
||||
## Leerdoelen
|
||||
Na deze les kan de student:
|
||||
- Een Next.js app deployen naar Vercel
|
||||
- Environment variables configureren in Vercel
|
||||
- Supabase redirect URLs instellen voor productie
|
||||
- Een deployment checklist doorlopen
|
||||
- Lighthouse gebruiken voor performance audit
|
||||
- Basis security checks uitvoeren
|
||||
- Productie monitoring begrijpen
|
||||
- Het juiste Claude model kiezen per taak
|
||||
- Composer Mode effectief gebruiken voor multi-file features
|
||||
- @ mentions strategisch inzetten voor context
|
||||
- Geavanceerde .cursorrules files schrijven
|
||||
- Codebase indexing optimaliseren
|
||||
- Token gebruik monitoren en kosten beheren
|
||||
- AI-assisted debugging toepassen
|
||||
- Refactoring uitvoeren met Cursor
|
||||
|
||||
@@ -1,187 +1,332 @@
|
||||
# Les 17: Eindopdracht Kickoff
|
||||
# Les 17: Vercel AI SDK - AI Features in je App
|
||||
|
||||
---
|
||||
|
||||
## Hoofdstuk
|
||||
**Hoofdstuk 3: Advanced** (Les 10-18)
|
||||
**Deel 4: Advanced AI Features** (Les 13-18)
|
||||
|
||||
## Beschrijving
|
||||
Bespreking van de eindopdracht requirements, planning maken, en laatste vragen beantwoorden voordat studenten zelfstandig verder werken.
|
||||
Bouw AI-powered features in je apps met de Vercel AI SDK. Leer hoe je chat interfaces, streaming responses en AI-gegenereerde content implementeert.
|
||||
|
||||
---
|
||||
|
||||
## Te Behandelen
|
||||
|
||||
### Eindopdracht Overview
|
||||
### Groepsdiscussie (15 min)
|
||||
Bespreek klassikaal de Cursor .cursorrules ervaringen uit Les 16 - welke regels zorgen voor betere AI output?
|
||||
|
||||
**Wat is de eindopdracht?**
|
||||
- Bouw een AI-powered web applicatie
|
||||
- Gebruik alle tools die je hebt geleerd
|
||||
- Vrije keuze in implementatie
|
||||
### Waarom Vercel AI SDK?
|
||||
|
||||
**Drie voorbeeldprojecten:**
|
||||
1. **AI Recipe Generator** - Recepten op basis van ingrediënten
|
||||
2. **Smart Budget Buddy** - Financieel overzicht met AI insights
|
||||
3. **Travel Planner AI** - Reisplanning met AI suggesties
|
||||
**Het probleem:** Direct API calls naar OpenAI/Anthropic zijn complex:
|
||||
- Streaming handmatig implementeren
|
||||
- Error handling
|
||||
- State management
|
||||
|
||||
**Of:** Eigen idee (met goedkeuring docent)
|
||||
**De oplossing:** Vercel AI SDK
|
||||
- Simpele React hooks
|
||||
- Built-in streaming
|
||||
- Provider-agnostic (OpenAI, Anthropic, etc.)
|
||||
- Edge-ready
|
||||
|
||||
---
|
||||
|
||||
### Requirements Doorlopen
|
||||
### Installatie & Setup
|
||||
|
||||
**Technische vereisten:**
|
||||
- Next.js 14 met App Router
|
||||
- TypeScript
|
||||
- Tailwind CSS
|
||||
- Supabase (database + auth)
|
||||
- Vercel AI SDK (chat of completion feature)
|
||||
- Deployed op Vercel
|
||||
```bash
|
||||
npm install ai @ai-sdk/openai
|
||||
# of voor Anthropic:
|
||||
npm install ai @ai-sdk/anthropic
|
||||
```
|
||||
|
||||
**Documentatie vereisten:**
|
||||
- `docs/PROJECT-BRIEF.md` - Project beschrijving
|
||||
- `docs/PROMPT-LOG.md` - Minimaal 10 prompts
|
||||
- `docs/AI-DECISIONS.md` - Minimaal 5 beslissingen
|
||||
- Complete README met setup instructies
|
||||
**Environment variable:**
|
||||
```bash
|
||||
# .env.local
|
||||
OPENAI_API_KEY=sk-xxxxx
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Beoordelingscriteria
|
||||
### Core Hooks
|
||||
|
||||
| Criterium | Weging |
|
||||
|-----------|--------|
|
||||
| Technische uitvoering | 40% |
|
||||
| AI integratie | 25% |
|
||||
| Documentatie (PROMPT-LOG, AI-DECISIONS) | 20% |
|
||||
| Code kwaliteit & organisatie | 15% |
|
||||
#### useChat - Voor Conversaties
|
||||
|
||||
**Minimale vereisten:**
|
||||
- App werkt in productie
|
||||
- Auth + CRUD werkt
|
||||
- AI feature werkt
|
||||
- Documentatie compleet
|
||||
```tsx
|
||||
'use client'
|
||||
import { useChat } from 'ai/react'
|
||||
|
||||
export function ChatComponent() {
|
||||
const { messages, input, handleInputChange, handleSubmit, isLoading } = useChat()
|
||||
|
||||
return (
|
||||
<div className="flex flex-col h-screen">
|
||||
<div className="flex-1 overflow-y-auto p-4">
|
||||
{messages.map(m => (
|
||||
<div key={m.id} className={m.role === 'user' ? 'text-right' : 'text-left'}>
|
||||
<span className="inline-block p-2 rounded-lg bg-gray-100">
|
||||
{m.content}
|
||||
</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<form onSubmit={handleSubmit} className="p-4 border-t">
|
||||
<input
|
||||
value={input}
|
||||
onChange={handleInputChange}
|
||||
placeholder="Type a message..."
|
||||
className="w-full p-2 border rounded"
|
||||
/>
|
||||
<button type="submit" disabled={isLoading}>
|
||||
{isLoading ? 'Sending...' : 'Send'}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
#### useCompletion - Voor Single Completions
|
||||
|
||||
```tsx
|
||||
import { useCompletion } from 'ai/react'
|
||||
|
||||
export function SummaryComponent() {
|
||||
const { completion, input, handleInputChange, handleSubmit, isLoading } = useCompletion()
|
||||
|
||||
return (
|
||||
<div>
|
||||
<form onSubmit={handleSubmit}>
|
||||
<textarea
|
||||
value={input}
|
||||
onChange={handleInputChange}
|
||||
placeholder="Paste text to summarize..."
|
||||
/>
|
||||
<button type="submit">Summarize</button>
|
||||
</form>
|
||||
{completion && <p>{completion}</p>}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Timeline
|
||||
### API Routes
|
||||
|
||||
**Nu tot deadline:**
|
||||
- Les 17: Kickoff, planning maken
|
||||
- Les 18: Werksessie met docent support
|
||||
- Daarna: Zelfstandig afronden
|
||||
**app/api/chat/route.ts:**
|
||||
```typescript
|
||||
import { openai } from '@ai-sdk/openai'
|
||||
import { streamText } from 'ai'
|
||||
|
||||
**Tips:**
|
||||
- Focus eerst op werkende MVP
|
||||
- Dan pas polish
|
||||
- Documenteer TIJDENS het bouwen
|
||||
export async function POST(req: Request) {
|
||||
const { messages } = await req.json()
|
||||
|
||||
const result = streamText({
|
||||
model: openai('gpt-4o-mini'),
|
||||
system: 'You are a helpful cooking assistant. Suggest recipes based on ingredients.',
|
||||
messages,
|
||||
})
|
||||
|
||||
return result.toDataStreamResponse()
|
||||
}
|
||||
```
|
||||
|
||||
**Met custom system prompt:**
|
||||
```typescript
|
||||
const result = streamText({
|
||||
model: openai('gpt-4o-mini'),
|
||||
system: `You are a recipe assistant for the AI Recipe Generator app.
|
||||
|
||||
When the user provides ingredients:
|
||||
1. Suggest 2-3 recipes they could make
|
||||
2. List required additional ingredients (if any)
|
||||
3. Provide brief cooking instructions
|
||||
|
||||
Be concise and practical.`,
|
||||
messages,
|
||||
})
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Veel Voorkomende Vragen
|
||||
### Streaming Responses
|
||||
|
||||
**Q: Mag ik een ander project doen dan de voorbeelden?**
|
||||
A: Ja, met goedkeuring. Bespreek je idee met de docent.
|
||||
**Waarom streaming?**
|
||||
- Betere UX (user ziet direct resultaat)
|
||||
- Snellere perceived performance
|
||||
- Geen wachten op complete response
|
||||
|
||||
**Q: Moet ik alle AI tools gebruiken?**
|
||||
A: Je moet minimaal Cursor en Vercel AI SDK gebruiken. De rest is optioneel.
|
||||
**Hoe het werkt:**
|
||||
1. Server stuurt tokens één voor één
|
||||
2. Client rendert elke token direct
|
||||
3. User ziet "typing" effect
|
||||
|
||||
**Q: Wat als ik vastloop?**
|
||||
A: Documenteer het probleem in PROMPT-LOG, vraag hulp in Les 18.
|
||||
|
||||
**Q: Hoeveel prompts moet ik loggen?**
|
||||
A: Minimaal 10, maar meer is beter. Focus op prompts waarvan je iets leerde.
|
||||
**Loading indicator:**
|
||||
```tsx
|
||||
{isLoading && (
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="animate-pulse">●</div>
|
||||
<span>AI is thinking...</span>
|
||||
</div>
|
||||
)}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Planning Maken
|
||||
### Integratie met Supabase
|
||||
|
||||
**Wat moet je nog doen?**
|
||||
**Conversations opslaan:**
|
||||
|
||||
Maak checklist:
|
||||
- [ ] Core features compleet
|
||||
- [ ] AI feature werkt
|
||||
- [ ] Auth werkt
|
||||
- [ ] Design afgewerkt
|
||||
- [ ] Edge cases gehandled
|
||||
- [ ] Documentatie compleet
|
||||
- [ ] Deployed en getest
|
||||
```typescript
|
||||
// Maak tabel in Supabase:
|
||||
// conversations: id, user_id, created_at
|
||||
// messages: id, conversation_id, role, content, created_at
|
||||
|
||||
**Prioriteer:**
|
||||
1. Wat werkt nog niet?
|
||||
2. Wat is kritiek vs nice-to-have?
|
||||
3. Hoeveel tijd heb je?
|
||||
// Na elke message:
|
||||
async function saveMessage(conversationId: string, role: string, content: string) {
|
||||
await supabase.from('messages').insert({
|
||||
conversation_id: conversationId,
|
||||
role,
|
||||
content
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
**In je component:**
|
||||
```tsx
|
||||
const { messages, input, handleSubmit } = useChat({
|
||||
onFinish: async (message) => {
|
||||
await saveMessage(conversationId, message.role, message.content)
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Error Handling
|
||||
|
||||
```tsx
|
||||
const { messages, error, reload } = useChat()
|
||||
|
||||
{error && (
|
||||
<div className="p-4 bg-red-100 text-red-700 rounded">
|
||||
<p>Something went wrong. Please try again.</p>
|
||||
<button onClick={reload}>Retry</button>
|
||||
</div>
|
||||
)}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Cost Management
|
||||
|
||||
**Model keuze:**
|
||||
| Model | Kosten | Gebruik voor |
|
||||
|-------|--------|--------------|
|
||||
| gpt-4o-mini | Goedkoop | Meeste taken |
|
||||
| gpt-4o | Duur | Complexe reasoning |
|
||||
| claude-3-haiku | Goedkoop | Simpele taken |
|
||||
| claude-3-sonnet | Medium | Balans |
|
||||
|
||||
**Bespaartips:**
|
||||
1. Gebruik gpt-4o-mini als default
|
||||
2. Korte system prompts
|
||||
3. Beperk conversation history
|
||||
4. Caching waar mogelijk
|
||||
|
||||
---
|
||||
|
||||
## Tools
|
||||
- Vercel AI SDK (`ai` package)
|
||||
- Next.js API Routes
|
||||
- OpenAI API / Anthropic API
|
||||
- Cursor
|
||||
- Alle geleerde tools
|
||||
- Supabase
|
||||
|
||||
---
|
||||
|
||||
## Lesopdracht (2 uur)
|
||||
|
||||
### Plan Je Afronding
|
||||
### Bouw een AI Chat Component
|
||||
|
||||
**Deel 1: Status Check (30 min)**
|
||||
**Deel 1: Setup (20 min)**
|
||||
1. `npm install ai @ai-sdk/openai`
|
||||
2. Voeg `OPENAI_API_KEY` toe aan `.env.local`
|
||||
3. Maak `app/api/chat/route.ts`
|
||||
|
||||
Beantwoord voor jezelf:
|
||||
1. Welke features werken al?
|
||||
2. Welke features missen nog?
|
||||
3. Wat is je grootste blocker?
|
||||
4. Hoe staat je documentatie ervoor?
|
||||
**Deel 2: Basic Chat (40 min)**
|
||||
1. Maak `components/Chat.tsx`
|
||||
2. Implementeer `useChat` hook
|
||||
3. Bouw chat UI met Tailwind
|
||||
4. Test streaming werkt
|
||||
|
||||
Maak een eerlijke inschatting.
|
||||
**Deel 3: System Prompt (30 min)**
|
||||
1. Schrijf system prompt voor je eindproject:
|
||||
- Recipe Generator: cooking assistant
|
||||
- Budget Buddy: financial advisor
|
||||
- Travel Planner: travel expert
|
||||
2. Test met relevante vragen
|
||||
|
||||
**Deel 2: Planning Maken (30 min)**
|
||||
|
||||
Maak gedetailleerde planning:
|
||||
- Wat doe je vandaag?
|
||||
- Wat doe je in Les 18?
|
||||
- Wat doe je thuis?
|
||||
- Wanneer ben je klaar?
|
||||
|
||||
**Deel 3: Begin Met Hoogste Prioriteit (1 uur)**
|
||||
|
||||
Start met de belangrijkste ontbrekende onderdelen:
|
||||
- Werkt je AI feature? → Prioriteit 1
|
||||
- Werkt auth? → Prioriteit 2
|
||||
- Is het deployed? → Prioriteit 3
|
||||
|
||||
Vraag hulp als je vastloopt!
|
||||
**Deel 4: Supabase Integratie (30 min)**
|
||||
1. Maak `messages` tabel
|
||||
2. Sla berichten op met `onFinish`
|
||||
3. Laad history bij page load
|
||||
|
||||
### Deliverable
|
||||
- Statusoverzicht: wat werkt, wat niet
|
||||
- Planning voor afronden
|
||||
- Voortgang op hoogste prioriteit
|
||||
- Werkende AI chat met streaming
|
||||
- Custom system prompt
|
||||
- Messages opgeslagen in Supabase
|
||||
|
||||
---
|
||||
|
||||
## Huiswerk
|
||||
## Huiswerk (2 uur)
|
||||
|
||||
### Werk aan je Eindopdracht
|
||||
### Bouw AI Feature voor Eindproject
|
||||
|
||||
**Dit is geen nieuw huiswerk - gebruik deze tijd om je eindopdracht af te ronden.**
|
||||
**Deel 1: Core AI Feature (1 uur)**
|
||||
|
||||
Focus op:
|
||||
1. Features compleet maken
|
||||
2. Bugs fixen
|
||||
3. Documentatie bijwerken
|
||||
4. Testen in productie
|
||||
Implementeer de AI chat die past bij je eindproject:
|
||||
|
||||
**Bereid vragen voor:**
|
||||
Schrijf op waar je hulp bij nodig hebt voor Les 18 (werksessie).
|
||||
| Project | AI Feature |
|
||||
|---------|-----------|
|
||||
| Recipe Generator | "Wat kan ik maken met kip en rijst?" |
|
||||
| Budget Buddy | "Analyseer mijn uitgaven deze maand" |
|
||||
| Travel Planner | "Plan een weekend Barcelona" |
|
||||
|
||||
- Custom system prompt
|
||||
- Context uit je database meegeven
|
||||
|
||||
**Deel 2: UX Polish (30 min)**
|
||||
|
||||
Voeg toe:
|
||||
- Streaming indicator
|
||||
- Suggested prompts / quick actions
|
||||
- Copy response button
|
||||
- Clear chat button
|
||||
- Error handling
|
||||
|
||||
**Deel 3: Documentatie (30 min)**
|
||||
|
||||
Maak `docs/AI-FEATURE.md`:
|
||||
- Welke AI feature heb je gebouwd?
|
||||
- Wat doet de system prompt?
|
||||
- Hoe integreert het met Supabase?
|
||||
- Welke model keuzes heb je gemaakt?
|
||||
|
||||
### Deliverable
|
||||
- Voortgang op eindopdracht
|
||||
- Lijst met vragen voor Les 18
|
||||
- AI feature in eindproject
|
||||
- Deployed preview
|
||||
- AI-FEATURE.md documentatie
|
||||
|
||||
---
|
||||
|
||||
## Leerdoelen
|
||||
Na deze les kan de student:
|
||||
- De eindopdracht requirements begrijpen
|
||||
- Een realistische planning maken
|
||||
- Prioriteiten stellen voor afronden
|
||||
- Eigen voortgang eerlijk inschatten
|
||||
- Hulp vragen waar nodig
|
||||
- Vercel AI SDK installeren en configureren
|
||||
- `useChat` en `useCompletion` hooks gebruiken
|
||||
- Streaming responses implementeren
|
||||
- API routes opzetten voor AI providers
|
||||
- Custom system prompts schrijven
|
||||
- Chat history opslaan in Supabase
|
||||
- Error handling en loading states implementeren
|
||||
- Kostenbewust omgaan met AI APIs
|
||||
|
||||
@@ -1,152 +1,276 @@
|
||||
# Les 18: Eindproject Werksessie
|
||||
# Les 18: Deployment & Production + Eindopdracht
|
||||
|
||||
---
|
||||
|
||||
## Hoofdstuk
|
||||
**Hoofdstuk 3: Advanced** (Les 10-18)
|
||||
**Deel 4: Advanced AI Features** (Les 13-18)
|
||||
|
||||
## Beschrijving
|
||||
Werksessie voor het afronden van je eindproject. Geen nieuwe theorie - focus op bouwen, vragen stellen, en hulp krijgen.
|
||||
Deploy je eindproject naar productie. Leer environment variables, Vercel deployment, en basis performance optimalisatie. Bespreking van de eindopdracht requirements en afrondende werksessie.
|
||||
|
||||
---
|
||||
|
||||
## Opzet van de Les
|
||||
## Te Behandelen
|
||||
|
||||
### Korte Standup (15 min)
|
||||
### Groepsdiscussie (15 min)
|
||||
Bespreek klassikaal de AI feature ervaringen uit Les 17 - welke system prompts werkten goed en welke challenges kwamen jullie tegen?
|
||||
|
||||
**Elke student deelt (max 1 minuut):**
|
||||
1. Waar sta ik?
|
||||
2. Wat is mijn grootste blocker?
|
||||
3. Wat wil ik vandaag afronden?
|
||||
### Vercel Deployment Flow
|
||||
|
||||
### Werktijd (1u 45min)
|
||||
**Hoe Vercel werkt:**
|
||||
1. Connect GitHub repository
|
||||
2. Push naar main → automatische deploy
|
||||
3. Push naar andere branch → preview URL
|
||||
4. Alles automatisch (build, SSL, CDN)
|
||||
|
||||
**Studenten werken zelfstandig:**
|
||||
- Docent loopt rond
|
||||
- Vraag hulp wanneer nodig
|
||||
- Peer support aangemoedigd
|
||||
|
||||
**Focus gebieden:**
|
||||
- Features afronden
|
||||
- Bugs fixen
|
||||
- Documentatie completeren
|
||||
- Deployment issues oplossen
|
||||
**Waarom Vercel voor Next.js:**
|
||||
- Gemaakt door dezelfde makers
|
||||
- Zero-config deployment
|
||||
- Gratis tier ruim voldoende
|
||||
- Automatische HTTPS
|
||||
- Global CDN
|
||||
|
||||
---
|
||||
|
||||
## Veelvoorkomende Problemen
|
||||
### Environment Variables in Vercel
|
||||
|
||||
### AI Chat Werkt Niet
|
||||
**Lokaal (.env.local) vs Productie (Vercel Dashboard):**
|
||||
|
||||
**Check:**
|
||||
| Waar | Bestand/Locatie | Voorbeeld |
|
||||
|------|-----------------|-----------|
|
||||
| Lokaal | `.env.local` | Development |
|
||||
| Vercel | Dashboard → Settings → Env Vars | Production |
|
||||
|
||||
**Stap voor stap:**
|
||||
1. Ga naar je Vercel project
|
||||
2. Settings → Environment Variables
|
||||
3. Voeg toe:
|
||||
- `NEXT_PUBLIC_SUPABASE_URL`
|
||||
- `NEXT_PUBLIC_SUPABASE_ANON_KEY`
|
||||
- `OPENAI_API_KEY`
|
||||
4. Selecteer environment (Production, Preview, Development)
|
||||
5. Save & Redeploy
|
||||
|
||||
**Let op:**
|
||||
- `NEXT_PUBLIC_` prefix = zichtbaar in browser
|
||||
- Zonder prefix = alleen server-side (API routes)
|
||||
|
||||
---
|
||||
|
||||
### Supabase Productie Setup
|
||||
|
||||
**Redirect URLs configureren:**
|
||||
1. Ga naar Supabase → Authentication → URL Configuration
|
||||
2. Voeg toe bij "Redirect URLs":
|
||||
- `https://jouw-app.vercel.app/**`
|
||||
- `https://jouw-app.vercel.app`
|
||||
|
||||
**Waarom:**
|
||||
- Auth redirects werken alleen naar toegestane URLs
|
||||
- Wildcards (`**`) voor sub-routes
|
||||
|
||||
---
|
||||
|
||||
### Deployment Checklist
|
||||
|
||||
**Voor deployment:**
|
||||
- [ ] `npm run build` werkt lokaal
|
||||
- [ ] Geen TypeScript errors
|
||||
- [ ] Environment variables gedocumenteerd in `.env.example`
|
||||
- [ ] `.gitignore` bevat `.env*.local`
|
||||
- [ ] README up-to-date
|
||||
|
||||
**Na deployment:**
|
||||
- [ ] App laadt correct
|
||||
- [ ] Auth werkt (login/logout)
|
||||
- [ ] Data wordt opgehaald uit Supabase
|
||||
- [ ] AI features werken (indien van toepassing)
|
||||
- [ ] Geen console errors
|
||||
|
||||
---
|
||||
|
||||
### Performance Basics
|
||||
|
||||
**Lighthouse Audit:**
|
||||
1. Open Chrome DevTools
|
||||
2. Tab "Lighthouse"
|
||||
3. Klik "Analyze page load"
|
||||
4. Aim for score >80 in elke categorie
|
||||
|
||||
**Quick wins:**
|
||||
- Gebruik Next.js `Image` component (niet `<img>`)
|
||||
- Lazy load components die niet direct nodig zijn
|
||||
- Verwijder ongebruikte dependencies
|
||||
|
||||
---
|
||||
|
||||
### Security Checklist
|
||||
|
||||
**Belangrijk voor productie:**
|
||||
- [ ] API keys nooit in client-side code
|
||||
- [ ] Supabase RLS enabled (Row Level Security)
|
||||
- [ ] Error messages geven geen gevoelige info
|
||||
- [ ] HTTPS (automatisch via Vercel)
|
||||
|
||||
---
|
||||
|
||||
## Eindopdracht Overview
|
||||
|
||||
### Wat is de eindopdracht?
|
||||
- Bouw een AI-powered web applicatie
|
||||
- Gebruik alle tools die je hebt geleerd
|
||||
- Vrije keuze in implementatie
|
||||
|
||||
**Drie voorbeeldprojecten:**
|
||||
1. **AI Recipe Generator** - Recepten op basis van ingrediënten
|
||||
2. **Smart Budget Buddy** - Financieel overzicht met AI insights
|
||||
3. **Travel Planner AI** - Reisplanning met AI suggesties
|
||||
|
||||
**Of:** Eigen idee (met goedkeuring docent)
|
||||
|
||||
---
|
||||
|
||||
### Technische Vereisten
|
||||
|
||||
**Stack:**
|
||||
- Next.js 14 met App Router
|
||||
- TypeScript
|
||||
- Tailwind CSS
|
||||
- Supabase (database + auth)
|
||||
- Vercel AI SDK (chat of completion feature)
|
||||
- Deployed op Vercel
|
||||
|
||||
**Documentatie vereisten:**
|
||||
- `docs/PROJECT-BRIEF.md` - Project beschrijving
|
||||
- `docs/PROMPT-LOG.md` - Minimaal 10 prompts
|
||||
- `docs/AI-DECISIONS.md` - Minimaal 5 beslissingen
|
||||
- Complete README met setup instructies
|
||||
|
||||
---
|
||||
|
||||
### Beoordelingscriteria
|
||||
|
||||
| Criterium | Weging |
|
||||
|-----------|--------|
|
||||
| Technische uitvoering | 40% |
|
||||
| AI integratie | 25% |
|
||||
| Documentatie (PROMPT-LOG, AI-DECISIONS) | 20% |
|
||||
| Code kwaliteit & organisatie | 15% |
|
||||
|
||||
**Minimale vereisten:**
|
||||
- App werkt in productie
|
||||
- Auth + CRUD werkt
|
||||
- AI feature werkt
|
||||
- Documentatie compleet
|
||||
|
||||
---
|
||||
|
||||
### Veelvoorkomende Problemen
|
||||
|
||||
**AI Chat Werkt Niet:**
|
||||
1. API key correct in `.env.local`?
|
||||
2. API key ook in Vercel env vars?
|
||||
3. Correct model gekozen?
|
||||
4. API route syntax correct?
|
||||
|
||||
### Auth Werkt Niet in Productie
|
||||
|
||||
**Check:**
|
||||
**Auth Werkt Niet in Productie:**
|
||||
1. Redirect URLs in Supabase toegevoegd?
|
||||
2. Beide URLs: met en zonder trailing slash?
|
||||
3. Wildcard (`**`) voor sub-routes?
|
||||
|
||||
### Deployment Faalt
|
||||
|
||||
**Check:**
|
||||
**Deployment Faalt:**
|
||||
1. `npm run build` lokaal succesvol?
|
||||
2. Alle TypeScript errors gefixed?
|
||||
3. Alle env vars in Vercel?
|
||||
|
||||
### Supabase Data Toont Niet
|
||||
|
||||
**Check:**
|
||||
1. RLS policies correct?
|
||||
2. Correct env vars?
|
||||
3. Supabase client correct geïnitialiseerd?
|
||||
|
||||
---
|
||||
|
||||
## Documentatie Checklist
|
||||
|
||||
**PROMPT-LOG.md (minimaal 10 entries):**
|
||||
- [ ] Prompts die goed werkten
|
||||
- [ ] Prompts die NIET werkten (en wat je leerde)
|
||||
- [ ] Verschillende tools gebruikt
|
||||
|
||||
**AI-DECISIONS.md (minimaal 5 entries):**
|
||||
- [ ] Database schema beslissing
|
||||
- [ ] UI/UX keuzes
|
||||
- [ ] Technische trade-offs
|
||||
- [ ] Problemen en oplossingen
|
||||
|
||||
**README.md:**
|
||||
- [ ] Project beschrijving
|
||||
- [ ] Features lijst
|
||||
- [ ] Tech stack
|
||||
- [ ] Setup instructies
|
||||
- [ ] Productie URL
|
||||
|
||||
---
|
||||
|
||||
## Peer Review (optioneel)
|
||||
|
||||
**Als je klaar bent, help een klasgenoot:**
|
||||
1. Test hun app
|
||||
2. Geef feedback
|
||||
3. Help met bugs
|
||||
|
||||
---
|
||||
|
||||
## Afsluiting (laatste 10 min)
|
||||
|
||||
**Check-out:**
|
||||
- Wie is klaar?
|
||||
- Wie heeft nog vragen?
|
||||
- Deadline reminder
|
||||
|
||||
---
|
||||
|
||||
## Tools
|
||||
- Vercel
|
||||
- GitHub
|
||||
- Supabase
|
||||
- Chrome DevTools (Lighthouse)
|
||||
- Cursor
|
||||
- Alle geleerde tools
|
||||
- Elkaar!
|
||||
|
||||
---
|
||||
|
||||
## Lesopdracht (2 uur)
|
||||
|
||||
### Werk aan je Eindproject
|
||||
### Deploy Je Eindproject
|
||||
|
||||
**Dit is WERKTIJD.**
|
||||
**Deel 1: Pre-Deployment Check (30 min)**
|
||||
|
||||
Er is geen specifieke opdracht behalve: werk aan je eindproject.
|
||||
Run door de checklist:
|
||||
1. `npm run build` - fix eventuele errors
|
||||
2. Check TypeScript errors
|
||||
3. Maak/update `.env.example`
|
||||
4. Update README met project info
|
||||
|
||||
**Prioriteiten:**
|
||||
1. ❌ Wat werkt nog niet? → Fix het
|
||||
2. ✅ Wat werkt al? → Maak het af
|
||||
3. 📝 Documentatie → Vul aan
|
||||
**Deel 2: Vercel Deployment (30 min)**
|
||||
|
||||
**Vraag hulp:**
|
||||
- Als je langer dan 15 minuten vastloopt
|
||||
- Als je niet weet waar te beginnen
|
||||
- Als je feedback wilt op je aanpak
|
||||
1. Ga naar [vercel.com](https://vercel.com)
|
||||
2. "Add New Project"
|
||||
3. Import je GitHub repository
|
||||
4. Voeg environment variables toe
|
||||
5. Deploy!
|
||||
|
||||
**Aan het eind van de les:**
|
||||
- App werkt in productie
|
||||
- Of: je weet precies wat nog moet gebeuren
|
||||
**Deel 3: Supabase Config (20 min)**
|
||||
|
||||
1. Voeg Vercel URL toe aan Supabase redirect URLs
|
||||
2. Test auth in productie
|
||||
3. Verifieer data access
|
||||
|
||||
**Deel 4: Testing & Lighthouse (40 min)**
|
||||
|
||||
1. Test alle features in productie:
|
||||
- Login/logout
|
||||
- CRUD operaties
|
||||
- AI chat (indien aanwezig)
|
||||
2. Run Lighthouse audit
|
||||
3. Fix issues tot score >80
|
||||
4. Screenshot resultaat
|
||||
|
||||
### Deliverable
|
||||
- Voortgang op eindproject
|
||||
- Duidelijk beeld van wat nog moet
|
||||
- Werkende productie URL
|
||||
- Lighthouse screenshot (score >80)
|
||||
- Test rapport: wat werkt, wat niet
|
||||
|
||||
---
|
||||
|
||||
## Huiswerk
|
||||
## Huiswerk (Eindopdracht Afronden)
|
||||
|
||||
### Rond Je Eindproject Af
|
||||
|
||||
**Dit is de laatste les. Alles wat nog moet, doe je zelfstandig.**
|
||||
**Dit is de laatste les. Gebruik deze tijd om je eindopdracht af te ronden.**
|
||||
|
||||
**Deel 1: Bug Fixes (1 uur)**
|
||||
|
||||
1. Test je app grondig in productie
|
||||
2. Fix gevonden bugs
|
||||
3. Test edge cases:
|
||||
- Lege states
|
||||
- Error states
|
||||
- Loading states
|
||||
4. Redeploy
|
||||
|
||||
**Deel 2: Performance Optimization (30 min)**
|
||||
|
||||
1. Run Lighthouse opnieuw
|
||||
2. Fix top 3 performance issues
|
||||
3. Document wat je hebt verbeterd
|
||||
|
||||
**Deel 3: Documentatie Afronden (30 min)**
|
||||
|
||||
Update je `README.md`:
|
||||
- Werkende productie URL
|
||||
- Features lijst
|
||||
- Tech stack
|
||||
- Setup instructies
|
||||
- Screenshots
|
||||
|
||||
Complete `docs/`:
|
||||
- PROMPT-LOG.md (minimaal 10 entries)
|
||||
- AI-DECISIONS.md (minimaal 5 entries)
|
||||
|
||||
**Checklist voor inleveren:**
|
||||
- [ ] App werkt op productie URL
|
||||
@@ -165,14 +289,20 @@ Er is geen specifieke opdracht behalve: werk aan je eindproject.
|
||||
|
||||
### Deliverable
|
||||
- Complete eindopdracht
|
||||
- Deployed en werkend
|
||||
- Alle documentatie compleet
|
||||
- Ingeleverd voor deadline
|
||||
|
||||
---
|
||||
|
||||
## Leerdoelen
|
||||
Na deze les kan de student:
|
||||
- Zelfstandig problemen oplossen
|
||||
- Hulp vragen wanneer nodig
|
||||
- Een Next.js app deployen naar Vercel
|
||||
- Environment variables configureren in Vercel
|
||||
- Supabase redirect URLs instellen voor productie
|
||||
- Een deployment checklist doorlopen
|
||||
- Lighthouse gebruiken voor performance audit
|
||||
- Basis security checks uitvoeren
|
||||
- De eindopdracht requirements begrijpen
|
||||
- Een project afronden en inleveren
|
||||
- Documentatie completeren
|
||||
- Peer feedback geven en ontvangen
|
||||
- Documentatie voltooien volgens de vereisten
|
||||
|
||||
Reference in New Issue
Block a user