# 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-app` commando klaar hebben - [ ] Terminal groot genoeg zodat klas kan zien (terminal font minimaal 16pt) - [ ] Browser met localhost:3000 open - [ ] Vercel account ingelogd (voorbeeldproject gereed) - [ ] `.cursorrules` bestand 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.ts` bestand. 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 `/about` pagina? Maak een `about` folder met een `page.tsx` erin." *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 `children` wisselt." *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 is `mijn-eerste-post`." *Tim loopt de TypeScript typing uit* > "En weer TypeScript. `params` is een Promise. Dat is Next.js 15. Je await't params en dan heb je `slug`." --- ### 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.tsx` wordt 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 in `components/`. Types in `types/`. Business logic in `lib/`." *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 `PageProps` interface met `params` en `searchParams`. Beiden zijn Promises. SearchParams kan optioneel `query` en `page` bevatten — die vraagtekens zijn optional syntax." *Tim tipt op het scherm* > "Nu weet TypeScript precies wat er binnenkomt. Typ je `body.titel` in plaats van `body.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 je `loading.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 `onSubmit` met fetch naar een API, gebruik je een `action` die 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)`, dan `if (loading) return `. In Next.js? Maak een `loading.tsx` en klaar." *Tim wijst naar error.tsx* > "Hetzelfde met errors. `error.tsx` vangt fouten op. Gebruiker ziet nette foutmelding in plaats van crash." *Tim slaat handen in elkaar* > "En TypeScript typing overal. `error: Error` en `reset: () => 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 ``. Next.js optimaliseert automatisch — lazy loading, juiste formaat." > "Twee: `next/link`. Gebruik dit in plaats van `` tags. Client-side navigatie — pagina herlaadt niet, veel sneller." > "Drie: metadata. Exporteer een `metadata` object. 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` — niet `page.tsx`!" *Tim toont de GET handler* > "Je exporteert functies die GET, POST, PUT, DELETE heten. Dit bestand op `/api/polls/route.ts` betekent: 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. `Poll` interface, 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/1` geeft poll 1 terug, `/api/polls/2` geeft 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.local` staat 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.ts` in je `src` root. NIET in `app/`!" *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 `matcher` bepaal 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* ```typescript 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.ts` geeft `/api/polls`." - "TypeScript error bij `fetch`? Zet het in een `try/catch` en 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.tsx` met skeleton. Tailwind `animate-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 dev` werkt." --- ### 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