180 lines
6.5 KiB
Markdown
180 lines
6.5 KiB
Markdown
# Les 7 — Docenttekst
|
||
## Van In-Memory naar Supabase
|
||
|
||
---
|
||
|
||
## Lesoverzicht
|
||
|
||
| Gegeven | Details |
|
||
|---------|---------|
|
||
| **Les** | 7 van 18 |
|
||
| **Onderwerp** | Supabase: database koppelen aan Next.js |
|
||
| **Duur** | 3 uur (09:00 – 12:00) |
|
||
| **Voorbereiding** | Werkend QuickPoll project uit Les 6, Supabase account |
|
||
| **Benodigdheden** | Laptop, Cursor/VS Code, browser, GitHub account |
|
||
|
||
---
|
||
|
||
## Leerdoelen
|
||
|
||
Na deze les kunnen studenten:
|
||
1. Uitleggen wat Supabase is en waarvoor je het gebruikt
|
||
2. Via de Supabase GUI tabellen aanmaken met relaties (foreign keys)
|
||
3. RLS policies instellen voor publieke toegang
|
||
4. De Supabase JavaScript client gebruiken in een Next.js project
|
||
5. Data ophalen en muteren via de Supabase client (select, update, insert)
|
||
6. Environment variables gebruiken voor API keys
|
||
|
||
---
|
||
|
||
## Tijdsplanning
|
||
|
||
### 09:00 – 09:10 | Welkom & Terugblik (10 min)
|
||
|
||
- Vraag: "Wie heeft het huiswerk gemaakt? Waar liep je tegenaan?"
|
||
- Kort terugblikken: wat hebben we gebouwd in Les 6?
|
||
- Aankondigen: "Vandaag maken we de app echt werkend én koppelen we een database"
|
||
|
||
### 09:10 – 09:30 | DEEL 1: Poll afmaken (20 min)
|
||
|
||
**Stap 1.1** — `votePoll()` in data.ts (5 min)
|
||
- Leg uit: we missen een functie om stemmen te verwerken
|
||
- Typ de functie, leg de logica uit
|
||
|
||
**Stap 1.2** — POST route fixen (5 min)
|
||
- Laat zien dat de huidige route alleen logt
|
||
- Vervang met werkende versie: body uitlezen, votePoll aanroepen, response sturen
|
||
|
||
**Stap 1.3** — Server Component + VoteForm split (10 min)
|
||
- DIT IS HET KERNMOMENT: leg het patroon uit
|
||
- Maak `components/VoteForm.tsx` — Client Component met useState + fetch
|
||
- Herschrijf `app/poll/[id]/page.tsx` als Server Component (geen 'use client'!)
|
||
- Server Component haalt data → geeft als prop door → Client Component doet interactie
|
||
- Dit patroon verandert NIET meer als we Supabase koppelen
|
||
|
||
**Stap 1.4** — GET route + visuele feedback (5 min)
|
||
- Voeg GET route toe (nodig voor VoteForm na het stemmen)
|
||
- Update PollItem met percentage bars
|
||
|
||
**✅ Check:** Demo op localhost — stem, zie de bar groeien
|
||
|
||
> **Tip:** Als studenten vastlopen, laat ze de browser console openen. Fouten in fetch calls verschijnen daar.
|
||
|
||
### 09:30 – 10:15 | DEEL 2: Supabase Introductie — No Code (45 min)
|
||
|
||
Dit is voor veel studenten hun EERSTE database-ervaring. Neem de tijd!
|
||
|
||
**Stap 2.1** — Wat is Supabase? (5 min)
|
||
- Open-source Firebase alternatief
|
||
- PostgreSQL = echte database, 30+ jaar oud
|
||
- Gratis tier voor leren
|
||
|
||
**Stap 2.2** — Project aanmaken (5 min)
|
||
- Iedereen logt in op supabase.com (GitHub)
|
||
- Maak samen een project aan
|
||
- Wacht tot het klaar is (~30 sec)
|
||
|
||
> **Tip:** Zorg dat iedereen een GitHub account heeft! Dit is een veelvoorkomend blokpunt.
|
||
|
||
**Stap 2.3** — polls tabel (10 min)
|
||
- Table Editor → New Table
|
||
- Leg uit: id (uuid), created_at (timestamp), question (text)
|
||
- Leg uit: NOT NULL — het veld mag niet leeg zijn
|
||
|
||
**Stap 2.4** — options tabel + foreign key (10 min)
|
||
- Vier kolommen: poll_id, text, votes
|
||
- Foreign key: leg uit wat dat is en waarom
|
||
- CASCADE: als poll weg is, opties ook
|
||
|
||
**Stap 2.5** — RLS policies (5 min)
|
||
- Leg uit: standaard mag niemand iets → we geven toestemming
|
||
- Maak SELECT policy op polls, SELECT + UPDATE op options
|
||
|
||
**Stap 2.6** — Testdata invoeren (5 min)
|
||
- Voeg 2 polls + 8 opties toe via de GUI
|
||
|
||
**Stap 2.7** — SQL Editor (5 min)
|
||
- Laat SELECT, WHERE en JOIN zien
|
||
- Dit is een mooi "aha-moment" — de data die ze net hebben ingevoerd komt terug
|
||
|
||
> **Tip:** Laat studenten ook zelf een query proberen. Bijv: "Hoeveel opties heeft poll X?"
|
||
|
||
### 10:15 – 10:30 | PAUZE (15 min)
|
||
|
||
### 10:30 – 11:30 | DEEL 3: Supabase koppelen aan Next.js (60 min)
|
||
|
||
**Stap 3.1** — npm install (2 min)
|
||
- `npm install @supabase/supabase-js`
|
||
|
||
**Stap 3.2** — .env.local (5 min)
|
||
- Kopieer URL + anon key uit Supabase dashboard
|
||
- Leg uit: NEXT_PUBLIC_ prefix, .gitignore
|
||
- ⚠️ Check: staat .env.local in .gitignore?
|
||
|
||
**Stap 3.3** — supabase.ts client (3 min)
|
||
- Drie regels code, simpel
|
||
|
||
**Stap 3.4** — Types updaten (5 min)
|
||
- Poll + Option interfaces
|
||
- Leg uit: waarom twee types? Matcht de twee tabellen
|
||
|
||
**Stap 3.5** — data.ts herschrijven (15 min)
|
||
- Dit is het kernstuk. Neem de tijd.
|
||
- `getPolls()`: select met options(*)
|
||
- `getPollById()`: select met eq + single
|
||
- `votePoll()`: twee stappen (fetch → update)
|
||
- Leg de Supabase syntax stap voor stap uit
|
||
|
||
> **Tip:** Als studenten TypeScript errors krijgen, check of ze de types correct hebben geüpdatet.
|
||
|
||
**Stap 3.6** — Homepage async maken (5 min)
|
||
- `async function Home()` + `await getPolls()`
|
||
- Leg uit: Server Component mag async zijn
|
||
|
||
**Stap 3.7** — PollItem aanpassen (5 min)
|
||
- option.text, option.votes, option.id
|
||
|
||
**Stap 3.8** — VoteForm + detail pagina + API routes (10 min)
|
||
- VoteForm: optionId (uuid) i.p.v. optionIndex (number)
|
||
- Page.tsx: alleen `await` toevoegen — structuur verandert niet!
|
||
- Benadruk: "Dát is de kracht van het Server Component + Client Component patroon"
|
||
|
||
**Stap 3.9** — Testen! (10 min)
|
||
- Samen testen op localhost
|
||
- Stem, refresh, check Supabase Table Editor
|
||
- Het "aha-moment": data overleeft een server restart!
|
||
|
||
> **Tip:** Open het Supabase dashboard naast de app. Stem in de app, refresh de Table Editor — studenten zien het live veranderen.
|
||
|
||
### 11:30 – 11:45 | Vragen & Reflectie (15 min)
|
||
|
||
Mogelijke vragen:
|
||
- "Kan iedereen nu stemmen?" → Ja, via de anon key + RLS policies
|
||
- "Is dit veilig?" → Voor een leerproject ja. In productie: auth + strakkere RLS
|
||
- "Hoe voorkom je dubbel stemmen?" → Met authenticatie (volgende les!)
|
||
- "Wat als de database offline is?" → Error handling in onze functies
|
||
|
||
### 11:45 – 12:00 | Huiswerk & Afsluiting (15 min)
|
||
|
||
**Opdracht:**
|
||
1. Maak een /create pagina (formulier → INSERT in Supabase)
|
||
2. Voeg navbar link toe
|
||
3. Extra: SQL queries schrijven
|
||
|
||
**Vooruitblik:** "Volgende les: Supabase Auth — inloggen, registreren, en bijhouden wie er stemt."
|
||
|
||
---
|
||
|
||
## Veelvoorkomende problemen
|
||
|
||
| Probleem | Oplossing |
|
||
|----------|-----------|
|
||
| "supabase.com laadt niet" | Probeer een andere browser of incognito |
|
||
| "Kan geen project aanmaken" | Check of ze een org hebben, anders aanmaken |
|
||
| Foreign key lukt niet | Check of de polls tabel al bestaat en data heeft |
|
||
| RLS blokkeert alles | Check of de policies correct zijn (anon, SELECT, true) |
|
||
| .env.local werkt niet | Server herstarten na aanmaken .env.local! |
|
||
| TypeScript errors na type change | Check imports, rebuild, herstart TS server |
|
||
| "Data verschijnt niet" | Check browser console voor Supabase errors |
|
||
| Votes updaten niet | Check of UPDATE RLS policy op options staat |
|