fix: better order
This commit is contained in:
@@ -14,100 +14,255 @@
|
||||
**Hoofdstuk 2: Intermediate** (Les 4-9)
|
||||
|
||||
## Beschrijving
|
||||
Leer de basics van Supabase: een database opzetten, data opslaan/ophalen, en simpele authenticatie. AI helpt je met de complexiteit.
|
||||
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.
|
||||
|
||||
---
|
||||
|
||||
## Te Behandelen
|
||||
|
||||
### Wat is Supabase?
|
||||
- Open-source Firebase alternative
|
||||
- Hosted Postgres database
|
||||
- Gratis tier voor development
|
||||
- Mooie UI om tabellen te beheren
|
||||
### Stap 1: Next.js Project Aanmaken
|
||||
|
||||
### Supabase UI Tour
|
||||
- Dashboard overview
|
||||
- Table Editor: tabellen maken zonder SQL
|
||||
- Kolommen toevoegen (text, number, boolean, timestamp)
|
||||
- Data handmatig invoeren en bekijken
|
||||
Dit is de eerste keer dat je een volledig Next.js project opzet.
|
||||
|
||||
### Database Basics (zonder SQL kennis)
|
||||
- Tabellen = spreadsheets met regels
|
||||
- Kolommen = velden (naam, email, etc.)
|
||||
- Rijen = individuele records
|
||||
- Primary key: unieke identifier per rij
|
||||
```bash
|
||||
# Maak nieuw project
|
||||
npx create-next-app@latest todo-app
|
||||
|
||||
### Supabase Client in Next.js
|
||||
# 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
|
||||
|
||||
```
|
||||
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
|
||||
```
|
||||
|
||||
### 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
|
||||
|
||||
**Installatie:**
|
||||
```bash
|
||||
npm install @supabase/supabase-js
|
||||
```
|
||||
|
||||
**Setup:**
|
||||
```ts
|
||||
### Stap 7: Supabase Client Maken
|
||||
|
||||
Maak `src/lib/supabase.ts`:
|
||||
|
||||
```typescript
|
||||
import { createClient } from '@supabase/supabase-js'
|
||||
|
||||
const supabase = createClient(
|
||||
process.env.NEXT_PUBLIC_SUPABASE_URL!,
|
||||
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
|
||||
)
|
||||
const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL!
|
||||
const supabaseAnonKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
|
||||
|
||||
export const supabase = createClient(supabaseUrl, supabaseAnonKey)
|
||||
```
|
||||
|
||||
### CRUD Operaties (met AI hulp)
|
||||
### Stap 8: Database Tabel Maken (via UI)
|
||||
|
||||
**Create:**
|
||||
```ts
|
||||
**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', completed: false })
|
||||
```
|
||||
.insert({ title: 'Nieuwe taak' })
|
||||
|
||||
**Read:**
|
||||
```ts
|
||||
// READ - todos ophalen
|
||||
const { data, error } = await supabase
|
||||
.from('todos')
|
||||
.select('*')
|
||||
```
|
||||
.order('created_at', { ascending: false })
|
||||
|
||||
**Update:**
|
||||
```ts
|
||||
// UPDATE - todo afvinken
|
||||
const { data, error } = await supabase
|
||||
.from('todos')
|
||||
.update({ completed: true })
|
||||
.eq('id', 1)
|
||||
```
|
||||
.eq('id', todoId)
|
||||
|
||||
**Delete:**
|
||||
```ts
|
||||
// DELETE - todo verwijderen
|
||||
const { error } = await supabase
|
||||
.from('todos')
|
||||
.delete()
|
||||
.eq('id', 1)
|
||||
.eq('id', todoId)
|
||||
```
|
||||
|
||||
### Simpele Authentication
|
||||
- Supabase Auth UI component (plug & play)
|
||||
- Magic Link login (geen wachtwoord nodig)
|
||||
- Session checken met `supabase.auth.getUser()`
|
||||
### Stap 10: Authenticatie Setup
|
||||
|
||||
### Environment Variables
|
||||
- `.env.local` voor secrets
|
||||
- `NEXT_PUBLIC_` prefix voor client-side
|
||||
- Nooit API keys committen naar Git
|
||||
```bash
|
||||
npm install @supabase/auth-ui-react @supabase/auth-ui-shared
|
||||
```
|
||||
|
||||
### AI Helpt Met
|
||||
- Database schema suggesties
|
||||
- Query schrijven als je vastloopt
|
||||
- Error messages begrijpen
|
||||
- Code voorbeelden genereren
|
||||
**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}
|
||||
/>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
**Session checken:**
|
||||
```typescript
|
||||
const { data: { user } } = await supabase.auth.getUser()
|
||||
|
||||
if (user) {
|
||||
// User is ingelogd
|
||||
} else {
|
||||
// Redirect naar login
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Deployment naar Vercel (Productie)
|
||||
|
||||
### Stap 1: GitHub Repository
|
||||
|
||||
```bash
|
||||
# In je project folder
|
||||
git init
|
||||
git add .
|
||||
git commit -m "Initial commit"
|
||||
|
||||
# Maak repo op GitHub, dan:
|
||||
git remote add origin https://github.com/jouw-username/todo-app.git
|
||||
git push -u origin main
|
||||
```
|
||||
|
||||
### 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
|
||||
|
||||
| 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 een echt project zou je aparte databases hebben, maar voor deze cursus is dat niet nodig.
|
||||
|
||||
---
|
||||
|
||||
## Tools
|
||||
- Supabase (gratis tier)
|
||||
- Next.js
|
||||
- Supabase (gratis tier)
|
||||
- Vercel (gratis tier)
|
||||
- Cursor/OpenCode
|
||||
|
||||
---
|
||||
@@ -116,72 +271,79 @@ const { error } = await supabase
|
||||
|
||||
### Bouw een Todo App met Supabase
|
||||
|
||||
**Deel 1: Supabase Setup (20 min)**
|
||||
- Maak gratis Supabase account
|
||||
- Maak nieuw project
|
||||
- Kopieer URL en anon key naar `.env.local`
|
||||
|
||||
**Deel 2: Database via UI (20 min)**
|
||||
- Maak `todos` tabel via Table Editor
|
||||
- Kolommen: `id` (auto), `title` (text), `completed` (boolean), `created_at` (timestamp)
|
||||
- Voeg 3 test todos toe via UI
|
||||
|
||||
**Deel 3: Next.js Integratie (1 uur)**
|
||||
**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 Supabase client
|
||||
- Bouw simpele UI:
|
||||
- Lijst van todos ophalen en tonen
|
||||
- Form om nieuwe todo toe te voegen
|
||||
- Checkbox om todo af te vinken
|
||||
- Delete button
|
||||
- Maak `src/lib/supabase.ts`
|
||||
- Test: `npm run dev` werkt zonder errors
|
||||
|
||||
**Deel 4: Auth toevoegen (20 min)**
|
||||
- Installeer `@supabase/auth-ui-react`
|
||||
- Voeg login pagina toe met Auth UI component
|
||||
- Check of user ingelogd is
|
||||
**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
|
||||
|
||||
**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 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
|
||||
|
||||
### Deliverable
|
||||
- Werkende Todo app met Supabase backend
|
||||
- Login functionaliteit
|
||||
- CRUD operaties werken
|
||||
- Werkende Todo app lokaal
|
||||
- GitHub repository met code
|
||||
- Screenshot van werkende app
|
||||
|
||||
---
|
||||
|
||||
## Huiswerk (2 uur)
|
||||
|
||||
### Extend de Todo App
|
||||
### Deploy naar Productie + Uitbreiden
|
||||
|
||||
**Feature 1: Filtering (30 min)**
|
||||
- Filter op: Alle / Actief / Voltooid
|
||||
- Sorteer op datum
|
||||
|
||||
**Feature 2: User-specifieke todos (30 min)**
|
||||
- Voeg `user_id` kolom toe aan todos tabel
|
||||
- Filter todos op ingelogde user
|
||||
- Elke user ziet alleen eigen todos
|
||||
|
||||
**Feature 3: Polish (30 min)**
|
||||
- Loading states
|
||||
- Error handling met toast messages
|
||||
- Empty state ("Geen todos gevonden")
|
||||
|
||||
**Deploy (30 min)**
|
||||
**Deel 1: Deployment (30 min)**
|
||||
- Push code naar GitHub
|
||||
- Deploy naar Vercel
|
||||
- Voeg environment variables toe in Vercel dashboard
|
||||
- Test of alles werkt in productie
|
||||
- Configureer environment variables in Vercel
|
||||
- Voeg Vercel URL toe aan Supabase Redirect URLs
|
||||
- Test: app werkt op productie URL
|
||||
|
||||
**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"
|
||||
|
||||
**Deel 3: Polish (30 min)**
|
||||
- Styling verbeteren met Tailwind
|
||||
- Responsive design (mobile friendly)
|
||||
- Kleine animaties (fade in/out)
|
||||
|
||||
### Deliverable
|
||||
- Deployed Todo app op Vercel
|
||||
- Screenshot van werkende app
|
||||
- Link naar live versie
|
||||
- Deployed app op Vercel (werkende URL)
|
||||
- Alle features werken in productie
|
||||
- Screenshot van productie app
|
||||
|
||||
---
|
||||
|
||||
## Leerdoelen
|
||||
Na deze les kan de student:
|
||||
- Een Supabase project opzetten
|
||||
- Tabellen maken via de Supabase UI (zonder SQL)
|
||||
- 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
|
||||
- Basis CRUD operaties uitvoeren (create, read, update, delete)
|
||||
- Simpele authenticatie implementeren met Auth UI
|
||||
- Environment variables correct gebruiken
|
||||
- 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
|
||||
|
||||
Reference in New Issue
Block a user