6.0 KiB
Les 11 — Lesopdracht
Bouw je eigen AI + Supabase app
Vak: AI-Assisted Development Opleiding: NOVI Hogeschool Utrecht Wanneer: Thuis, vóór volgende les Inleveren: GitHub URL + screenshot van werkende chat
Doel
Bouw een complete versie van wat Tim live demonstreerde — met je eigen thema. Tim bouwde Polderfest 2027. Jij bouwt iets anders.
Je oefent end-to-end:
- Next.js project from scratch
- Nieuwe Supabase aanmaken + koppelen
- Eigen seed-script schrijven (mag AI bij helpen)
- Chat-route + chat-UI met
streamText+useChat - 3 vragen kunnen stellen die alleen via jouw data beantwoord kunnen worden
Belangrijk: dit is niet dezelfde Polderfest-demo namaken. Je kiest een eigen thema. Anders leer je vooral kopiëren.
Vereisten
Jouw thema moet:
- Volledig fictief zijn — geen Spotify, geen restaurants in Amsterdam, geen Wikipedia-data
- Minstens 5 velden hebben (waarvan 1 categorisch, 1 numeriek, 1 tekstrijk)
- Minstens 100 records bevatten
- Vragen oproepen die je écht niet aan ChatGPT kunt stellen zonder jouw data
Verboden thema's (te bekend voor LLMs):
- Restaurants in een echte stad
- Films / muziek / boeken die echt bestaan
- Sport-statistieken uit de echte wereld
- Klimaat / financiële data uit publieke bronnen
Geschikte thema-richtingen (kies of bedenk eigen):
- Fictief restaurant-aggregator in een verzonnen stad (bv. "Polderstad")
- Galactische bestuurders archief (sci-fi)
- Verzonnen scriptie-archief van NOVI (1000 nep-titels)
- Fictieve museumcollectie met verzonnen kunstenaars
- Fictief NPO-programma overzicht voor 2030
- Verzonnen mysteries / cryptid-sightings database NL
- D&D campagne-NPCs voor een fictieve wereld
- Fictieve nederlands ondernemers ecosysteem
Stappenplan
Stap 1 — Thema kiezen + schema ontwerpen (30 min)
- Bedenk thema
- Schrijf op papier (of in Notion): welke velden? Welke vragen wil je kunnen stellen?
- Vertaal naar Supabase SQL schema (zie
schema.sqlvan Polderfest als voorbeeld)
Stap 2 — Next.js project + Supabase (15 min)
npx create-next-app@latest mijn-thema \
--typescript --tailwind --app --eslint --no-src-dir --turbopack
cd mijn-thema
npm i @supabase/supabase-js ai @ai-sdk/openai zod
npm i tsx dotenv --save-dev
- Maak nieuwe Supabase project aan
- Run je schema in SQL Editor
- Vul
.env.localmet URL + keys + OpenAI key
Stap 3 — Seed script (45 min)
Open seed-polderfest.ts (zie bijlage) als referentie. Je hebt twee opties:
Optie A — Met de hand:
- Kopieer de structuur
- Vervang Polderfest-bouwstenen (genres, stages, cities…) door jouw thema-bouwstenen
- Pas de
generateBandfunctie aan naargenerateItemvoor jouw thema
Optie B — Met AI hulp (aanbevolen):
- Open OpenCode / Cursor met
seed-polderfest.tsals context - Vraag: "Pas dit seed-script aan voor [mijn thema]. Schema is [paste schema]. Genereer 100+ records."
- Review wat AI maakt — vragen om aanpassingen waar nodig
Run je seed:
npx tsx scripts/seed-mijn-thema.ts
Verifieer in Supabase Table Editor: 100+ records.
Stap 4 — Chat route (20 min)
app/api/chat/route.ts — gebruik Polderfest-versie als template:
import { streamText } from "ai";
import { openai } from "@ai-sdk/openai";
import { createClient } from "@supabase/supabase-js";
const supabase = createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
);
export async function POST(req: Request) {
const { messages } = await req.json();
const { data: items } = await supabase.from("items").select("*");
const context = items!.map((i) =>
`- ${i.name} (${i.category}, ${i.rating})`
).join("\n");
const system = `Je bent een assistent voor [thema-naam].
Hier is alle data:
${context}
Beantwoord vragen op basis van bovenstaande data. Verzin niets.
Antwoord in het Nederlands.`;
const result = streamText({
model: openai("gpt-4o-mini"),
system,
messages,
});
return result.toDataStreamResponse();
}
Stap 5 — Chat UI (15 min)
app/chat/page.tsx — kopieer Polderfest UI, pas titel + placeholder aan.
Stap 6 — Testen + 3 vragen (15 min)
Browse naar /chat. Stel deze 3 vragen aan jouw AI:
- Een filter-vraag ("Welke X hebben Y?")
- Een aggregatie-vraag ("Hoeveel X zijn er in totaal?" / "Wie heeft de hoogste Z?")
- Een samenvatting-vraag ("Vat de Z-categorie samen in 3 zinnen")
Screenshots van werkende antwoorden bewaren — die heb je nodig.
Inleveren (vóór volgende les)
- GitHub repo met je code
- 3 screenshots van werkende chat-antwoorden in je README
- Eén alinea onder de screenshots: waarom kan een gewone LLM deze vragen niet beantwoorden zonder jouw data?
Veelvoorkomende problemen
| Probleem | Oplossing |
|---|---|
OPENAI_API_KEY is not defined |
Dev server herstarten na .env.local aanpassen |
Supabase insert: permission denied |
Gebruik SUPABASE_SERVICE_ROLE_KEY in seed-script (geen anon) |
| AI verzint dingen | System prompt verstevigen: "Verzin niets. Gebruik alleen onze data." |
| AI antwoordt in Engels | Voeg toe aan prompt: "Antwoord in het Nederlands." |
| Chat hangt / streamt niet | API endpoint moet result.toDataStreamResponse() returnen |
tsx command not found |
npm i tsx --save-dev, run met npx tsx ... |
Tijd-indicatie
| Stap | Tijd |
|---|---|
| Thema + schema bedenken | 30 min |
| Project + Supabase setup | 15 min |
| Seed script (met AI hulp) | 45 min |
| Chat route + UI | 35 min |
| Testen + screenshots | 15 min |
| Totaal | ~2,5 uur |
Loop je vast? Vraag in Brightspace of plan korte 1-op-1 met Tim.
Tips
- Begin klein. 100 records is genoeg. 500 als je extra wil.
- AI laten helpen bij seed. Schaal je productiviteit 10×.
- System prompt is je hefboom. Goede prompt = goede antwoorden. Slechte prompt = AI verzint.
- Test met simpele vraag eerst ("Hoeveel records zijn er?"). Dan opbouwen.
- Token cost in de gaten houden — onze hele les kostte <2 cent. Jouw test ook.
Succes!