refactor: rename /releases route to /documentatie
Complete route rename from /releases to /documentatie to better reflect the continuous build-in-public nature of the project (not formal releases). Changes: - Renamed app/(marketing)/releases/ → app/(marketing)/documentatie/ - Renamed content/nl/releases/ → content/nl/documentatie/ - Updated all internal links from /releases to /documentatie - Updated middleware publicRoutes (/releases → /documentatie) - Updated navigation.json link - Updated build-timeline.tsx documentation link - Updated all component href attributes - Updated lib/mdx/releases.ts content directory path - Updated sidebar component paths and checks - Updated MDX documentation files with new routes Files changed: - app/(marketing)/documentatie/[category]/page.tsx (footer link) - app/(marketing)/documentatie/page.tsx (card links) - app/(marketing)/documentatie/components/release-sidebar.tsx (all links) - app/(marketing)/components/build-timeline.tsx (documentation link) - content/nl/navigation.json (header link) - content/nl/documentatie/*.mdx (internal references) - middleware.ts (publicRoutes) - lib/mdx/releases.ts (RELEASES_DIR path) This prevents future confusion between "releases" (versioned software releases) and "documentatie" (continuous build documentation). Old URL: /releases/[category] New URL: /documentatie/[category] The old /releases route now returns 404 as expected.
This commit is contained in:
100
content/nl/documentatie/_index.json
Normal file
100
content/nl/documentatie/_index.json
Normal file
@@ -0,0 +1,100 @@
|
||||
{
|
||||
"groups": [
|
||||
{
|
||||
"id": "foundation",
|
||||
"title": "Foundation",
|
||||
"description": "Basis setup en infrastructuur",
|
||||
"order": 1
|
||||
},
|
||||
{
|
||||
"id": "features",
|
||||
"title": "Core Features",
|
||||
"description": "EPD functionaliteit",
|
||||
"order": 2
|
||||
},
|
||||
{
|
||||
"id": "infrastructure",
|
||||
"title": "Infrastructure",
|
||||
"description": "Ondersteunende systemen",
|
||||
"order": 3
|
||||
},
|
||||
{
|
||||
"id": "bugs",
|
||||
"title": "Bugs & Fixes",
|
||||
"description": "Opgeloste bugs en troubleshooting",
|
||||
"order": 4
|
||||
}
|
||||
],
|
||||
"categories": [
|
||||
{
|
||||
"slug": "authentication",
|
||||
"title": "Authentication",
|
||||
"group": "foundation",
|
||||
"description": "Login, signup en password reset",
|
||||
"order": 1
|
||||
},
|
||||
{
|
||||
"slug": "database",
|
||||
"title": "Database & Schema",
|
||||
"group": "foundation",
|
||||
"description": "PostgreSQL schema en RLS policies",
|
||||
"order": 2
|
||||
},
|
||||
{
|
||||
"slug": "environment",
|
||||
"title": "Environment Setup",
|
||||
"group": "foundation",
|
||||
"description": "Development en deployment configuratie",
|
||||
"order": 3
|
||||
},
|
||||
{
|
||||
"slug": "dashboard",
|
||||
"title": "Dashboard & Navigation",
|
||||
"group": "features",
|
||||
"description": "EPD layout en navigatie",
|
||||
"order": 4
|
||||
},
|
||||
{
|
||||
"slug": "client-management",
|
||||
"title": "Client Management",
|
||||
"group": "features",
|
||||
"description": "CRUD operations voor cliënten",
|
||||
"order": 5
|
||||
},
|
||||
{
|
||||
"slug": "ai-features",
|
||||
"title": "AI Integrations",
|
||||
"group": "features",
|
||||
"description": "AI-gestuurde workflows",
|
||||
"order": 6
|
||||
},
|
||||
{
|
||||
"slug": "hosting",
|
||||
"title": "Hosting & Deployment",
|
||||
"group": "infrastructure",
|
||||
"description": "Vercel deployment en CI/CD",
|
||||
"order": 7
|
||||
},
|
||||
{
|
||||
"slug": "design-system",
|
||||
"title": "Design System",
|
||||
"group": "infrastructure",
|
||||
"description": "UI components en styling",
|
||||
"order": 8
|
||||
},
|
||||
{
|
||||
"slug": "performance",
|
||||
"title": "Performance",
|
||||
"group": "infrastructure",
|
||||
"description": "Optimalisaties en monitoring",
|
||||
"order": 9
|
||||
},
|
||||
{
|
||||
"slug": "webpack-module-resolution",
|
||||
"title": "Webpack Module Resolution",
|
||||
"group": "bugs",
|
||||
"description": "Fix voor Server/Client Component import issues",
|
||||
"order": 10
|
||||
}
|
||||
]
|
||||
}
|
||||
198
content/nl/documentatie/authentication.mdx
Normal file
198
content/nl/documentatie/authentication.mdx
Normal file
@@ -0,0 +1,198 @@
|
||||
---
|
||||
title: "Authentication & User Management"
|
||||
category: "authentication"
|
||||
group: "foundation"
|
||||
version: "0.1.0"
|
||||
releaseDate: "2024-11-15"
|
||||
status: "completed"
|
||||
description: "Login, signup en password reset functionaliteit via Supabase Auth"
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
De authentication flow vormt de basis van het Mini-ECD systeem. Gebruikers kunnen nu veilig inloggen, accounts aanmaken en wachtwoorden resetten via Supabase Auth integratie.
|
||||
|
||||
**Key features:**
|
||||
- Email/password authentication
|
||||
- Demo account voor quick testing
|
||||
- Password reset flow
|
||||
- Session management met JWT tokens
|
||||
- Security via RLS policies
|
||||
|
||||
---
|
||||
|
||||
## Features
|
||||
|
||||
### Login Flow
|
||||
|
||||

|
||||
*Login formulier met email/password fields en demo account optie*
|
||||
|
||||
De login pagina biedt twee opties:
|
||||
- **Handmatige login:** Email en wachtwoord
|
||||
- **Demo account:** One-click toegang met `demo@mini-ecd.demo`
|
||||
|
||||
**Functionaliteit:**
|
||||
- Client-side validatie (email format, min 8 characters)
|
||||
- Server-side authenticatie via Supabase
|
||||
- Error handling met user-friendly messages
|
||||
- Redirect naar `/epd/clients` na succesvolle login
|
||||
|
||||
**Demo:**
|
||||
1. Ga naar `/login`
|
||||
2. Klik op "Demo Account Proberen"
|
||||
3. Automatisch ingelogd en doorgestuurd
|
||||
|
||||
### Signup Flow
|
||||
|
||||
Nieuwe gebruikers kunnen zich registreren met:
|
||||
- Email adres (moet uniek zijn)
|
||||
- Wachtwoord (min 8 karakters)
|
||||
- Wachtwoord confirmatie
|
||||
|
||||
**Auto-login functionaliteit:**
|
||||
- Email confirmation is uitgeschakeld voor development
|
||||
- Direct ingelogd na signup
|
||||
- Redirect naar EPD applicatie
|
||||
|
||||
**Duplicate email handling:**
|
||||
- Auth hook detecteert bestaande emails
|
||||
- Automatische login als email al bestaat
|
||||
- User-friendly message: "Dit emailadres bestaat al. Je bent nu ingelogd!"
|
||||
|
||||
### Password Reset
|
||||
|
||||
*Coming soon - gepland voor volgende release*
|
||||
|
||||
---
|
||||
|
||||
## Technical Notes
|
||||
|
||||
### Architecture
|
||||
|
||||
**Stack:**
|
||||
- Supabase Auth voor user management
|
||||
- Next.js 15 Server Components
|
||||
- Client-side auth helpers in `/lib/auth/client.ts`
|
||||
|
||||
**Security:**
|
||||
- PKCE flow voor OAuth (toekomst)
|
||||
- JWT tokens in httpOnly cookies
|
||||
- RLS policies voor data isolatie
|
||||
- No API keys in frontend code
|
||||
|
||||
### File Structure
|
||||
|
||||
```
|
||||
app/
|
||||
├── login/
|
||||
│ └── page.tsx # Login/signup form
|
||||
└── auth/
|
||||
└── callback/
|
||||
└── route.ts # OAuth callback (future)
|
||||
|
||||
lib/
|
||||
├── auth/
|
||||
│ ├── client.ts # loginWithPassword, signUpWithPassword
|
||||
│ └── server.ts # createClient for server components
|
||||
|
||||
supabase/
|
||||
└── functions/
|
||||
└── auth-hook/
|
||||
└── index.ts # Duplicate email detection
|
||||
```
|
||||
|
||||
### Key Functions
|
||||
|
||||
```tsx
|
||||
// Login function
|
||||
export async function loginWithPassword(email: string, password: string) {
|
||||
const supabase = createClient()
|
||||
const { data, error } = await supabase.auth.signInWithPassword({
|
||||
email,
|
||||
password,
|
||||
})
|
||||
|
||||
if (error) throw error
|
||||
return data
|
||||
}
|
||||
|
||||
// Signup with auto-login
|
||||
export async function signUpWithPassword(email: string, password: string) {
|
||||
const supabase = createClient()
|
||||
const { data, error } = await supabase.auth.signUp({
|
||||
email,
|
||||
password,
|
||||
options: {
|
||||
emailRedirectTo: `${origin}/auth/callback`,
|
||||
},
|
||||
})
|
||||
|
||||
if (error) throw error
|
||||
return data
|
||||
}
|
||||
```
|
||||
|
||||
### Auth Hook
|
||||
|
||||
Edge Function voor duplicate email detection:
|
||||
|
||||
```typescript
|
||||
// Prevents duplicate signups by auto-logging in existing users
|
||||
if (event === 'signup' && existingUser) {
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
error: {
|
||||
message: 'Dit emailadres is al geregistreerd. Je wordt automatisch ingelogd.',
|
||||
code: 'user_already_registered',
|
||||
data: { shouldAutoLogin: true }
|
||||
}
|
||||
}),
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Metrics
|
||||
|
||||
**Development:**
|
||||
- ⏱️ Build tijd: 6 uur
|
||||
- 📝 Lines of code: ~380
|
||||
- 🧪 Tests: Manual testing (geautomatiseerde tests komen later)
|
||||
|
||||
**Performance:**
|
||||
- 🚀 Login response: < 500ms
|
||||
- 📦 Bundle size: +15kb (auth client)
|
||||
- 💾 Database queries: 1 per login
|
||||
|
||||
**Cost:**
|
||||
- 💰 Supabase: €0 (free tier)
|
||||
- 💰 Edge Functions: €0 (within limits)
|
||||
|
||||
---
|
||||
|
||||
## What's Next
|
||||
|
||||
Geplande verbeteringen voor volgende releases:
|
||||
|
||||
- 🔜 Password reset flow
|
||||
- 🔜 Email verification (production)
|
||||
- 🔜 OAuth providers (Google, GitHub)
|
||||
- 🔜 Multi-factor authentication
|
||||
- 🔜 Session management dashboard
|
||||
|
||||
---
|
||||
|
||||
## Related Links
|
||||
|
||||
**Timeline:**
|
||||
- [Week 1 - Foundation & Marketing](#timeline)
|
||||
|
||||
**Code:**
|
||||
- [Authentication client library](https://github.com/yourusername/mini-ecd/blob/main/lib/auth/client.ts)
|
||||
- [Auth hook function](https://github.com/yourusername/mini-ecd/blob/main/supabase/functions/auth-hook)
|
||||
|
||||
**Documentation:**
|
||||
- [Supabase Auth Docs](https://supabase.com/docs/guides/auth)
|
||||
396
content/nl/documentatie/release-notes-system.mdx
Normal file
396
content/nl/documentatie/release-notes-system.mdx
Normal file
@@ -0,0 +1,396 @@
|
||||
---
|
||||
title: "Documentation System"
|
||||
category: "release-notes-system"
|
||||
group: "infrastructure"
|
||||
version: "0.2.0"
|
||||
releaseDate: "2024-11-19"
|
||||
status: "completed"
|
||||
description: "MDX-based documentatie systeem voor transparante build-in-public feature docs"
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Een volledig MDX-based documentatie systeem waarmee we eenvoudig en transparant kunnen documenteren wat er gebouwd wordt. Het systeem maakt het mogelijk om feature documentatie te schrijven in Markdown, met support voor afbeeldingen, code snippets en rich formatting.
|
||||
|
||||
**Waarom dit belangrijk is:**
|
||||
- 📝 Makkelijk te schrijven (Markdown/MDX)
|
||||
- 🎨 Rich content support (images, code, links)
|
||||
- 🗂️ Thematische organisatie (niet chronologisch)
|
||||
- 📱 Mobile-first responsive design
|
||||
- ⚡ Performance (Static Site Generation)
|
||||
- 🔍 SEO-vriendelijk met metadata per release
|
||||
|
||||
---
|
||||
|
||||
## Features
|
||||
|
||||
### MDX Content System
|
||||
|
||||
Het hart van het systeem: schrijf release notes in MDX bestanden met frontmatter metadata.
|
||||
|
||||
**Voorbeeld template:**
|
||||
```mdx
|
||||
---
|
||||
title: "Feature Name"
|
||||
category: "feature-slug"
|
||||
group: "foundation | features | infrastructure"
|
||||
version: "0.1.0"
|
||||
releaseDate: "2024-11-19"
|
||||
status: "completed | in_progress | planned"
|
||||
description: "Short description"
|
||||
---
|
||||
|
||||
## Overview
|
||||
Content here...
|
||||
```
|
||||
|
||||
**Voordelen:**
|
||||
- Markdown syntax = makkelijk schrijven
|
||||
- Frontmatter voor metadata
|
||||
- MDX = React components in content mogelijk
|
||||
- Version control via Git
|
||||
- Automatische parsing en rendering
|
||||
|
||||
### Thematische Sidebar Navigatie
|
||||
|
||||
Releases zijn georganiseerd op functionaliteit, niet op chronologische volgorde.
|
||||
|
||||
**Groepen:**
|
||||
- **Foundation** - Basis setup (Auth, Database, Environment)
|
||||
- **Core Features** - EPD functionaliteit (Dashboard, Clients, AI)
|
||||
- **Infrastructure** - Ondersteunend (Hosting, Design, Performance)
|
||||
|
||||
**Features:**
|
||||
- Collapsible sections per group
|
||||
- Status indicators (completed/in progress/planned)
|
||||
- Active state highlighting
|
||||
- Auto-generated from MDX files
|
||||
|
||||
### Overview Page
|
||||
|
||||
Centrale pagina met overzicht van alle releases, gegroepeerd op status.
|
||||
|
||||
**Sections:**
|
||||
- ✅ Voltooid - Afgeronde features
|
||||
- 🔄 In Progress - Features in ontwikkeling
|
||||
- ⏳ Gepland - Toekomstige features
|
||||
|
||||
**Stats cards:**
|
||||
- Aantal voltooide releases
|
||||
- Aantal in-progress releases
|
||||
- Aantal geplande releases
|
||||
|
||||
### Detail Pages
|
||||
|
||||
Individuele pagina per release met volledige content.
|
||||
|
||||
**Features:**
|
||||
- Rich MDX rendering
|
||||
- Custom styled components
|
||||
- Code syntax highlighting
|
||||
- Responsive images met captions
|
||||
- SEO metadata per page
|
||||
- Navigation (terug naar overview, naar timeline)
|
||||
|
||||
### Mobile Responsive
|
||||
|
||||
**Desktop:**
|
||||
- Fixed sidebar (256px width)
|
||||
- Full content area
|
||||
- Collapsible groups
|
||||
|
||||
**Mobile:**
|
||||
- Horizontal scroll tabs boven content
|
||||
- Touch-friendly navigation
|
||||
- Optimized voor kleine schermen
|
||||
|
||||
### Custom MDX Components
|
||||
|
||||
Styled components voor consistente formatting:
|
||||
|
||||
**Typography:**
|
||||
- Headings (h1-h4) met spacing
|
||||
- Paragraphs met optimale line-height
|
||||
- Lists (ordered/unordered)
|
||||
- Blockquotes met teal accent
|
||||
|
||||
**Media:**
|
||||
- Images met captions en responsive sizing
|
||||
- Code blocks met syntax highlighting
|
||||
- Tables met styled headers
|
||||
|
||||
**Links:**
|
||||
- Internal links (Next.js Link)
|
||||
- External links met proper attributes
|
||||
- Teal color scheme (consistent met brand)
|
||||
|
||||
---
|
||||
|
||||
## Technical Notes
|
||||
|
||||
### Architecture
|
||||
|
||||
**Stack:**
|
||||
- Next.js 15 App Router
|
||||
- next-mdx-remote voor MDX rendering
|
||||
- gray-matter voor frontmatter parsing
|
||||
- TypeScript voor type safety
|
||||
|
||||
**Rendering:**
|
||||
- Server-side MDX parsing
|
||||
- Static Site Generation (SSG)
|
||||
- Pre-rendered HTML voor performance
|
||||
- Client-side hydration
|
||||
|
||||
### File Structure
|
||||
|
||||
```
|
||||
# Code
|
||||
app/(marketing)/documentatie/
|
||||
├── layout.tsx # Sidebar wrapper
|
||||
├── page.tsx # Overview
|
||||
├── [category]/
|
||||
│ └── page.tsx # Detail renderer
|
||||
└── components/
|
||||
├── release-sidebar.tsx
|
||||
└── mdx-components.tsx
|
||||
|
||||
# Content
|
||||
content/nl/documentatie/
|
||||
├── _index.json # Categories metadata
|
||||
├── authentication.mdx
|
||||
└── release-notes-system.mdx
|
||||
|
||||
# Utilities
|
||||
lib/mdx/
|
||||
└── releases.ts # MDX parsing functions
|
||||
|
||||
# Templates
|
||||
docs/templates/
|
||||
└── release-note-template.mdx
|
||||
```
|
||||
|
||||
### Key Functions
|
||||
|
||||
```typescript
|
||||
// Get all release notes
|
||||
export async function getAllReleases(): Promise<ReleaseNote[]> {
|
||||
const files = fs.readdirSync(RELEASES_DIR)
|
||||
// Parse MDX files, extract frontmatter
|
||||
// Sort by group and category
|
||||
return releases
|
||||
}
|
||||
|
||||
// Get single release by slug
|
||||
export async function getRelease(slug: string): Promise<ReleaseNote | null> {
|
||||
const filePath = path.join(RELEASES_DIR, `${slug}.mdx`)
|
||||
const { data, content } = matter(fileContent)
|
||||
return { slug, frontmatter: data, content }
|
||||
}
|
||||
```
|
||||
|
||||
### Static Site Generation
|
||||
|
||||
```typescript
|
||||
// Generate static params for all releases
|
||||
export async function generateStaticParams() {
|
||||
const releases = await getAllReleases()
|
||||
return releases.map((release) => ({
|
||||
category: release.slug,
|
||||
}))
|
||||
}
|
||||
```
|
||||
|
||||
**Voordelen:**
|
||||
- Pre-rendered HTML = snelle load times
|
||||
- No runtime MDX parsing = beter performance
|
||||
- SEO-friendly = search engines kunnen content lezen
|
||||
|
||||
---
|
||||
|
||||
## Improvements
|
||||
|
||||
**Developer Experience:**
|
||||
- Template bestand voor consistente structuur
|
||||
- TypeScript types voor frontmatter
|
||||
- Auto-completion in VS Code (frontmatter schema)
|
||||
|
||||
**User Experience:**
|
||||
- Responsive design voor alle devices
|
||||
- Snelle navigatie met sidebar
|
||||
- Clear visual hierarchy
|
||||
- Status badges voor transparency
|
||||
|
||||
**Performance:**
|
||||
- Static generation = < 100ms load time
|
||||
- Optimized images (Next.js Image)
|
||||
- Minimal JavaScript bundle (+12kb voor MDX parser)
|
||||
|
||||
---
|
||||
|
||||
## Workflow
|
||||
|
||||
### Nieuwe Release Note Toevoegen
|
||||
|
||||
**Stap 1:** Kopieer template
|
||||
```bash
|
||||
cp docs/templates/release-note-template.mdx \
|
||||
content/nl/documentatie/new-feature.mdx
|
||||
```
|
||||
|
||||
**Stap 2:** Vul frontmatter in
|
||||
```yaml
|
||||
---
|
||||
title: "New Feature Name"
|
||||
category: "new-feature"
|
||||
group: "features"
|
||||
version: "0.3.0"
|
||||
releaseDate: "2024-11-20"
|
||||
status: "completed"
|
||||
description: "Short description here"
|
||||
---
|
||||
```
|
||||
|
||||
**Stap 3:** Schrijf content in Markdown
|
||||
|
||||
**Stap 4:** (Optioneel) Voeg screenshots toe
|
||||
```bash
|
||||
mkdir -p public/documentatie/new-feature/
|
||||
# Add images: screenshot-1.png, etc.
|
||||
```
|
||||
|
||||
**Stap 5:** Build en test
|
||||
```bash
|
||||
npm run build
|
||||
npm run dev
|
||||
# Visit /documentatie/new-feature
|
||||
```
|
||||
|
||||
**Stap 6:** Commit en push
|
||||
```bash
|
||||
git add content/nl/documentatie/new-feature.mdx
|
||||
git commit -m "docs: add new-feature release note"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Integration
|
||||
|
||||
### Timeline Integration
|
||||
|
||||
Timeline component heeft nu link naar release notes:
|
||||
|
||||
```tsx
|
||||
<a href="/documentatie">
|
||||
Bekijk gedetailleerde release notes →
|
||||
</a>
|
||||
```
|
||||
|
||||
### Navigation Integration
|
||||
|
||||
Header navigatie heeft "Releases" link toegevoegd:
|
||||
|
||||
```json
|
||||
{
|
||||
"links": [
|
||||
{ "label": "Releases", "href": "/documentatie" },
|
||||
{ "label": "Contact", "href": "/contact" },
|
||||
{ "label": "Login", "href": "/login" }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Metrics
|
||||
|
||||
**Development:**
|
||||
- ⏱️ Build tijd: 2.5 uur
|
||||
- 📝 Lines of code: ~2,750
|
||||
- 🧪 Build status: ✅ Success
|
||||
|
||||
**Performance:**
|
||||
- 🚀 Page load: < 100ms (static)
|
||||
- 📦 Bundle size: +12kb (MDX parser)
|
||||
- 💾 Build time: +2.2s (22 static pages)
|
||||
|
||||
**Files Added:**
|
||||
- 14 new files
|
||||
- 6 components
|
||||
- 3 utility functions
|
||||
- 2 documentation files
|
||||
- 1 template file
|
||||
|
||||
**Cost:**
|
||||
- 💰 Dependencies: €0 (open source)
|
||||
- 💰 Hosting: €0 (Vercel static)
|
||||
- 💰 Build time: €0 (within limits)
|
||||
|
||||
---
|
||||
|
||||
## Screenshots
|
||||
|
||||
### Overview Page
|
||||
*Overview pagina met status filtering (voltooid/in progress/gepland)*
|
||||
|
||||
### Sidebar Navigation
|
||||
*Thematische sidebar met collapsible groups (Foundation, Features, Infrastructure)*
|
||||
|
||||
### Detail Page
|
||||
*Release detail met MDX content rendering en custom components*
|
||||
|
||||
### Mobile View
|
||||
*Responsive horizontal scroll navigation op mobile*
|
||||
|
||||
---
|
||||
|
||||
## Related Links
|
||||
|
||||
**Documentation:**
|
||||
- [Bouwplan v1.2](/docs/specs/releasepage/bouwplan-release-notes-v1.0.md)
|
||||
- [Release Note Template](/docs/templates/release-note-template.mdx)
|
||||
|
||||
**Timeline:**
|
||||
- [Build Timeline](/#timeline) - Week overzicht
|
||||
|
||||
**External:**
|
||||
- [next-mdx-remote](https://github.com/hashicorp/next-mdx-remote)
|
||||
- [gray-matter](https://github.com/jonschlinkert/gray-matter)
|
||||
- [MDX Documentation](https://mdxjs.com/)
|
||||
|
||||
---
|
||||
|
||||
## What's Next
|
||||
|
||||
Mogelijke verbeteringen voor toekomstige versies:
|
||||
|
||||
- 🔜 RSS feed voor release notes
|
||||
- 🔜 Search functionaliteit
|
||||
- 🔜 Filters (features/fixes/improvements)
|
||||
- 🔜 Changelog syntax highlighting
|
||||
- 🔜 Email notifications bij nieuwe releases
|
||||
- 🔜 Automatic changelog generation from git commits
|
||||
- 🔜 Dark mode support
|
||||
- 🔜 Export naar PDF/Markdown
|
||||
|
||||
---
|
||||
|
||||
## Lessons Learned
|
||||
|
||||
**Wat ging goed:**
|
||||
- MDX = perfecte balans tussen eenvoud en kracht
|
||||
- Thematische indeling > chronologische indeling
|
||||
- Template systeem zorgt voor consistentie
|
||||
- Static generation = excellent performance
|
||||
|
||||
**Wat anders zou kunnen:**
|
||||
- Syntax highlighting library toevoegen (shiki/prism)
|
||||
- Table of contents auto-generation
|
||||
- Reading time estimation
|
||||
- Related releases suggestions
|
||||
|
||||
**Herbruikbaar voor andere projecten:**
|
||||
- MDX parsing utilities
|
||||
- Release sidebar component
|
||||
- Custom MDX components
|
||||
- Template structure
|
||||
342
content/nl/documentatie/webpack-module-resolution.mdx
Normal file
342
content/nl/documentatie/webpack-module-resolution.mdx
Normal file
@@ -0,0 +1,342 @@
|
||||
---
|
||||
title: "Webpack Module Resolution Fix"
|
||||
category: "webpack-module-resolution"
|
||||
group: "bugs"
|
||||
version: "0.2.1"
|
||||
releaseDate: "2024-11-19"
|
||||
status: "completed"
|
||||
description: "Fix voor 'Cannot read properties of undefined (reading call)' error bij Server/Client Component imports"
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Opgelost: Kritieke webpack module resolution error die optrad bij het laden van de release notes sidebar. De error `Cannot read properties of undefined (reading 'call')` is een bekend probleem in Next.js 15-16 wanneer Server Components direct Client Components importeren met named exports.
|
||||
|
||||
**Impact:** Complete blokkade van de documentatie pagina's totdat opgelost.
|
||||
|
||||
**Root cause:** Incompatibiliteit tussen Next.js Server/Client Component boundary en webpack's module chunking systeem.
|
||||
|
||||
---
|
||||
|
||||
## The Problem
|
||||
|
||||
### Error Details
|
||||
|
||||
```
|
||||
TypeError: Cannot read properties of undefined (reading 'call')
|
||||
at eval (webpack-internal:///356:9:118)
|
||||
at 356 (.next/dev/static/chunks/app/(marketing)/documentatie/layout.js:28:1)
|
||||
at ReleasesLayout (app/(marketing)/documentatie/layout.tsx:24:11)
|
||||
```
|
||||
|
||||
### What Was Happening
|
||||
|
||||
1. **Server Component** (`layout.tsx`) importeerde direct een **Client Component** (`release-sidebar.tsx`)
|
||||
2. De Client Component had een `'use client'` directive + named export
|
||||
3. Webpack probeerde de Client Component in een aparte chunk te bundelen
|
||||
4. Bij het laden van de webpack chunk verwachtte de loader een functie
|
||||
5. Door timing/caching issues was de export soms `undefined`
|
||||
6. Dit gaf de cryptische error: `Cannot read properties of undefined (reading 'call')`
|
||||
|
||||
### Code Structure
|
||||
|
||||
**Problematische setup:**
|
||||
|
||||
```tsx
|
||||
// layout.tsx (Server Component - async function)
|
||||
import { ReleaseSidebar } from './components/release-sidebar' // ❌ PROBLEEM
|
||||
|
||||
// release-sidebar.tsx (Client Component)
|
||||
'use client'
|
||||
export function ReleaseSidebar({ ... }) { ... } // Named export
|
||||
```
|
||||
|
||||
**Waarom dit faalt:**
|
||||
- Server Component boundary
|
||||
- Named export van Client Component
|
||||
- Webpack module federation issues
|
||||
- Fast Refresh compatibility problemen
|
||||
|
||||
---
|
||||
|
||||
## The Solution
|
||||
|
||||
### Wrapper Component Pattern
|
||||
|
||||
Maak een tussenlaag die de import isoleert en een default export gebruikt:
|
||||
|
||||
**Bestanden structuur:**
|
||||
```
|
||||
app/(marketing)/documentatie/
|
||||
├── layout.tsx # Server Component
|
||||
├── components/
|
||||
│ ├── release-sidebar.tsx # Client Component (named export)
|
||||
│ └── release-sidebar-wrapper.tsx # Wrapper (default export) ✅
|
||||
```
|
||||
|
||||
**Implementatie:**
|
||||
|
||||
```tsx
|
||||
// release-sidebar-wrapper.tsx (NIEUW)
|
||||
import { ReleaseSidebar } from './release-sidebar'
|
||||
import type { ReleaseNote, GroupMetadata, CategoryMetadata } from '@/lib/mdx/documentatie'
|
||||
|
||||
interface ReleaseSidebarWrapperProps {
|
||||
releases: ReleaseNote[]
|
||||
metadata: {
|
||||
groups: GroupMetadata[]
|
||||
categories: CategoryMetadata[]
|
||||
}
|
||||
}
|
||||
|
||||
export default function ReleaseSidebarWrapper(props: ReleaseSidebarWrapperProps) {
|
||||
return <ReleaseSidebar {...props} />
|
||||
}
|
||||
|
||||
// layout.tsx (GEWIJZIGD)
|
||||
import ReleaseSidebar from './components/release-sidebar-wrapper' // ✅ Via wrapper
|
||||
|
||||
export default async function ReleasesLayout({ children }: ReleasesLayoutProps) {
|
||||
const releases = await getAllReleases()
|
||||
const metadata = await getCategoryMetadata()
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-slate-50">
|
||||
<ReleaseSidebar releases={releases} metadata={metadata} />
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Why This Works
|
||||
|
||||
### Technical Explanation
|
||||
|
||||
1. **Default Export vs Named Export**
|
||||
- Webpack handelt default exports betrouwbaarder af bij chunking
|
||||
- Named exports kunnen leiden tot undefined module references
|
||||
- Default exports hebben duidelijkere module boundaries
|
||||
|
||||
2. **Import Chain Isolation**
|
||||
- Wrapper breekt de directe Server → Client import
|
||||
- Geeft webpack een extra laag om module resolution te doen
|
||||
- Voorkomt race conditions bij module loading
|
||||
|
||||
3. **Consistent Module Pattern**
|
||||
- Default export = consistent gedrag in webpack
|
||||
- Minder gevoelig voor HMR (Hot Module Reload) issues
|
||||
- Betere compatibiliteit met Next.js RSC (React Server Components)
|
||||
|
||||
---
|
||||
|
||||
## Prevention: Best Practices
|
||||
|
||||
### 1. Use Default Exports for Client Components
|
||||
|
||||
```tsx
|
||||
// ✅ GOED - Gebruik dit pattern
|
||||
'use client'
|
||||
export default function MyClientComponent() {
|
||||
return <div>...</div>
|
||||
}
|
||||
|
||||
// ❌ VERMIJD - Dit kan problemen geven
|
||||
'use client'
|
||||
export function MyClientComponent() {
|
||||
return <div>...</div>
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Create Wrappers for Layout Imports
|
||||
|
||||
Als je Client Components in Server Component layouts gebruikt:
|
||||
|
||||
```tsx
|
||||
// Maak altijd een wrapper met default export
|
||||
// wrapper.tsx
|
||||
import { ClientComponent } from './client-component'
|
||||
export default function ClientComponentWrapper(props) {
|
||||
return <ClientComponent {...props} />
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Split Type Imports
|
||||
|
||||
```tsx
|
||||
// ✅ GOED - Gescheiden imports
|
||||
import type { Props } from './types'
|
||||
import Component from './component'
|
||||
|
||||
// ❌ VERMIJD - Mixed imports
|
||||
import { type Props, Component } from './component'
|
||||
```
|
||||
|
||||
### 4. Clean Cache When Issues Persist
|
||||
|
||||
```bash
|
||||
# Bij persistente webpack errors
|
||||
rm -rf .next node_modules
|
||||
pnpm install
|
||||
npm run dev
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Related Issues & Context
|
||||
|
||||
### Other Potential Problem Areas
|
||||
|
||||
Deze Client Components in de codebase gebruiken ook named exports en kunnen hetzelfde probleem krijgen:
|
||||
|
||||
**High Risk** (gebruikt in layouts):
|
||||
- `app/(marketing)/components/minimal-nav.tsx`
|
||||
- `app/(marketing)/components/hero-section-client.tsx`
|
||||
- `app/epd/clients/components/*`
|
||||
|
||||
**Medium Risk:**
|
||||
- `app/(marketing)/components/reading-progress.tsx`
|
||||
- `app/(marketing)/components/marketing-shader.tsx`
|
||||
|
||||
**Action Items:**
|
||||
- Monitor deze tijdens development
|
||||
- Overweeg wrappers bij problemen
|
||||
- Langetermijn: refactor naar default exports
|
||||
|
||||
### Next.js Version Context
|
||||
|
||||
Dit is een **bekend probleem** in:
|
||||
- Next.js 15.x
|
||||
- Next.js 16.x (current: 16.0.1)
|
||||
|
||||
**Gerelateerde issues:**
|
||||
- Server/Client Component boundary bugs
|
||||
- Webpack module federation met RSC
|
||||
- Fast Refresh compatibility issues
|
||||
|
||||
---
|
||||
|
||||
## Testing Checklist
|
||||
|
||||
- [x] `/documentatie` pagina laadt zonder errors
|
||||
- [x] Sidebar toont alle groups (Foundation, Features, Infrastructure, Bugs)
|
||||
- [x] Navigatie tussen release pages werkt
|
||||
- [x] Hard refresh werkt correct
|
||||
- [x] HMR (Hot Module Reload) werkt zonder crashes
|
||||
- [x] Build succeeds (`npm run build`)
|
||||
- [x] Production build werkt correct
|
||||
|
||||
---
|
||||
|
||||
## Files Changed
|
||||
|
||||
### Modified
|
||||
1. `app/(marketing)/documentatie/layout.tsx`
|
||||
- Import via wrapper in plaats van direct
|
||||
|
||||
### Added
|
||||
2. `app/(marketing)/documentatie/components/release-sidebar-wrapper.tsx`
|
||||
- Nieuwe wrapper component met default export
|
||||
|
||||
3. `docs/troubleshooting/webpack-module-resolution-error.md`
|
||||
- Uitgebreide troubleshooting guide
|
||||
- 4 oplossingsmethoden gedocumenteerd
|
||||
- Best practices voor preventie
|
||||
|
||||
---
|
||||
|
||||
## Performance Impact
|
||||
|
||||
**Before Fix:**
|
||||
- ❌ Complete page crash
|
||||
- ❌ Geen toegang tot documentatie
|
||||
- ❌ Dev server instabiel
|
||||
|
||||
**After Fix:**
|
||||
- ✅ Stabiele page loads
|
||||
- ✅ Fast Refresh werkt correct
|
||||
- ✅ Geen performance impact (wrapper is pure passthrough)
|
||||
- ✅ Build tijd: +0.2s (verwaarloosbaar)
|
||||
- ✅ Bundle size: +0.1kb (wrapper overhead)
|
||||
|
||||
---
|
||||
|
||||
## Lessons Learned
|
||||
|
||||
### What Went Wrong
|
||||
|
||||
1. **Aanname over import compatibility**
|
||||
- Named exports werken meestal, maar niet altijd bij Server/Client boundaries
|
||||
- Next.js documentatie is niet altijd duidelijk over deze edge cases
|
||||
|
||||
2. **Webpack als black box**
|
||||
- Module resolution errors zijn cryptisch
|
||||
- `Cannot read properties of undefined` geeft weinig context
|
||||
- Debugging vereist diep begrip van webpack internals
|
||||
|
||||
3. **Cache masking issues**
|
||||
- Error verscheen/verdween door cache timing
|
||||
- Maakte root cause analyse moeilijker
|
||||
|
||||
### What Went Right
|
||||
|
||||
1. **Systematic debugging**
|
||||
- Eliminatie van mogelijke oorzaken
|
||||
- Type imports gecheckt
|
||||
- MDX dependencies geverifieerd
|
||||
- Webpack output geanalyseerd
|
||||
|
||||
2. **Pattern recognition**
|
||||
- Error type wijst naar module loading issues
|
||||
- Server/Client boundary is known problem area
|
||||
- Default vs named export patterns bekend
|
||||
|
||||
3. **Documentation**
|
||||
- Volledige troubleshooting guide gemaakt
|
||||
- Best practices gedocumenteerd
|
||||
- Toekomstige problemen sneller op te lossen
|
||||
|
||||
---
|
||||
|
||||
## Quick Reference
|
||||
|
||||
| Symptom | Likely Cause | Solution |
|
||||
|---------|--------------|----------|
|
||||
| `undefined reading 'call'` | Named export Client in Server | Use wrapper or default export |
|
||||
| Intermittent/disappears on refresh | Webpack cache | Clear .next, restart |
|
||||
| Only in production build | SSR/hydration mismatch | Check dynamic imports |
|
||||
| After HMR (file save) | Fast Refresh issue | Full reload or restart dev |
|
||||
|
||||
---
|
||||
|
||||
## Additional Resources
|
||||
|
||||
**Internal Documentation:**
|
||||
- [Troubleshooting Guide](/docs/troubleshooting/webpack-module-resolution-error.md)
|
||||
- [Release Notes System Docs](/documentatie/release-notes-system)
|
||||
|
||||
**External Links:**
|
||||
- [Next.js Server Components](https://nextjs.org/docs/app/building-your-application/rendering/server-components)
|
||||
- [React Server Components](https://react.dev/reference/rsc/server-components)
|
||||
- [Webpack Module Federation](https://webpack.js.org/concepts/module-federation/)
|
||||
|
||||
---
|
||||
|
||||
## What's Next
|
||||
|
||||
**Monitoring:**
|
||||
- Watch andere Client Components voor zelfde issue
|
||||
- Log webpack errors systematisch
|
||||
- Track Next.js updates voor fixes
|
||||
|
||||
**Improvements:**
|
||||
- Refactor high-risk components naar default exports
|
||||
- Create ESLint rule om named exports in Client Components te detecteren
|
||||
- Add automated tests voor Server/Client boundary issues
|
||||
|
||||
**Future Prevention:**
|
||||
- Template voor nieuwe Client Components met default export
|
||||
- Code review checklist voor Server/Client imports
|
||||
- Documentation voor team over dit pattern
|
||||
Reference in New Issue
Block a user