21 KiB
Les 05: Next.js — Het React Framework - Docenttekst
NOVI Hogeschool | Instructeur: Tim | Duur: 180 minuten
VOORBEREIDING
Checklist voor Tim (30 minuten voor les):
- Cursor openen en
create-next-appcommando klaar hebben - Terminal groot genoeg zodat klas kan zien (terminal font minimaal 16pt)
- Browser met localhost:3000 open
- Vercel account ingelogd (voorbeeldproject gereed)
.cursorrulesbestand voorbereid- Slides open in presentatiemodus
- WiFi stabiel en npm packages cached
- Backup laptop met dezelfde setup klaar (plan B)
Hardware check:
- HDMI/USB-C verbinding stabiel
- Scherm groot genoeg voor klas (10+ personen)
- Audio werkt (voor eventuele demo video's)
BLOK 1: HET PROBLEEM & DE OPLOSSING (0:00-0:20)
Slide 1: Titel
Tijd: 0:00-0:02
Tim staat op, enthousiastisch, maakt oogcontact met de klas
"Welkom bij Les 5! De afgelopen weken hebben jullie HTML, CSS, JavaScript, en TypeScript geleerd. Vandaag maken we een grote stap: we gaan van losse technologieën naar een echt framework. Next.js."
Tim loopt even heen en weer
"Na vandaag kun je een complete webapplicatie bouwen. Met routing, API's, middleware — alles. En het mooiste? Het is gebouwd op React, dus alles wat je al kent werkt gewoon."
Tim duim enthousiast met twee duimen omhoog
Slide 2: Planning Vandaag
Tijd: 0:02-0:05
Tim wijst naar het scherm met een pointer
"Dit is het plan. Eerst: waarom zou je Next.js gebruiken? Wat mist er in gewoon React? Dan duiken we in routing en project structuur — hoe organiseer je een Next.js app. Daarna TypeScript in Next.js, server en client components, en hoe je data ophaalt."
Tim loopt langs de slide
"In het laatste blok: API routes, middleware, environment variables, hoe je deployed op Vercel, en Cursor workflow. Flink programma, maar het is allemaal praktisch."
Tim klapt in handen
"Na de pauze gaan we SAMEN de setup doen. Ik loop het voor, jullie volgen mee. Zo heeft iedereen een werkend project staan. Daarna gaan jullie zelfstandig verder bouwen."
Tim knikt stellig
Slide 3: Terugblik Les 4 — TypeScript
Tijd: 0:05-0:08
Tim leunt tegen het bureau
"Vorige week hebben jullie TypeScript geleerd. Types, interfaces, unions, narrowing — en natuurlijk die escaperoom. Wie heeft alle 10 kamers gehaald?"
Tim steekt hand op, kijkt rond
"Nice. Die TypeScript kennis gaan we vandaag direct gebruiken. Next.js is volledig TypeScript-first. Alles wat je schrijft in Next.js is getypt. Dus jullie zijn al voorbereid."
Tim wijst naar zijn hoofd
"Je hebt het juiste mental model al."
Slide 4: Het Probleem met Pure React
Tijd: 0:08-0:14
Tim opent Cursor, navigeert naar een browser
"Oké, stel je voor: je bouwt een webshop met React. Klanten moeten producten kunnen vinden via URL —
/products/laptop. Je wilt dat Google de shop indexeert. Je wilt snelle laadtijden. Je wilt een API backend."
Tim telt op zijn vingers
"React kan pagina's renderen. Maar routing? React-router nodig. Server-side rendering? Niet standaard. API? Aparte Express server. Images optimaliseren? Extra library. En alles moet je zelf configureren."
Tim doet alsof hij achter een puinhoop zit
"Je bent meer bezig met setup dan met je app bouwen. Dat is het probleem."
Slide 5: Next.js = Het React Framework
Tijd: 0:14-0:18
Tim opent de slide met Next.js logo's
"Next.js pakt al die problemen en lost ze op in één framework. Routing? Maak een folder. API? Maak een
route.tsbestand. Server-side rendering? Standaard aan. TypeScript? Zero configuratie."
Tim slaat op het bureau voor nadruk
"Het is gemaakt door Vercel — dat is ook een hosting platform. Dus van development tot deployment zit het allemaal erin."
Tim kijkt direct naar de klas
"En het belangrijkste: Next.js is gebouwd OP React. Je schrijft gewoon React components. useState, useEffect, JSX — alles wat je kent werkt gewoon. Next.js voegt er alleen superkrachten aan toe."
Slide 6: Wie Gebruikt Next.js?
Tijd: 0:18-0:20
Tim toont een logo wall op het scherm
"Netflix, TikTok, Nike, Notion — ze vertrouwen op Next.js. Waarom? Performance, SEO, developer experience. Snel itereren, snel deployen."
Tim wijst naar de logos
"Als jullie straks solliciteren en Next.js op je CV staat, dan weten bedrijven: die kan een complete webapplicatie bouwen."
BLOK 2: APP ROUTER & PROJECT STRUCTUUR (0:20-0:40)
Slide 7: create-next-app (Live Demo)
Tijd: 0:20-0:28
Tim opent Terminal in Cursor, groot zichtbaar voor de klas
"Laten we het meteen proberen. Ik typ dit commando."
Tim typt langzaam: npx create-next-app@latest demo-app
Wacht tot het begint en loopt door opties
"TypeScript? Ja, Les 4 was niet voor niks. Tailwind? Ja, maakt styling makkelijker. App Router? Ja — dat is modern. Src directory? Ja, houdt je code netjes."
Tim wacht totdat het installeert, ongeveer 30 seconden
"Nu:
cd demo-app && npm run dev. Boem. Werkende app."
Tim opent browser op localhost:3000
"Dat is alles. Geen webpack config, geen babel setup. Het werkt gewoon. Dit is Next.js."
Tim toont de default welcome page
Slide 8: App Router — Folder = Route
Tijd: 0:28-0:32
Tim toont de slide met de gouden regel
"Dit is het meest elegante aan Next.js. De gouden regel: elke folder in
app/is een route. Wil je een/aboutpagina? Maak eenaboutfolder met eenpage.tsxerin."
Tim maakt live in zijn project een nieuwe folder about/page.tsx aan
"En klaar. Geen router config, geen complexe imports. Folder = route."
Tim navigeert in browser naar /about en toont dat het werkt
"En nesting werkt hetzelfde. Dashboard met settings subpagina?
dashboard/settings/page.tsx. Next.js snapt automatisch de structuur."
Slide 9: Speciale Bestanden
Tijd: 0:32-0:35
Tim wijst naar de slide
"Next.js heeft speciale bestanden.
page.tsx— dat is je pagina.layout.tsx— dat is je wrapper.loading.tsx— loading spinner.error.tsx— error handler.route.ts— API endpoint."
Tim opent de file explorer en wijst files aan
"Wat heel krachtig is: layouts nesten. Je root layout heeft een navbar. Je blog layout voegt een sidebar toe. Alles composeert vanzelf."
Slide 10: Layouts in Actie
Tijd: 0:35-0:38
Tim toont de code slide met RootLayout
"Kijk. De root layout wraps alles. Elke pagina krijgt deze nav en footer. En het mooie: als je navigeert, wordt de layout NIET opnieuw gerenderd. Alleen de
childrenwisselt."
Tim highlight de children prop
"En
Metadata? Dat is type-safe SEO. Title, description, Open Graph — alles is getypt."
Slide 11: Dynamic Routes
Tijd: 0:38-0:41
Tim wijst naar vierkante haken op de slide
"Stel je hebt een blog met 100 posts. Je gaat geen 100 folders aanmaken. Je maakt één folder met vierkante haken:
[slug]. Dat is een variabele."
Tim maakt een blog/[slug]/page.tsx folder aan
"Alles wat je in de URL typt wordt beschikbaar als parameter.
/blog/mijn-eerste-post— slug ismijn-eerste-post."
Tim loopt de TypeScript typing uit
"En weer TypeScript.
paramsis een Promise. Dat is Next.js 15. Je await't params en dan heb jeslug."
Slide 12: Route Groups
Tijd: 0:41-0:44
Tim toont de slide met ronde haken
"Route Groups met ronde haken.
(marketing)en(dashboard). Ze verschijnen NIET in de URL — het is puur organisatie."
Tim maakt folders aan met ronde haken
"Dus
(marketing)/about/page.tsxwordt gewoon/about. En elk group kan zijn eigen layout hebben. Marketing met hero en footer, dashboard met sidebar."
Tim knikt
"Hoe grote Next.js apps georganiseerd zijn."
Slide 13: Project Structuur Best Practices
Tijd: 0:44-0:47
Tim toont de folder tree
"Hier is hoe je een project organiseert.
app/is ALLEEN voor routing — geen componenten. Componenten gaan incomponents/. Types intypes/. Business logic inlib/."
Tim wijst naar elk onderdeel
"Dit is geen harde regel van Next.js. Maar het is wel de conventie. Als je in een team werkt, weet iedereen meteen waar dingen staan."
BLOK 3: TYPESCRIPT, COMPONENTS & DATA (0:47-1:07)
Slide 14: TypeScript in Next.js
Tijd: 0:47-0:52
Tim toont de code met PageProps
"Hier komt Les 4 echt samen. Alles in Next.js is getypt. Page props? Getypt. API request bodies? Getypt."
Tim highlight de interface
"We definiëren een
PagePropsinterface metparamsensearchParams. Beiden zijn Promises. SearchParams kan optioneelqueryenpagebevatten — die vraagtekens zijn optional syntax."
Tim tipt op het scherm
"Nu weet TypeScript precies wat er binnenkomt. Typ je
body.titelin plaats vanbody.question, krijg je direct rood."
Slide 15: Server Components vs Client Components
Tijd: 0:52-0:58
Tim toont twee code blokken
"Dit is misschien het belangrijkste concept in Next.js. Standaard is elk component een Server Component. Het draait op de server, niet in de browser. De browser krijgt alleen HTML — geen JavaScript."
Tim maakt een gebaar van versturen
"Waarom is dat goed? Performance. Je stuurt minder code naar de browser. En je kunt direct data fetchen —
await fetch()in je component."
Tim wijst naar het tweede blokje
"Maar: server components kunnen geen interactiviteit hebben. Geen useState, geen onClick. Daarvoor heb je Client Components nodig. Je zet
'use client'bovenaan en dan werkt het zoals je gewend bent."
Tim benadrukt
"De truc is: server components voor alles wat kan, en client components alleen voor interactiviteit. Meeste code is server."
Slide 16: Data Fetching in Server Components
Tijd: 0:58-1:02
Tim toont de server component met async function
"In gewoon React fetch je data met useEffect. useState voor loading, useState voor error, useState voor data. Drie states voor één ding. In Next.js? Niet nodig."
Tim wijst naar await fetch()
"Een server component kan async zijn. Je schrijft gewoon
await fetch(). Component wacht op data en rendert het. Terwijl het wacht, toont Next.js automatisch jeloading.tsx."
Tim highlight het revalidate object
"En dat
revalidate: 60? Dat is caching. Eerste keer fetcht Next.js. Volgende 60 seconden serveert het cache. Dan opnieuw. Nul configuratie."
Slide 17: Server Actions
Tijd: 1:02-1:05
Tim toont de form met action={createPoll}
"Server Actions zijn relatief nieuw en ze veranderen hoe je met formulieren werkt. In plaats van
onSubmitmet fetch naar een API, gebruik je eenactiondie direct een server functie aanroept."
Tim wijst naar 'use server'
"
'use server'in de functie body. Dat draait op de server. Browser stuurt form, server verwerkt het. Geen API route nodig."
"Waarom? Minder code. Geen API route bestand, geen fetch, geen response handling. En het werkt zonder JavaScript in de browser."
Slide 18: Loading & Error States
Tijd: 1:05-1:07
Tim toont loading.tsx en error.tsx
"In gewoon React: eigen loading states beheren.
useState(true), danif (loading) return <Spinner />. In Next.js? Maak eenloading.tsxen klaar."
Tim wijst naar error.tsx
"Hetzelfde met errors.
error.tsxvangt fouten op. Gebruiker ziet nette foutmelding in plaats van crash."
Tim slaat handen in elkaar
"En TypeScript typing overal.
error: Errorenreset: () => void. Les 4 comes back!"
BLOK 4: API, MIDDLEWARE, DEPLOY & CURSOR (1:07-1:27)
Slide 19: next/image, next/link & Metadata
Tijd: 1:07-1:11
Tim toont drie imports
"Drie ding die je altijd gebruikt. Een:
next/image. Gebruik dit in plaats van<img>. Next.js optimaliseert automatisch — lazy loading, juiste formaat."
"Twee:
next/link. Gebruik dit in plaats van<a>tags. Client-side navigatie — pagina herlaadt niet, veel sneller."
"Drie: metadata. Exporteer een
metadataobject. TypeScript helpt met autocomplete — title, description, Open Graph. Alles voor SEO."
Slide 20: Route Handlers — Je Eigen API
Tijd: 1:11-1:16
Tim opent een route.ts bestand
"Route Handlers zijn API endpoints in je Next.js app. Bestand:
route.ts— nietpage.tsx!"
Tim toont de GET handler
"Je exporteert functies die GET, POST, PUT, DELETE heten. Dit bestand op
/api/polls/route.tsbetekent: GET /api/polls."
Tim navigeert in browser naar /api/polls
"En ik krijg JSON terug. Dat is mijn API. In hetzelfde project. Geen CORS issues, geen aparte server."
Tim highlight de TypeScript
"En alles is getypt.
Pollinterface, request body getypt, return type getypt."
Slide 21: Dynamic API Routes
Tijd: 1:16-1:19
Tim toont /api/polls/[id]/route.ts
"Net zoals pagina's kunnen API routes ook dynamisch zijn.
/api/polls/1geeft poll 1 terug,/api/polls/2geeft poll 2."
Tim highlight de error handling
"En error handling is essentieel. Poll niet gevonden? 404 status. Alles getypt."
Slide 22: Environment Variables
Tijd: 1:19-1:22
Tim toont .env.local
"Environment variables zijn hoe je secrets beheert. Database URLs, API keys — niet hardcoden. In
.env.local."
Tim benadrukt
"Twee regels. Een:
NEXT_PUBLIC_prefix? Beschikbaar in browser. Dus NOOIT secrets daarmee. Twee: zonder prefix? Alleen op server. Perfect voor secrets."
Tim wijst
"
.env.localstaat automatisch in.gitignore. Komt nooit in Git."
Slide 23: Middleware
Tijd: 1:22-1:25
Tim opent het middleware bestand
"Middleware draait VÓÓR elke request. Eén bestand:
middleware.tsin jesrcroot. NIET inapp/!"
Tim loopt door het voorbeeld
"Usecase: logging, auth check, redirects, rate limiting. Elke request gaat langs de beveiliger bij de deur."
Tim wijst naar matcher
"Met
matcherbepaal je op welke routes het actief is. Wil je het alleen op API routes?/api/:path*."
Slide 24: Deployment op Vercel
Tijd: 1:25-1:27
Tim toont Vercel dashboard
"Vercel = makers van Next.js = beste hosting. Push naar GitHub, import project, KLAAR. Automatische deployments bij elke push."
Tim toont wat je gratis krijgt
"HTTPS, global CDN, preview deployments per branch. Environment variables in dashboard. Serverless functions voor API routes."
Tim knikt
"Voor het huiswerk: deploy op Vercel. Dan heb je een echte URL."
Slide 25: Next.js + Cursor — AI Development
Tijd: 1:27-1:30
Tim opent Cursor
"Cursor kent alle Next.js patterns. Zit je in
route.ts, suggereert Tab-completie GET en POST handlers automatisch."
Tim waarschuwt
"Maar: AI is tool, geen vervanger. BEGRIJP wat Next.js doet. Cursor genereert Server Component met useState? JIJ ziet dat is fout."
Tim toont .cursorrules bestand
"Pro tip: maak
.cursorrules. Vertel Cursor hoe je wilt coderen. Next.js 15, TypeScript, server components standaard. Veel betere suggesties."
Slide 26: Samenvatting — Next.js in Één Overzicht
Tijd: 1:30-1:33
Tim toont de tabel
"Dit is je cheat sheet. Bewaar deze slide. Alles wat je straks nodig hebt: pagina, layout, API route, middleware, loading, error."
Tim loopt de tabel door
"Print dit in je hoofd. Server Component standaard. Client met
'use client'voor interactiviteit. Server Action voor forms. Route Handler voor API."
Tim klapt
"Alles getypt met TypeScript. Alles op Vercel. Dit is je complete toolkit."
PAUZE (1:33-1:45)
Tim geeft pauzeaankondiging
"15 minuten pauze! Naar het toilet, koffie, stretch. Over 15 minuten gaan we SAMEN de setup doen. Iedereen een werkend project."
Tim loopt rond, praat informeel met studenten
BLOK 5: SAMEN OPZETTEN & BOUWEN (1:45-2:45)
Slide 27: Opdracht — QuickPoll App
Tijd: 1:45-1:48
Tim herstart na pauze, energiek
"Oké! We gaan QuickPoll bouwen — een poll/stemming app. Alles wat we net geleerd hebben: routing, API's, TypeScript, components."
Tim wijst naar de slide
"Aanpak: eerst SAMEN de setup. Ik loop het voor, jullie volgen mee. Daarna gaan jullie zelfstandig verder."
Slide 28: Samen Opzetten (Tim + Klas)
Tijd: 1:48-2:03
Tim opent Terminal, grote font, klas kan alles zien
"Open je terminal. We gaan dit samen doen. Typ mee. Stap 1: create-next-app."
Tim typt langzaam: npx create-next-app@latest quickpoll --typescript --tailwind --app --src-dir
Pauzeert bij elke vlag om uit te leggen
"TypeScript: yes. Tailwind: yes. App Router: yes. Src-dir: yes. Klaar?"
Wacht tot iedereen dezelfde output ziet
"Nu:
cd quickpoll && npm run dev. Check of localhost:3000 werkt op je laptop."
Tim wacht 30 seconden
"Iedereen groen licht? Top!"
Tim opent zijn VS Code
"Stap 2: types. Dit is de TypeScript mindset. We beginnen ALTIJD met types. Maak
src/types/index.ts."
Tim typt langzaam en klas volgt
export interface Poll {
id: string;
question: string;
options: string[];
votes: number[];
}
export interface CreatePollBody {
question: string;
options: string[];
}
Pauzeert na elke interface
"Dit zijn je core types. Alles in je app bouwt hierop. TypeScript helpt nu met autocomplete."
"Stap 3: folder structuur. Nog geen code — alleen bestanden aanmaken. Zo weet je wat je gaat bouwen."
Tim maakt folders aan op scherm, klas volgt in hun eigen IDE
src/app/
├── page.tsx (al aanwezig)
├── poll/
│ └── [id]/
│ └── page.tsx
└── api/
└── polls/
├── route.ts
└── [id]/
├── route.ts
└── vote/
└── route.ts
src/components/
└── (leeg voor nu)
src/lib/
└── data.ts
src/types/
└── index.ts (net gemaakt)
Tim loopt langs elke folder
"Oké, iedereen klaar met setup? Mooi. Nu gaan jullie ZELF verder. Cursor Tab UIT. Zelf typen. Ik loop rond en help waar nodig. Begrenzing: 60 minuten."
Tim geeft de opdracht sheet
Slide 29: Individueel Bouwen (~60 min)
Tijd: 2:03-2:43
Tim loopt rond, klas werkt zelfstandig
Tim helpt bij veel voorkomende problemen:
- "Vergeten
'use client'in component? Dat is een Server Component — je kan useState niet gebruiken." - "API route geeft 404? Check de folder path —
/api/polls/route.tsgeeft/api/polls." - "TypeScript error bij
fetch? Zet het in eentry/catchen type de response."
Tim monitort voortgang:
- Na 10 min: "Iedereen verder dan stap 4? In-memory data? Top."
- Na 25 min: "Wie zit al aan stap 6? API routes? Nice!"
- Na 45 min: "Stap 7 is poll detail pagina. Daar is de meeste complexiteit. Zit je vast? Vraag hier."
Tim helpt met rondlopen:
Tips voor Rondlopen (Tim geeft deze hints als nodig):
- Stap 4 (data): Array met 3-4 polls in
lib/data.ts. IDs als strings. - Stap 5 (homepage): Import data,
map()over polls, toon vraag + aantal opties. - Stap 6 (API routes): GET terug alle polls. POST voegt nieuwe toe. GET met
[id]terug single poll. - Stap 7 (detail): Fetch poll data. Map options. VoteForm client component met onClick handler.
- Stap 8 (middleware): Log alle requests.
matcher: ["/api/*"]. - Stap 9 (loading):
loading.tsxmet skeleton. Tailwindanimate-pulse.
"Cursor Tab mag nu AAN als je echt vastloopt. Maar geef het eerst 5 minuten zelf."
"Vragen? Ik ben hier. Vraag buurman/buurvrouw ook — samen is sterker."
Tim circuliert, geeft high-fives aan wie stap 7 afmaken
BLOK 6: AFSLUITING (2:43-3:00)
Slide 30: Huiswerk — Next.js Mini Blog
Tijd: 2:43-2:50
Tim verzamelt klas
"Oké, huiswerk! Jullie bouwen een Mini Blog. Waarom een ander thema? Omdat ik wil dat je het ZELF kunt, niet dat je QuickPoll kopieert."
Tim loopt langs de eisen
"Homepage met blog posts. Dynamic route
/post/[slug]voor elke post. API routes: GET alle posts, POST nieuwe. Middleware voor logging. Loading en error states. Minimaal 3 pagina's."
Tim benadrukt
"EN: deploy op Vercel. Ik wil werkende URL zien. Push naar GitHub, koppel Vercel, stuur link."
"Inleveren: GitHub repo + Vercel URL. Deadline: volgende les. Zorg dat
npm run devwerkt."
Slide 31: Preview Les 6
Tijd: 2:50-2:55
Tim geeft sneak peek
"Volgende les: verdieping. Database — Prisma of Drizzle. Authentication — NextAuth. Caching en revalidation. Forms met Server Actions verdieping."
Tim wijst
"Zorg dat huiswerk af en deployed is. Les 6 bouwt hierop voort."
Slide 32: Afsluiting
Tijd: 2:55-3:00
Tim staat vooraan, serieus maar met lach
"Vandaag hebben jullie een COMPLETE Next.js app gebouwd. From scratch. Routing, API's, middleware, TypeScript — het hele pakket. Dat is impressive voor één les."
Tim loopt
"Onthoud: Next.js is React met extra's. Alles wat je al kende werkt. Nu heb je een framework dat je leven makkelijker maakt. En Vercel zet het online in twee minuten."
Tim maakt oogcontact
"Vragen? Nee? Mooi. Dan zie ik jullie volgende week. Vergeet huiswerk niet — ik wil URL zien!"
Tim geeft enthousiaste groet
POST-SESSIE CHECKLIST
Tim controleert (30 minuten na les):
- Alle aanwezigen hebben werkend
npm run dev - Typefiles sync'd met GitHub (voor huiswerk)
- Vercel accounts actief (student weet hoe te deployen)
- Huiswerkopdracht duidelijk — geen vragen open
- Slides online gedeeld met klas
- Feedback verzameld van moeilijke momenten
Voorbereiding Les 6:
- Prisma setup docs klaar
- NextAuth.js voorbeeld project
- Database schema voorbeeld
- Caching strategieën voorbereiding