fix: implement lessons feedback
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user