fix: les 6

This commit is contained in:
2026-03-11 14:07:00 +01:00
parent d5066021ab
commit 9ffdecf2c4
117 changed files with 13198 additions and 5194 deletions

View File

@@ -1,444 +1,330 @@
# Les 14: Project Setup & Repository Structure
# Les 14: AI Chat Interface & Streaming
---
## Hoofdstuk
**Deel 4: Advanced AI Features** (Les 13-18)
**Deel 4: Advanced AI & Deployment** (Les 13-18)
## Beschrijving
Leer professionele project setup en repository structuur. Begrijp hoe een goed georganiseerd project AI tools effectiever maakt en samenwerking vergemakkelijkt.
Bouwen van professionele chat interfaces met streaming responses. Message rendering, markdown support, error handling, loading states, en UX patterns voor AI-powered features.
---
## Te Behandelen
## Te Behandelen (~45 min)
### Groepsdiscussie (15 min)
Bespreek klassikaal de AI assistant reflecties uit Les 13 - welke instructies werkten goed en welke niet?
### Waarom Project Structuur Belangrijk Is
**Voor jezelf:**
- Sneller code terugvinden
- Makkelijker onderhouden
- Minder bugs door consistentie
**Voor AI tools:**
- Betere context understanding
- Consistentere code generation
- Cursor/Claude begrijpt je project beter
**Voor samenwerking:**
- Anderen begrijpen je code sneller
- Standaard conventies = minder discussie
- Onboarding nieuwe developers eenvoudiger
- Chat UI patterns en best practices
- useChat hook deep dive (state, loading, error)
- Streaming response handling en real-time updates
- Message rendering strategies en optimizations
- Markdown rendering in chat messages
- Error handling en error boundaries
- Loading states en skeleton loaders
- User input validation and sanitization
- Accessibility in chat interfaces (ARIA labels)
- Message persistence (localStorage of database)
- Performance optimization
---
### Next.js 14 Project Structuur
### useChat Hook Deep Dive
**Aanbevolen structuur:**
```
project-root/
├── src/
│ ├── app/ # Next.js App Router
│ │ ├── (auth)/ # Route group voor auth pagina's
│ │ │ ├── login/
│ │ └── register/
│ ├── api/ # API routes
│ │ └── chat/
│ │ ├── dashboard/
│ │ ├── layout.tsx
│ │ ├── page.tsx
└── globals.css
│ │
├── components/ # React components
│ ├── ui/ # Basis UI components
│ │ │ ├── Button.tsx
│ │ │ ├── Input.tsx
│ │ └── Card.tsx
│ ├── layout/ # Layout components
│ ├── Header.tsx
├── Footer.tsx
└── Sidebar.tsx
└── features/ # Feature-specifieke components
├── auth/
│ │ └── dashboard/
│ │
│ ├── lib/ # Utilities en configuraties
├── supabase.ts # Supabase client
├── utils.ts # Helper functies
│ └── constants.ts # App constanten
│ ├── hooks/ # Custom React hooks
├── useAuth.ts
└── useTodos.ts
│ │
│ └── types/ # TypeScript types
├── database.ts
│ └── api.ts
├── public/ # Static assets
│ ├── images/
│ └── favicon.ico
├── docs/ # Documentatie
│ ├── PROMPT-LOG.md
│ ├── AI-DECISIONS.md
│ └── PROJECT-BRIEF.md
├── .cursorrules # Cursor AI configuratie
├── .env.local # Environment variables (niet in git!)
├── .env.example # Template voor env vars
├── .gitignore
├── package.json
├── tsconfig.json
├── tailwind.config.ts
└── README.md
**State management met useChat:**
```typescript
'use client'
import { useChat } from 'ai/react'
export function ChatComponent() {
const {
messages, // All messages in conversation
input, // Current input text
handleInputChange, // Update input
handleSubmit, // Send message
isLoading, // Is AI responding?
error, // Any errors?
} = useChat({
api: '/api/chat',
initialMessages: [], // Optional: pre-load messages
})
return (
<>
<div>
{messages.map((msg) => (
<div key={msg.id}>
<strong>{msg.role}:</strong> {msg.content}
</div>
))}
</div>
{isLoading && <div>AI is thinking...</div>}
{error && <div>Error: {error.message}</div>}
<form onSubmit={handleSubmit}>
<input
value={input}
onChange={handleInputChange}
disabled={isLoading}
/>
<button type="submit" disabled={isLoading}>Send</button>
</form>
</>
)
}
```
---
### Component Organisatie
### Message Rendering Patterns
**UI Components (src/components/ui/):**
- Herbruikbare, generieke components
- Geen business logic
- Props-driven
- Voorbeelden: Button, Input, Modal, Card
**Layout Components (src/components/layout/):**
- Structurele components
- Meestal één per type
- Voorbeelden: Header, Footer, Sidebar, Navigation
**Feature Components (src/components/features/):**
- Business logic bevattend
- Specifiek voor één feature
- Groepeer per feature/domein
---
### File Naming Conventions
**Components:**
```
✅ Button.tsx # PascalCase
✅ UserProfile.tsx
❌ button.tsx
❌ user-profile.tsx
**Basic pattern:**
```typescript
<div className="space-y-4">
{messages.map((msg) => (
<div
key={msg.id}
className={msg.role === 'user' ? 'ml-auto' : 'mr-auto'}
>
<div className="bg-gray-200 p-3 rounded">
{msg.content}
</div>
</div>
))}
</div>
```
**Hooks:**
```
✅ useAuth.ts # camelCase met 'use' prefix
✅ useTodos.ts
❌ UseAuth.ts
❌ auth-hook.ts
**With markdown rendering:**
```typescript
import ReactMarkdown from 'react-markdown'
<div className="bg-gray-200 p-3 rounded">
<ReactMarkdown>{msg.content}</ReactMarkdown>
</div>
```
**Utilities:**
```
✅ formatDate.ts # camelCase
✅ utils.ts
✅ constants.ts
```
**Types:**
```
✅ database.ts # camelCase
✅ User.types.ts # optioneel: .types suffix
**With message types:**
```typescript
{messages.map((msg) => (
<div key={msg.id} className={msg.role === 'user' ? 'user-message' : 'ai-message'}>
{msg.content}
</div>
))}
```
---
### .cursorrules Setup
### Error Handling
**Maak .cursorrules in project root:**
```markdown
# Project: [Jouw Project Naam]
**Structured error handling:**
## Tech Stack
- Next.js 14 met App Router
- TypeScript (strict mode)
- Tailwind CSS
- Supabase
- React Query
```typescript
try {
const response = await fetch('/api/chat', {
method: 'POST',
body: JSON.stringify({ messages }),
})
## File Structure
- Components in src/components/
- UI components in src/components/ui/
- API routes in src/app/api/
if (!response.ok) {
throw new Error(`API error: ${response.status}`)
}
## Code Conventions
- Functional components only
- Named exports (geen default exports)
- Props interface boven component
- Nederlandse comments
// Handle streaming...
} catch (error) {
console.error('Chat error:', error)
setError({
message: 'Failed to send message',
code: error instanceof Error ? error.message : 'unknown'
})
}
```
## Naming
- Components: PascalCase (Button.tsx)
- Hooks: camelCase met use prefix (useAuth.ts)
- Utils: camelCase (formatDate.ts)
## Styling
- Tailwind CSS classes
- Geen inline styles
- Responsive mobile-first
## TypeScript
- Strict mode
- Geen any types
- Interfaces voor props
- Types voor data
## Don'ts
- Geen console.log in productie
- Geen hardcoded strings
- Geen unused imports
**Error boundary:**
```typescript
<ErrorBoundary fallback={<div>Chat error occurred</div>}>
<ChatComponent />
</ErrorBoundary>
```
---
### Git Best Practices
### Loading States
**Commit Message Format:**
```
type: korte beschrijving
**Skeleton loader:**
```typescript
function MessageSkeleton() {
return (
<div className="animate-pulse">
<div className="bg-gray-300 h-4 rounded w-48 mb-2" />
<div className="bg-gray-300 h-4 rounded w-64" />
</div>
)
}
Types:
- feat: nieuwe feature
- fix: bug fix
- refactor: code verbetering
- docs: documentatie
- style: formatting
- test: tests toevoegen
```
**Voorbeelden:**
```bash
git commit -m "feat: add user authentication with Supabase"
git commit -m "fix: resolve hydration error in TodoList"
git commit -m "docs: update README with setup instructions"
```
**.gitignore essentials:**
```
# Dependencies
node_modules/
# Environment
.env*.local
# Next.js
.next/
out/
# IDE
.idea/
.vscode/
# OS
.DS_Store
{isLoading && <MessageSkeleton />}
```
---
### Environment Variables
### Input Validation
**Structuur:**
```bash
# .env.local (NOOIT committen!)
NEXT_PUBLIC_SUPABASE_URL=https://xxx.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJhbGci...
OPENAI_API_KEY=sk-...
**Validate before sending:**
# .env.example (WEL committen)
NEXT_PUBLIC_SUPABASE_URL=your-supabase-url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
OPENAI_API_KEY=your-openai-key
```typescript
function handleSubmit(e: React.FormEvent) {
e.preventDefault()
// Trim whitespace
const trimmedInput = input.trim()
// Validate non-empty
if (!trimmedInput) {
setError('Message cannot be empty')
return
}
// Validate length
if (trimmedInput.length > 1000) {
setError('Message too long (max 1000 chars)')
return
}
// Send message
handleSubmit(e)
}
```
**Regels:**
- `NEXT_PUBLIC_` prefix = zichtbaar in browser
- Zonder prefix = alleen server-side
- Nooit secrets in `NEXT_PUBLIC_` vars
---
### README.md Template
### Message Persistence
```markdown
# Project Naam
**Save to localStorage:**
Korte beschrijving van je project.
```typescript
const [messages, setMessages] = useState(() => {
const saved = localStorage.getItem('chat_history')
return saved ? JSON.parse(saved) : []
})
## Features
- Feature 1
- Feature 2
- Feature 3
// Save whenever messages change
useEffect(() => {
localStorage.setItem('chat_history', JSON.stringify(messages))
}, [messages])
```
## Tech Stack
- Next.js 14
- TypeScript
- Tailwind CSS
- Supabase
- Vercel AI SDK
## Getting Started
### Prerequisites
- Node.js 18+
- npm of yarn
- Supabase account
### Installation
1. Clone de repository
```bash
git clone https://github.com/username/project.git
cd project
```
2. Installeer dependencies
```bash
npm install
```
3. Maak .env.local (zie .env.example)
4. Start development server
```bash
npm run dev
```
## Environment Variables
Zie `.env.example` voor benodigde variabelen.
## Deployment
Deployed op Vercel: [productie-url]
## Documentatie
- [PROMPT-LOG.md](docs/PROMPT-LOG.md)
- [AI-DECISIONS.md](docs/AI-DECISIONS.md)
**Save to database:**
```typescript
const saveMessage = async (message: Message) => {
await fetch('/api/messages', {
method: 'POST',
body: JSON.stringify({
content: message.content,
role: message.role,
userId: user.id,
}),
})
}
```
---
## Tools
- Vercel AI SDK
- React Markdown
- Cursor
- Git
- GitHub
- TypeScript
---
## Lesopdracht (2 uur)
## Lesopdracht (2 uur, klassikaal)
### Setup Je Eindproject
### Build Professional Chat Interface
**Deel 1: Project Structuur (45 min)**
**Groepsdiscussie (15 min):**
Bespreek klassikaal de Vercel AI SDK ervaringen uit Les 13 - welke tool calling patterns werkten goed?
1. Maak nieuw Next.js project:
```bash
npx create-next-app@latest mijn-eindproject --typescript --tailwind --app
```
**Deel 1: Chat Component (45 min)**
2. Maak de mappenstructuur:
- src/components/ui/
- src/components/layout/
- src/components/features/
- src/lib/
- src/hooks/
- src/types/
- docs/
Build components/ChatInterface.tsx:
1. Use useChat hook
2. Render messages with proper styling
3. User vs AI message styling
4. Input form with validation
5. Tailwind + shadcn/ui components
3. Maak placeholder files:
- src/lib/supabase.ts
- src/lib/utils.ts
**Deel 2: Markdown & Error Handling (30 min)**
**Deel 2: Configuratie (30 min)**
1. Install react-markdown: `npm install react-markdown`
2. Render AI responses with markdown
3. Add error boundary
4. Show error messages to user
5. Proper loading states
1. Maak .cursorrules met jouw conventies
2. Maak .env.example
3. Update .gitignore
4. Maak README.md met template
**Deel 3: UX Improvements (30 min)**
**Deel 3: Git Setup (25 min)**
1. Auto-scroll to latest message
2. Disable input while loading
3. Show message count/token usage
4. Add clear chat history button
5. Save messages to localStorage
1. git init
2. Initial commit met goede message
3. Push naar GitHub
4. Check: .env.local NIET gecommit?
**Deel 4: Testing (15 min)**
**Deel 4: Documentatie Start (20 min)**
Maak in docs/:
- PROJECT-BRIEF.md (beschrijving eindproject)
- PROMPT-LOG.md (leeg template)
- AI-DECISIONS.md (leeg template)
Test chat interface locally with various inputs and error scenarios.
### Deliverable
- GitHub repository met correcte structuur
- .cursorrules file
- README.md
- docs/ folder met templates
- Werkende chat interface component
- Markdown rendering working
- Error handling implemented
- LocalStorage persistence
- GitHub commit with chat UI
---
## Huiswerk (2 uur)
### Bouw Project Foundation
### Integrate Chat into Your Project
**Deel 1: Base Components (1 uur)**
**Deel 1: Project Integration (1 uur)**
Maak basis UI components met AI hulp:
- src/components/ui/Button.tsx
- src/components/ui/Input.tsx
- src/components/ui/Card.tsx
- src/components/layout/Header.tsx
- src/components/layout/Footer.tsx
1. Add chat component to your app
2. Connect to your API route with tools
3. Style to match your design
4. Test with actual tools/integrations
5. Fix any bugs
Requirements:
- TypeScript interfaces voor props
- Tailwind styling
- Responsive design
- Volg je .cursorrules
**Deel 2: Enhanced Features (30 min)**
**Deel 2: Supabase Setup (30 min)**
Add one of these:
- Message copy button
- Regenerate response option
- Clear history confirmation
- Export chat history
- Message timestamps
1. Maak Supabase project (of hergebruik van Les 9)
2. Configureer src/lib/supabase.ts
3. Voeg env vars toe aan .env.local
4. Test connectie
**Deel 3: Performance & Polish (30 min)**
**Deel 3: Eerste Feature (30 min)**
Kies je eindproject en implementeer 1 basisfeature:
- Recipe Generator: ingredient input form
- Budget Buddy: expense entry form
- Travel Planner: destination search
Commit en push!
1. Optimize re-renders (useMemo, useCallback)
2. Virtual scrolling for long chats
3. Better accessibility (keyboard nav)
4. Mobile responsive tweaks
5. Update docs/AI-DECISIONS.md
### Deliverable
- Werkende UI components
- Supabase connectie
- 1 basic feature
- Alle commits met goede messages
---
## 💡 Eindopdracht
Dit is een goed moment om te starten met **deelopdracht 1** van je eindopdracht. De setup die je vandaag maakt kun je direct gebruiken voor je eindproject. Bespreek je projectidee met de docent als je feedback wilt.
- Chat fully integrated in project
- Enhanced features implemented
- Performance optimized
- GitHub commits with improvements
---
## Leerdoelen
Na deze les kan de student:
- Een professionele project structuur opzetten
- File naming conventions toepassen
- Een effectieve .cursorrules file schrijven
- Git best practices volgen
- Environment variables correct beheren
- Een README.md schrijven
- Project documentatie structureren
- useChat hook volledig begrijpen en gebruiken
- Professionele chat UI patterns implementeren
- Markdown rendering in chat messages
- Error handling en error boundaries toepassen
- Loading states en skeletons bouwen
- User input valideren en sanitizen
- Message persistence (localStorage/DB)
- Accessibility in chat interfaces verbeteren
- Performance optimizations toepassen
- Complete chat feature in Next.js app integreren