Content loader utility, Content directory structuur

This commit is contained in:
colinislit
2025-11-15 22:06:48 +01:00
parent dbde412465
commit 690e7b7c43
37 changed files with 9447 additions and 1035 deletions

1
.gitignore vendored
View File

@@ -32,6 +32,7 @@ yarn-error.log*
# env files (can opt-in for committing if needed)
.env*
!.env.example
# vercel
.vercel

View File

@@ -1,4 +1,6 @@
@import "tailwindcss";
@tailwind base;
@tailwind components;
@tailwind utilities;
/* =============================================================================
Mini-ECD Design System
@@ -76,47 +78,83 @@
/* Fonts */
--font-sans: var(--font-geist-sans);
--font-mono: var(--font-geist-mono);
}
@theme inline {
/* Basiskleuren */
--color-bg: var(--color-bg);
--color-surface: var(--color-surface);
--color-text: var(--color-text);
--color-border: var(--color-border);
/* Brand */
--color-brand: var(--color-brand);
--color-success: var(--color-success);
--color-warning: var(--color-warning);
--color-error: var(--color-error);
--color-info: var(--color-info);
/* Shadows */
--shadow-sm: var(--shadow-sm);
--shadow-md: var(--shadow-md);
--shadow-lg: var(--shadow-lg);
/* Fonts */
--font-sans: var(--font-sans);
--font-mono: var(--font-mono);
--radius: 0.625rem;
--background: oklch(1 0 0);
--foreground: oklch(0.129 0.042 264.695);
--card: oklch(1 0 0);
--card-foreground: oklch(0.129 0.042 264.695);
--popover: oklch(1 0 0);
--popover-foreground: oklch(0.129 0.042 264.695);
--primary: oklch(0.208 0.042 265.755);
--primary-foreground: oklch(0.984 0.003 247.858);
--secondary: oklch(0.968 0.007 247.896);
--secondary-foreground: oklch(0.208 0.042 265.755);
--muted: oklch(0.968 0.007 247.896);
--muted-foreground: oklch(0.554 0.046 257.417);
--accent: oklch(0.968 0.007 247.896);
--accent-foreground: oklch(0.208 0.042 265.755);
--destructive: oklch(0.577 0.245 27.325);
--border: oklch(0.929 0.013 255.508);
--input: oklch(0.929 0.013 255.508);
--ring: oklch(0.704 0.04 256.788);
--chart-1: oklch(0.646 0.222 41.116);
--chart-2: oklch(0.6 0.118 184.704);
--chart-3: oklch(0.398 0.07 227.392);
--chart-4: oklch(0.828 0.189 84.429);
--chart-5: oklch(0.769 0.188 70.08);
--sidebar: oklch(0.984 0.003 247.858);
--sidebar-foreground: oklch(0.129 0.042 264.695);
--sidebar-primary: oklch(0.208 0.042 265.755);
--sidebar-primary-foreground: oklch(0.984 0.003 247.858);
--sidebar-accent: oklch(0.968 0.007 247.896);
--sidebar-accent-foreground: oklch(0.208 0.042 265.755);
--sidebar-border: oklch(0.929 0.013 255.508);
--sidebar-ring: oklch(0.704 0.04 256.788);
}
/* Dark mode (optioneel, MVP gebruikt licht thema) */
@media (prefers-color-scheme: dark) {
:root {
.dark {
--color-bg: #0a0a0a;
--color-surface: #1a1a1a;
--color-text: #ededed;
--color-text-secondary: #a1a1a1;
--color-border: #333333;
}
--background: oklch(0.129 0.042 264.695);
--foreground: oklch(0.984 0.003 247.858);
--card: oklch(0.208 0.042 265.755);
--card-foreground: oklch(0.984 0.003 247.858);
--popover: oklch(0.208 0.042 265.755);
--popover-foreground: oklch(0.984 0.003 247.858);
--primary: oklch(0.929 0.013 255.508);
--primary-foreground: oklch(0.208 0.042 265.755);
--secondary: oklch(0.279 0.041 260.031);
--secondary-foreground: oklch(0.984 0.003 247.858);
--muted: oklch(0.279 0.041 260.031);
--muted-foreground: oklch(0.704 0.04 256.788);
--accent: oklch(0.279 0.041 260.031);
--accent-foreground: oklch(0.984 0.003 247.858);
--destructive: oklch(0.704 0.191 22.216);
--border: oklch(1 0 0 / 10%);
--input: oklch(1 0 0 / 15%);
--ring: oklch(0.551 0.027 264.364);
--chart-1: oklch(0.488 0.243 264.376);
--chart-2: oklch(0.696 0.17 162.48);
--chart-3: oklch(0.769 0.188 70.08);
--chart-4: oklch(0.627 0.265 303.9);
--chart-5: oklch(0.645 0.246 16.439);
--sidebar: oklch(0.208 0.042 265.755);
--sidebar-foreground: oklch(0.984 0.003 247.858);
--sidebar-primary: oklch(0.488 0.243 264.376);
--sidebar-primary-foreground: oklch(0.984 0.003 247.858);
--sidebar-accent: oklch(0.279 0.041 260.031);
--sidebar-accent-foreground: oklch(0.984 0.003 247.858);
--sidebar-border: oklch(1 0 0 / 10%);
--sidebar-ring: oklch(0.551 0.027 264.364);
}
/* Global styles */
body {
background: var(--color-bg);
color: var(--color-text);
font-family: var(--font-sans), system-ui, -apple-system, sans-serif;
}
@@ -132,3 +170,12 @@ body {
border-radius: 2px;
padding: 1px 0;
}
@layer base {
* {
@apply border-border;
}
body {
@apply bg-background text-foreground antialiased;
}
}

248
app/globals.css.backup Normal file
View File

@@ -0,0 +1,248 @@
@import "tailwindcss";
@plugin "tailwindcss-animate";
@import "tw-animate-css";
@custom-variant dark (&:is(.dark *));
/* =============================================================================
Mini-ECD Design System
Gebaseerd op ux-stylesheet.md (v2, UX-geoptimaliseerd)
============================================================================= */
:root {
/* Basiskleuren */
--color-bg: #F8FAFC;
--color-surface: #FFFFFF;
--color-surface-secondary: #F1F5F9;
--color-text: #0F172A;
--color-text-secondary: #475569;
--color-border: #E2E8F0;
/* Brand & Primary */
--color-brand: #3B82F6;
--color-brand-hover: #2563EB;
--color-brand-active: #1D4ED8;
--color-brand-subtle: #EFF6FF;
/* Neutral CTA */
--color-neutral: #334155;
--color-neutral-hover: #1F2937;
/* Module-accenten */
--color-module-appointments: #16A34A;
--color-module-appointments-bg: #E8F8EF;
--color-module-appointments-border: #CDECDC;
--color-module-meds: #F59E0B;
--color-module-meds-bg: #FEF6DC;
--color-module-meds-border: #F6E7B6;
--color-module-labs: #F97316;
--color-module-labs-bg: #FFEBDC;
--color-module-labs-border: #FFD2B8;
/* Status & Feedback */
--color-success: #16A34A;
--color-success-subtle: #ECFDF5;
--color-warning: #EAB308;
--color-warning-subtle: #FEFCE8;
--color-error: #DC2626;
--color-error-subtle: #FEF2F2;
--color-info: #3B82F6;
--color-info-subtle: #EFF6FF;
/* Badges (Severity DSM-light) */
--color-badge-low-bg: #E5E7EB;
--color-badge-low-text: #374151;
--color-badge-medium-bg: #FEF3C7;
--color-badge-medium-text: #92400E;
--color-badge-high-bg: #FEE2E2;
--color-badge-high-text: #991B1B;
/* Formulieren */
--color-input-bg: #FFFFFF;
--color-input-text: #0F172A;
--color-input-placeholder: #94A3B8;
--color-input-border: #CBD5E1;
--color-input-border-hover: #94A3B8;
--color-input-focus: #3B82F6;
--color-input-focus-border: #2563EB;
--color-input-disabled-bg: #F1F5F9;
--color-input-disabled-text: #94A3B8;
--color-input-invalid-border: #DC2626;
--color-input-invalid-text: #B91C1C;
/* Shadows */
--shadow-sm: 0 1px 2px rgba(15, 23, 42, 0.06);
--shadow-md: 0 2px 6px rgba(15, 23, 42, 0.08);
--shadow-lg: 0 8px 20px rgba(15, 23, 42, 0.10);
/* Fonts */
--font-sans: var(--font-geist-sans);
--font-mono: var(--font-geist-mono);
--radius: 0.625rem;
--background: oklch(1 0 0);
--foreground: oklch(0.129 0.042 264.695);
--card: oklch(1 0 0);
--card-foreground: oklch(0.129 0.042 264.695);
--popover: oklch(1 0 0);
--popover-foreground: oklch(0.129 0.042 264.695);
--primary: oklch(0.208 0.042 265.755);
--primary-foreground: oklch(0.984 0.003 247.858);
--secondary: oklch(0.968 0.007 247.896);
--secondary-foreground: oklch(0.208 0.042 265.755);
--muted: oklch(0.968 0.007 247.896);
--muted-foreground: oklch(0.554 0.046 257.417);
--accent: oklch(0.968 0.007 247.896);
--accent-foreground: oklch(0.208 0.042 265.755);
--destructive: oklch(0.577 0.245 27.325);
--border: oklch(0.929 0.013 255.508);
--input: oklch(0.929 0.013 255.508);
--ring: oklch(0.704 0.04 256.788);
--chart-1: oklch(0.646 0.222 41.116);
--chart-2: oklch(0.6 0.118 184.704);
--chart-3: oklch(0.398 0.07 227.392);
--chart-4: oklch(0.828 0.189 84.429);
--chart-5: oklch(0.769 0.188 70.08);
--sidebar: oklch(0.984 0.003 247.858);
--sidebar-foreground: oklch(0.129 0.042 264.695);
--sidebar-primary: oklch(0.208 0.042 265.755);
--sidebar-primary-foreground: oklch(0.984 0.003 247.858);
--sidebar-accent: oklch(0.968 0.007 247.896);
--sidebar-accent-foreground: oklch(0.208 0.042 265.755);
--sidebar-border: oklch(0.929 0.013 255.508);
--sidebar-ring: oklch(0.704 0.04 256.788);
}
@theme inline {
/* Basiskleuren */
--color-bg: var(--color-bg);
--color-surface: var(--color-surface);
--color-text: var(--color-text);
--color-border: var(--color-border);
/* Brand */
--color-brand: var(--color-brand);
--color-success: var(--color-success);
--color-warning: var(--color-warning);
--color-error: var(--color-error);
--color-info: var(--color-info);
/* Shadows */
--shadow-sm: var(--shadow-sm);
--shadow-md: var(--shadow-md);
--shadow-lg: var(--shadow-lg);
/* Fonts */
--font-sans: var(--font-sans);
--font-mono: var(--font-mono);
--color-sidebar-ring: var(--sidebar-ring);
--color-sidebar-border: var(--sidebar-border);
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
--color-sidebar-accent: var(--sidebar-accent);
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
--color-sidebar-primary: var(--sidebar-primary);
--color-sidebar-foreground: var(--sidebar-foreground);
--color-sidebar: var(--sidebar);
--color-chart-5: var(--chart-5);
--color-chart-4: var(--chart-4);
--color-chart-3: var(--chart-3);
--color-chart-2: var(--chart-2);
--color-chart-1: var(--chart-1);
--color-ring: var(--ring);
--color-input: var(--input);
--color-destructive: var(--destructive);
--color-accent-foreground: var(--accent-foreground);
--color-accent: var(--accent);
--color-muted-foreground: var(--muted-foreground);
--color-muted: var(--muted);
--color-secondary-foreground: var(--secondary-foreground);
--color-secondary: var(--secondary);
--color-primary-foreground: var(--primary-foreground);
--color-primary: var(--primary);
--color-popover-foreground: var(--popover-foreground);
--color-popover: var(--popover);
--color-card-foreground: var(--card-foreground);
--color-card: var(--card);
--color-foreground: var(--foreground);
--color-background: var(--background);
--radius-sm: calc(var(--radius) - 4px);
--radius-md: calc(var(--radius) - 2px);
--radius-lg: var(--radius);
--radius-xl: calc(var(--radius) + 4px);
}
/* Dark mode (optioneel, MVP gebruikt licht thema) */
@media (prefers-color-scheme: dark) {
:root {
--color-bg: #0a0a0a;
--color-surface: #1a1a1a;
--color-text: #ededed;
--color-text-secondary: #a1a1a1;
--color-border: #333333;
}
}
/* Global styles */
body {
background: var(--color-bg);
color: var(--color-text);
font-family: var(--font-sans), system-ui, -apple-system, sans-serif;
}
/* Focus styles (toegankelijkheid) */
*:focus-visible {
outline: 2px solid var(--color-brand);
outline-offset: 2px;
}
/* AI source highlighting (gebruikt in Intake editor) */
.ai-source-highlight {
background-color: #fef08a; /* lichtgeel */
border-radius: 2px;
padding: 1px 0;
}
.dark {
--background: oklch(0.129 0.042 264.695);
--foreground: oklch(0.984 0.003 247.858);
--card: oklch(0.208 0.042 265.755);
--card-foreground: oklch(0.984 0.003 247.858);
--popover: oklch(0.208 0.042 265.755);
--popover-foreground: oklch(0.984 0.003 247.858);
--primary: oklch(0.929 0.013 255.508);
--primary-foreground: oklch(0.208 0.042 265.755);
--secondary: oklch(0.279 0.041 260.031);
--secondary-foreground: oklch(0.984 0.003 247.858);
--muted: oklch(0.279 0.041 260.031);
--muted-foreground: oklch(0.704 0.04 256.788);
--accent: oklch(0.279 0.041 260.031);
--accent-foreground: oklch(0.984 0.003 247.858);
--destructive: oklch(0.704 0.191 22.216);
--border: oklch(1 0 0 / 10%);
--input: oklch(1 0 0 / 15%);
--ring: oklch(0.551 0.027 264.364);
--chart-1: oklch(0.488 0.243 264.376);
--chart-2: oklch(0.696 0.17 162.48);
--chart-3: oklch(0.769 0.188 70.08);
--chart-4: oklch(0.627 0.265 303.9);
--chart-5: oklch(0.645 0.246 16.439);
--sidebar: oklch(0.208 0.042 265.755);
--sidebar-foreground: oklch(0.984 0.003 247.858);
--sidebar-primary: oklch(0.488 0.243 264.376);
--sidebar-primary-foreground: oklch(0.984 0.003 247.858);
--sidebar-accent: oklch(0.279 0.041 260.031);
--sidebar-accent-foreground: oklch(0.984 0.003 247.858);
--sidebar-border: oklch(1 0 0 / 10%);
--sidebar-ring: oklch(0.551 0.027 264.364);
}
@layer base {
* {
@apply border-border outline-ring/50;
}
body {
@apply bg-background text-foreground;
}
}

22
components.json Normal file
View File

@@ -0,0 +1,22 @@
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "new-york",
"rsc": true,
"tsx": true,
"tailwind": {
"config": "tailwind.config.ts",
"css": "app/globals.css",
"baseColor": "slate",
"cssVariables": true,
"prefix": ""
},
"iconLibrary": "lucide",
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/ui",
"lib": "@/lib",
"hooks": "@/hooks"
},
"registries": {}
}

View File

@@ -0,0 +1,191 @@
'use client'
import { useMemo, useEffect } from 'react'
import { Canvas, ThreeEvent, useFrame, useThree } from '@react-three/fiber'
import { shaderMaterial, useTrailTexture } from '@react-three/drei'
import { useTheme } from 'next-themes' // lub twój provider
import * as THREE from 'three'
const DotMaterial = shaderMaterial(
{
time: 0,
resolution: new THREE.Vector2(),
dotColor: new THREE.Color('#FFFFFF'),
bgColor: new THREE.Color('#121212'),
mouseTrail: null,
render: 0,
rotation: 0,
gridSize: 50,
dotOpacity: 0.05
},
/* glsl */ `
void main() {
gl_Position = vec4(position.xy, 0.0, 1.0);
}
`,
/* glsl */ `
uniform float time;
uniform int render;
uniform vec2 resolution;
uniform vec3 dotColor;
uniform vec3 bgColor;
uniform sampler2D mouseTrail;
uniform float rotation;
uniform float gridSize;
uniform float dotOpacity;
vec2 rotate(vec2 uv, float angle) {
float s = sin(angle);
float c = cos(angle);
mat2 rotationMatrix = mat2(c, -s, s, c);
return rotationMatrix * (uv - 0.5) + 0.5;
}
vec2 coverUv(vec2 uv) {
vec2 s = resolution.xy / max(resolution.x, resolution.y);
vec2 newUv = (uv - 0.5) * s + 0.5;
return clamp(newUv, 0.0, 1.0);
}
float sdfCircle(vec2 p, float r) {
return length(p - 0.5) - r;
}
void main() {
vec2 screenUv = gl_FragCoord.xy / resolution;
vec2 uv = coverUv(screenUv);
vec2 rotatedUv = rotate(uv, rotation);
// Create a grid
vec2 gridUv = fract(rotatedUv * gridSize);
vec2 gridUvCenterInScreenCoords = rotate((floor(rotatedUv * gridSize) + 0.5) / gridSize, -rotation);
// Calculate distance from the center of each cell
float baseDot = sdfCircle(gridUv, 0.25);
// Screen mask
float screenMask = smoothstep(0.0, 1.0, 1.0 - uv.y); // 0 at the top, 1 at the bottom
vec2 centerDisplace = vec2(0.7, 1.1);
float circleMaskCenter = length(uv - centerDisplace);
float circleMaskFromCenter = smoothstep(0.5, 1.0, circleMaskCenter);
float combinedMask = screenMask * circleMaskFromCenter;
float circleAnimatedMask = sin(time * 2.0 + circleMaskCenter * 10.0);
// Mouse trail effect
float mouseInfluence = texture2D(mouseTrail, gridUvCenterInScreenCoords).r;
float scaleInfluence = max(mouseInfluence * 0.5, circleAnimatedMask * 0.3);
// Create dots with animated scale, influenced by mouse
float dotSize = min(pow(circleMaskCenter, 2.0) * 0.3, 0.3);
float sdfDot = sdfCircle(gridUv, dotSize * (1.0 + scaleInfluence * 0.5));
float smoothDot = smoothstep(0.05, 0.0, sdfDot);
float opacityInfluence = max(mouseInfluence * 50.0, circleAnimatedMask * 0.5);
// Mix background color with dot color, using animated opacity to increase visibility
vec3 composition = mix(bgColor, dotColor, smoothDot * combinedMask * dotOpacity * (1.0 + opacityInfluence));
gl_FragColor = vec4(composition, 1.0);
#include <tonemapping_fragment>
#include <colorspace_fragment>
}
`
)
function Scene() {
const size = useThree((s) => s.size)
const viewport = useThree((s) => s.viewport)
const { theme } = useTheme()
const rotation = 0
const gridSize = 100
const getThemeColors = () => {
switch (theme) {
case 'dark':
return {
dotColor: '#FFFFFF',
bgColor: '#121212',
dotOpacity: 0.025
}
case 'light':
return {
dotColor: '#e1e1e1',
bgColor: '#F4F5F5',
dotOpacity: 0.15
}
default:
return {
dotColor: '#FFFFFF',
bgColor: '#121212',
dotOpacity: 0.05
}
}
}
const themeColors = getThemeColors()
const [trail, onMove] = useTrailTexture({
size: 512,
radius: 0.1,
maxAge: 400,
interpolate: 1,
ease: function easeInOutCirc(x) {
return x < 0.5 ? (1 - Math.sqrt(1 - Math.pow(2 * x, 2))) / 2 : (Math.sqrt(1 - Math.pow(-2 * x + 2, 2)) + 1) / 2
}
})
const dotMaterial = useMemo(() => {
return new DotMaterial()
}, [])
useEffect(() => {
dotMaterial.uniforms.dotColor.value.setHex(themeColors.dotColor.replace('#', '0x'))
dotMaterial.uniforms.bgColor.value.setHex(themeColors.bgColor.replace('#', '0x'))
dotMaterial.uniforms.dotOpacity.value = themeColors.dotOpacity
}, [theme, dotMaterial, themeColors])
useFrame((state) => {
dotMaterial.uniforms.time.value = state.clock.elapsedTime
})
const handlePointerMove = (e: ThreeEvent<PointerEvent>) => {
onMove(e)
}
const scale = Math.max(viewport.width, viewport.height) / 2
return (
<mesh scale={[scale, scale, 1]} onPointerMove={handlePointerMove}>
<planeGeometry args={[2, 2]} />
<primitive
object={dotMaterial}
resolution={[size.width * viewport.dpr, size.height * viewport.dpr]}
rotation={rotation}
gridSize={gridSize}
mouseTrail={trail}
render={0}
/>
</mesh>
)
}
export const DotScreenShader = () => {
return (
<Canvas
gl={{
antialias: true,
powerPreference: 'high-performance',
outputColorSpace: THREE.SRGBColorSpace,
toneMapping: THREE.NoToneMapping
}}>
<Scene />
</Canvas>
)
}

15
content/nl/common.json Normal file
View File

@@ -0,0 +1,15 @@
{
"buttons": {
"readMore": "Lees verder",
"scrollDown": "Scroll naar beneden",
"followProgress": "Volg de voortgang",
"viewDemo": "Bekijk Demo",
"contact": "Contact"
},
"labels": {
"readingTime": "minuten lezen",
"lastUpdated": "Laatst bijgewerkt",
"share": "Deel"
}
}

105
content/nl/manifesto.json Normal file
View File

@@ -0,0 +1,105 @@
{
"hero": {
"quote": "Software is eating the world, but AI is going to eat software",
"attribution": "Jensen Huang, CEO van Nvidia",
"attributionContext": "zei dit tijdens zijn keynote op GTC in maart 2024",
"subtitle": "Nu, in 2025, zien we het gebeuren. En bijna niemand heeft het door."
},
"sections": [
{
"id": "opening",
"type": "paragraph",
"content": "Het traditionele SaaS-model is simpel: één gebruiker = één licentie. Logisch in een wereld waar elke gebruiker ongeveer evenveel waarde uit software haalt. Maar ook beperkend - je groei is gekoppeld aan het aantal medewerkers bij je klant. Dit model heeft de software-industrie 20 jaar gedomineerd. Vendors optimaliseren voor meer seats, meer modules, meer lock-in. Klanten betalen voor potentieel, niet voor werkelijke waarde."
},
{
"id": "problem",
"type": "paragraph",
"content": "Maar er gebeurt iets fundamenteels. AI maakt het mogelijk om software te genereren in plaats van te configureren. Niet meer kiezen uit wat bestaat, maar bouwen wat je nodig hebt. McKinsey noemt het \"Software on Demand\" - adaptieve diensten die via natuurlijke taal ontstaan. De implicaties zijn enorm."
},
{
"id": "mckinsey-insight",
"type": "insight",
"content": "McKinsey noemt het \"Software on Demand\" - adaptieve diensten die via natuurlijke taal ontstaan."
},
{
"id": "solution",
"type": "paragraph",
"content": "Waar traditionele implementaties 6-12 maanden duren, bouw je met AI een werkende applicatie in 4 weken. Niet omdat AI magisch is, maar omdat je 80% van de standaard-code niet meer hoeft te schrijven. De kostenbasis verschuift compleet - van €100k per jaar naar €50 per maand. Geen armies van consultants. Geen jarenlange developmenttrajecten. Infrastructuur die schaalt met gebruik. AI die de heavy lifting doet. En het belangrijkste: je bezit de code. Je controleert de roadmap. Aanpassing nodig? Dagen, geen kwartalen."
},
{
"id": "proof-numbers",
"type": "insight",
"content": "Van €100k per jaar naar €50 per maand. Geen armies van consultants. Geen jarenlange developmenttrajecten."
},
{
"id": "reality",
"type": "paragraph",
"content": "Dit is geen toekomstmuziek. Ik zie het nu al gebeuren - startups die complete workflows bouwen in de tijd dat enterprises nog aan het onderhandelen zijn over licenties. De vraag is niet óf dit de norm wordt, maar wanneer."
},
{
"id": "impact-vendors",
"type": "statement",
"variant": "dark",
"heading": "Voor software vendors is dit existentieel",
"content": "Hun hele businessmodel - recurring revenue op basis van seats - verdampt als klanten hun eigen oplossingen kunnen bouwen. Voor enterprises opent dit ongekende mogelijkheden. Software die past bij hoe je werkt, niet andersom. Innovatie in weken, niet jaren."
},
{
"id": "shift",
"type": "paragraph",
"content": "We staan nog aan het begin van deze shift. De grote vraag wordt: wie durft eerst? Wie accepteert dat de SAP-implementatie van 5 jaar geleden misschien wel de laatste traditionele software-aankoop was?"
},
{
"id": "experiment",
"type": "paragraph",
"content": "Tijd voor een experiment. Ik ga live bouwen hoe ver je komt met moderne AI-tools. Een EPD als testcase - daar ligt mijn ervaring, daar ken ik de pijn. Van niets naar een werkende applicatie in 4 weken, voor de maandelijkse kosten van één SaaS-licentie."
},
{
"id": "closing",
"type": "paragraph",
"content": "De AI Speedrun. Volg de voortgang. Doe suggesties. Kijk mee hoe het nieuwe development er in de praktijk uitziet. Want de beste manier om de toekomst te voorspellen, is hem bouwen."
}
],
"comparison": {
"heading": "Traditioneel vs AI Speedrun",
"items": [
{
"label": "Tijd",
"traditional": "6-12 maanden",
"aiSpeedrun": "4 weken"
},
{
"label": "Kosten",
"traditional": "€100k+ per jaar",
"aiSpeedrun": "€50 per maand"
},
{
"label": "Setup",
"traditional": "€50k consultants",
"aiSpeedrun": "€200 build cost"
},
{
"label": "Aanpassingen",
"traditional": "18 maanden",
"aiSpeedrun": "Dagen"
},
{
"label": "Code ownership",
"traditional": "Vendor lock-in",
"aiSpeedrun": "Jouw code"
}
]
},
"cta": {
"heading": "Tijd voor een experiment",
"subheading": "Bouw hem gewoon zelf. In 4 weken.",
"primaryButton": {
"text": "Volg de voortgang",
"href": "/build-log"
},
"secondaryButton": {
"text": "Bekijk Demo",
"href": "/demo"
}
}
}

11
content/nl/metadata.json Normal file
View File

@@ -0,0 +1,11 @@
{
"manifesto": {
"title": "Software on Demand - AI Speedrun Manifesto",
"description": "Jensen Huang: 'AI is going to eat software'. Een experiment: bouw een EPD in 4 weken voor €200.",
"ogTitle": "Software on Demand - AI Speedrun",
"ogDescription": "Van €100k en 12 maanden naar €200 en 4 weken. Het nieuwe development.",
"ogImage": "/og-manifesto.png",
"keywords": ["AI", "Software on Demand", "EPD", "Development", "Build in Public"]
}
}

View File

@@ -0,0 +1,14 @@
{
"logo": "AI SPEEDRUN",
"links": [
{
"label": "Build Log",
"href": "/build-log"
},
{
"label": "Demo",
"href": "/demo"
}
]
}

View File

@@ -0,0 +1,64 @@
export interface HeroContent {
quote: string
attribution: string
attributionContext?: string
subtitle: string
}
export type SectionType = 'paragraph' | 'insight' | 'statement'
export interface ParagraphSection {
id: string
type: 'paragraph'
content: string
}
export interface InsightSection {
id: string
type: 'insight'
content: string
}
export interface StatementSection {
id: string
type: 'statement'
variant?: 'dark' | 'light'
heading: string
content: string
}
export type ManifestoSection =
| ParagraphSection
| InsightSection
| StatementSection
export interface ComparisonItem {
label: string
traditional: string
aiSpeedrun: string
}
export interface ComparisonContent {
heading: string
items: ComparisonItem[]
}
export interface CTAButton {
text: string
href: string
}
export interface CTAContent {
heading: string
subheading?: string
primaryButton: CTAButton
secondaryButton: CTAButton
}
export interface ManifestoContent {
hero: HeroContent
sections: ManifestoSection[]
comparison: ComparisonContent
cta: CTAContent
}

View File

@@ -0,0 +1,214 @@
# 🎨 Design Review: Dot Shader Background Component
**Datum:** 15-11-2024
**Review Team:** Design & UX
**Vraag:** Kan het dot-shader-background component gebruikt worden voor marketingpagina en/of EPD app?
---
## 📋 Context Analyse
### Manifesto Kernwaarden
- **Innovatie & Disruptie:** "AI gaat software eten" - technologische vooruitgang centraal
- **Snelheid:** "4 weken vs 12 maanden" - efficiency en moderniteit
- **Bewijs door doen:** "Beste manier om toekomst te voorspellen is hem bouwen"
- **Digitale transformatie:** Software on Demand als nieuwe realiteit
### UX Stylesheet Principes
- **Lage cognitieve belasting:** Focus op content, niet op decoratie
- **Toegankelijkheid:** WCAG AA contrast, geen afleidende elementen
- **"Less is more":** Accentpalet bewust klein gehouden → minder visuele ruis
- **Functioneel design:** Elke visuele keuze moet doel dienen
### Shader Component Eigenschappen
- **Technisch:** Three.js shader met WebGL rendering
- **Visueel:** Geanimeerde dots met mouse trail interactie
- **Performance:** High-performance mode, GPU-accelerated
- **Theme support:** Dark/light mode compatible
- **Subtiel:** Lage opacity (0.025-0.15), niet dominant
---
## 🎯 Design Team Advies
### ✅ **AANBEVELING: Strategische Inzet**
Het design team adviseert **gecontroleerd gebruik** van het shader component, met duidelijke context-specifieke richtlijnen:
---
## 📍 Marketing Website: **JA, met voorwaarden**
### Waarom het werkt:
1. **Manifesto alignment:** Het component straalt technologische innovatie uit - perfect voor "Software on Demand" messaging
2. **Differentiatie:** Visueel onderscheidend van traditionele SaaS-landing pages
3. **Engagement:** Mouse trail interactie verhoogt tijd op pagina
4. **Credibility:** Toont technische vaardigheid zonder te overdrijven
### Implementatie Richtlijnen:
**Hero Section (Primaire Inzet)**
- ✅ Shader als full-screen achtergrond achter hero content
- ✅ Zeer lage opacity (0.02-0.05) - subtiel, niet dominant
- ✅ Content overlay met sterke contrast (wit op donker, of donker op licht)
- ✅ Performance: Lazy load alleen wanneer hero in viewport
**Secties (Secundaire Inzet)**
- ⚠️ Optioneel in "How it Works" of "Technology" secties
- ❌ NIET in comparison tables, ROI calculator, of formulier secties
- ❌ NIET op mobile (performance + UX overwegingen)
**Technische Aanpassingen Nodig:**
```typescript
// Marketing-specifieke configuratie
const marketingConfig = {
dotOpacity: 0.03, // Zeer subtiel
gridSize: 80, // Fijner grid voor eleganter effect
disableMouseTrail: false, // Interactiviteit behouden
performanceMode: 'high', // GPU optimization
mobileFallback: 'gradient' // Fallback voor mobile
}
```
**Contrast Check:**
- Tekst op shader achtergrond moet voldoen aan WCAG AA (4.5:1)
- Gebruik semi-transparante overlay indien nodig
- Test met verschillende tekstgroottes
---
## 🏥 EPD App: **NEE, tenzij zeer subtiel**
### Waarom het risicovol is:
1. **Cognitieve belasting:** Medische professionals hebben focus nodig - animaties zijn afleidend
2. **UX Stylesheet conflict:** Direct tegenstrijdig met "lage cognitieve belasting" principe
3. **Toegankelijkheid:** Kan problemen veroorzaken voor gebruikers met motion sensitivity
4. **Performance:** Elke milliseconde telt in productie-omgevingen
### Uitzondering: Onboarding/Welcome Screen
-**Alleen** op eerste login/welcome screen
- ✅ Zeer korte duur (3-5 seconden), dan fade-out
- ✅ Optioneel: "Skip animation" knop voor toegankelijkheid
-**NOOIT** tijdens actieve workflows (intake, profiel, behandelplan)
**Implementatie Als Uitzondering:**
```typescript
// EPD-specifieke configuratie (alleen welcome)
const epdWelcomeConfig = {
dotOpacity: 0.01, // Extreem subtiel
gridSize: 120, // Zeer fijn grid
disableMouseTrail: true, // Geen interactiviteit
autoFadeOut: true, // Fade na 3 seconden
skipButton: true, // Toegankelijkheid
reducedMotion: true // Respecteer prefers-reduced-motion
}
```
---
## 🎨 Stylesheet Matching Analyse
### Kleuren Compatibiliteit
**Light Theme Match:**
- ✅ Shader bg: `#F4F5F5` matcht stylesheet `#F8FAFC` (zeer dichtbij)
- ✅ Shader dots: `#e1e1e1` matcht border kleur `#E2E8F0` (harmonisch)
- ⚠️ Aanpassing nodig: Shader moet exact `#F8FAFC` gebruiken voor consistency
**Dark Theme Match:**
- ✅ Shader bg: `#121212` is acceptabel voor dark mode
- ✅ Shader dots: `#FFFFFF` met lage opacity werkt goed
- ⚠️ Stylesheet heeft geen dark mode spec gedefinieerd - dit moet eerst worden uitgewerkt
**Aanbevolen Aanpassingen:**
```typescript
// Update shader theme colors om exact te matchen
const getThemeColors = () => {
switch (theme) {
case 'light':
return {
dotColor: '#E2E8F0', // Match border color
bgColor: '#F8FAFC', // Match app background
dotOpacity: 0.03 // Zeer subtiel voor marketing
}
case 'dark':
return {
dotColor: '#475569', // Match secondary text
bgColor: '#0F172A', // Match primary text (inverted)
dotOpacity: 0.02 // Nog subtieler voor dark
}
}
}
```
---
## ⚖️ "Less is More" vs "Digital Innovation"
### Design Team Consensus:
**Marketing Website:**
- **"Less is more"** geldt voor **content en copy** - niet voor visuele impact
- Shader component kan **strategisch** gebruikt worden om innovatie te communiceren
- **Voorwaarde:** Het moet de boodschap versterken, niet afleiden
- **Test:** A/B test met en zonder shader - meet engagement metrics
**EPD App:**
- **"Less is more"** is hier **absoluut** - elke pixel moet functioneel zijn
- Shader component is **decoratief** en voegt geen functionele waarde toe
- **Uitzondering:** Welcome screen kan één keer indruk maken, daarna weg
---
## 📊 Risico Analyse
| Risico | Kans | Impact | Mitigatie |
|--------|------|--------|-----------|
| **Performance impact** | Medium | Hoog | Lazy loading, mobile fallback, performance monitoring |
| **Toegankelijkheid issues** | Medium | Hoog | `prefers-reduced-motion` respecteren, skip optie |
| **Cognitieve overload** | Hoog | Medium | Zeer lage opacity, alleen hero section |
| **Stylesheet mismatch** | Laag | Laag | Kleuren aanpassen naar exacte stylesheet waarden |
| **Mobile performance** | Hoog | Medium | Automatische fallback naar gradient |
---
## ✅ Finale Aanbeveling
### Marketing Website: **GO** ✅
- Implementeer in hero section met zeer lage opacity
- Pas kleuren aan naar exacte stylesheet waarden
- Voeg mobile fallback toe
- Monitor performance metrics
- Test toegankelijkheid met screen readers
### EPD App: **NO GO** ❌
- **Behalve:** Welcome screen (één keer, met skip optie)
- Focus op functioneel design volgens UX stylesheet
- Gebruik subtiele gradients of solid colors voor achtergronden
### Implementatie Prioriteit:
1. **Week 1:** Marketing hero section met shader (als MVP)
2. **Week 2:** Performance optimalisatie + mobile fallback
3. **Week 4:** A/B test resultaten evalueren
4. **Post-launch:** Beslissing over permanente implementatie
---
## 🎯 Design Principes Samenvatting
**Voor Marketing:**
> "Innovatie moet zichtbaar zijn, maar niet opdringerig"
**Voor EPD:**
> "Elke visuele keuze moet de gebruiker helpen, niet afleiden"
**Algemeen:**
> "Technologie moet de boodschap dienen, niet domineren"
---
**Design Team Sign-off:**
✅ Marketing website: Goedkeuring met voorwaarden
❌ EPD app: Afwijzing (behalve welcome screen)
📝 Stylesheet aanpassingen: Vereist voor consistency

View File

@@ -0,0 +1,403 @@
# 🚀 Marketing Shader Implementation Guide
**Doel:** Praktische implementatie van dot-shader component voor marketing website hero section.
---
## 📐 Design Specificaties
### Hero Section Layout
```
┌─────────────────────────────────────┐
│ [Shader Background - zeer subtiel] │
│ │
│ ┌─────────────────────────────┐ │
│ │ Hero Content Overlay │ │
│ │ - Headline (wit/donker) │ │
│ │ - Subheadline │ │
│ │ - CTA Buttons │ │
│ │ - Live Metrics Counter │ │
│ └─────────────────────────────┘ │
│ │
└─────────────────────────────────────┘
```
### Visuele Hiërarchie
1. **Shader:** Opacity 0.02-0.03 (bijna onzichtbaar, maar aanwezig)
2. **Content Overlay:** Semi-transparant of solid (afhankelijk van contrast)
3. **Tekst:** Hoog contrast (wit op donker, of donker op licht)
---
## 🔧 Technische Implementatie
### Stap 1: Aangepaste Marketing Variant
```typescript
// components/ui/marketing-shader-background.tsx
'use client'
import { DotScreenShader } from './dot-shader-background'
import { useTheme } from 'next-themes'
import { useEffect, useState } from 'react'
interface MarketingShaderProps {
variant?: 'hero' | 'section'
className?: string
}
export function MarketingShader({ variant = 'hero', className }: MarketingShaderProps) {
const { theme } = useTheme()
const [mounted, setMounted] = useState(false)
const [reducedMotion, setReducedMotion] = useState(false)
useEffect(() => {
setMounted(true)
// Check for reduced motion preference
const mediaQuery = window.matchMedia('(prefers-reduced-motion: reduce)')
setReducedMotion(mediaQuery.matches)
const handleChange = (e: MediaQueryListEvent) => setReducedMotion(e.matches)
mediaQuery.addEventListener('change', handleChange)
return () => mediaQuery.removeEventListener('change', handleChange)
}, [])
// Fallback voor mobile of reduced motion
if (!mounted || reducedMotion) {
return (
<div
className={`absolute inset-0 bg-gradient-to-br from-slate-50 via-blue-50/30 to-slate-100 ${className}`}
aria-hidden="true"
/>
)
}
// Desktop: shader component
return (
<div className={`absolute inset-0 overflow-hidden ${className}`} aria-hidden="true">
<DotScreenShader />
{/* Subtle overlay voor betere tekst leesbaarheid */}
<div className="absolute inset-0 bg-white/40 dark:bg-slate-900/40 pointer-events-none" />
</div>
)
}
```
### Stap 2: Hero Section Component
```typescript
// app/(marketing)/components/hero-section.tsx
import { MarketingShader } from '@/components/ui/marketing-shader-background'
import { LiveMetricsCounter } from './live-metrics-counter'
export function HeroSection() {
return (
<section className="relative min-h-screen flex items-center justify-center overflow-hidden">
{/* Shader Background */}
<MarketingShader variant="hero" className="z-0" />
{/* Content Overlay */}
<div className="relative z-10 container mx-auto px-4 py-20">
<div className="max-w-4xl mx-auto text-center">
{/* Headline */}
<h1 className="text-5xl md:text-7xl font-bold text-slate-900 dark:text-white mb-6">
Software on Demand
</h1>
{/* Subheadline */}
<p className="text-xl md:text-2xl text-slate-700 dark:text-slate-300 mb-8">
Van 100.000 en 12 maanden naar 200 en 4 weken
</p>
{/* Live Metrics */}
<LiveMetricsCounter />
{/* CTAs */}
<div className="flex flex-col sm:flex-row gap-4 justify-center mt-12">
<button className="px-8 py-4 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition">
Bekijk Demo
</button>
<button className="px-8 py-4 bg-slate-200 text-slate-900 rounded-lg hover:bg-slate-300 transition">
Lees Manifesto
</button>
</div>
</div>
</div>
</section>
)
}
```
### Stap 3: Shader Component Aanpassingen
```typescript
// Aanpassingen in dot-shader-background.tsx voor marketing gebruik
// In Scene component, update getThemeColors:
const getThemeColors = () => {
switch (theme) {
case 'light':
return {
dotColor: '#E2E8F0', // Match UX stylesheet border color
bgColor: '#F8FAFC', // Match UX stylesheet app background
dotOpacity: 0.03 // Zeer subtiel voor marketing
}
case 'dark':
return {
dotColor: '#475569', // Match secondary text
bgColor: '#0F172A', // Match primary text (inverted)
dotOpacity: 0.02 // Nog subtieler
}
default:
return {
dotColor: '#E2E8F0',
bgColor: '#F8FAFC',
dotOpacity: 0.03
}
}
}
// Update gridSize voor eleganter effect
const gridSize = 80 // Fijner dan standaard 100
```
---
## 🎨 Styling Integratie
### Tailwind Classes voor Content Overlay
```css
/* Zorg voor goede contrast over shader */
.hero-content {
/* Optioneel: semi-transparante achtergrond voor tekst */
background: rgba(255, 255, 255, 0.7);
backdrop-filter: blur(10px);
/* Of: solid achtergrond met padding */
background: white;
padding: 2rem;
border-radius: 1rem;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
```
### Contrast Check
**Test Scenario's:**
1. Wit tekst op shader achtergrond → Minimaal 4.5:1 contrast
2. Donker tekst op shader achtergrond → Minimaal 4.5:1 contrast
3. Met overlay → Contrast moet verbeteren
**Tools:**
- [WebAIM Contrast Checker](https://webaim.org/resources/contrastchecker/)
- Browser DevTools → Accessibility panel
---
## 📱 Mobile Responsive
### Breakpoint Strategie
```typescript
// components/ui/marketing-shader-background.tsx
export function MarketingShader({ variant, className }: MarketingShaderProps) {
const [isMobile, setIsMobile] = useState(false)
useEffect(() => {
const checkMobile = () => {
setIsMobile(window.innerWidth < 768) // Tailwind md breakpoint
}
checkMobile()
window.addEventListener('resize', checkMobile)
return () => window.removeEventListener('resize', checkMobile)
}, [])
// Mobile: gradient fallback (performance)
if (isMobile) {
return (
<div
className={`absolute inset-0 bg-gradient-to-br from-slate-50 via-blue-50/20 to-slate-100 ${className}`}
aria-hidden="true"
/>
)
}
// Desktop: shader
return <DotScreenShader />
}
```
**Reden:**
- Mobile GPU performance beperkt
- Batterij impact
- UX: Gebruikers verwachten snelle laadtijden op mobile
---
## ⚡ Performance Optimalisatie
### Lazy Loading
```typescript
import dynamic from 'next/dynamic'
// Lazy load shader alleen wanneer hero in viewport
const MarketingShader = dynamic(
() => import('@/components/ui/marketing-shader-background').then(mod => mod.MarketingShader),
{
ssr: false, // Client-side only
loading: () => <div className="absolute inset-0 bg-slate-50" />
}
)
```
### Intersection Observer
```typescript
// components/ui/marketing-shader-background.tsx
export function MarketingShader({ variant, className }: MarketingShaderProps) {
const [shouldRender, setShouldRender] = useState(false)
const ref = useRef<HTMLDivElement>(null)
useEffect(() => {
if (!ref.current) return
const observer = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting) {
setShouldRender(true)
observer.disconnect()
}
},
{ threshold: 0.1 }
)
observer.observe(ref.current)
return () => observer.disconnect()
}, [])
if (!shouldRender) {
return <div ref={ref} className={`absolute inset-0 bg-slate-50 ${className}`} />
}
return <DotScreenShader />
}
```
---
## ♿ Toegankelijkheid
### Reduced Motion Support
```typescript
// Automatisch detecteren en respecteren
const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches
if (prefersReducedMotion) {
// Geen animaties, statische gradient
return <StaticGradientBackground />
}
```
### Skip Animation Knop
```typescript
// Optioneel: knop om animatie uit te zetten
<button
onClick={() => setAnimationEnabled(false)}
className="sr-only focus:not-sr-only"
>
Skip animatie
</button>
```
### ARIA Labels
```typescript
<div
className="absolute inset-0"
aria-hidden="true" // Decoratief element, niet voor screen readers
role="presentation"
>
<DotScreenShader />
</div>
```
---
## 📊 Monitoring & Metrics
### Performance Tracking
```typescript
// Track shader performance
useEffect(() => {
const startTime = performance.now()
// Na render
requestAnimationFrame(() => {
const renderTime = performance.now() - startTime
if (renderTime > 100) {
console.warn('Shader render tijd hoog:', renderTime)
// Mogelijk fallback activeren
}
})
}, [])
```
### A/B Test Setup
```typescript
// Variant A: Met shader
// Variant B: Zonder shader (gradient)
const useShader = () => {
// Cookie/localStorage based variant assignment
const variant = localStorage.getItem('hero-variant') || 'A'
return variant === 'A'
}
```
**Metrics te meten:**
- Time to Interactive (TTI)
- First Contentful Paint (FCP)
- Bounce rate
- Engagement tijd
- Conversion rate
---
## ✅ Checklist
### Pre-Launch
- [ ] Shader opacity op 0.02-0.03 (zeer subtiel)
- [ ] Kleuren matchen exact UX stylesheet
- [ ] Mobile fallback geïmplementeerd
- [ ] Reduced motion support
- [ ] Contrast check gedaan (WCAG AA)
- [ ] Performance test (< 100ms render tijd)
- [ ] Lazy loading geïmplementeerd
### Post-Launch
- [ ] Performance monitoring actief
- [ ] A/B test resultaten analyseren
- [ ] Gebruikersfeedback verzamelen
- [ ] Accessibility audit uitgevoerd
---
## 🎯 Conclusie
Het shader component kan **strategisch** gebruikt worden op de marketing website, mits:
1. Zeer lage opacity (0.02-0.03)
2. Alleen in hero section
3. Mobile fallback aanwezig
4. Toegankelijkheid gewaarborgd
5. Performance geoptimaliseerd
**Resultaat:** Innovatieve uitstraling zonder UX compromissen.

0
docs/manifesto.md Normal file
View File

View File

@@ -0,0 +1,979 @@
# 🚀 Mission Control — Bouwplan Mini-EPD Prototype
**Projectnaam:** Mini-EPD Prototype
**Versie:** v1.0
**Datum:** 10-11-2025
**Auteur:** Development Team PinkRoccade GGZ
---
## 1. Doel en context
🎯 **Doel:** Een werkend mini-EPD prototype bouwen dat tijdens de AI-inspiratiesessie bij PinkRoccade GGZ de kernprocessen uit de GGZ demonstreert: **intake → probleemclassificatie → behandelplan**.
📘 **Toelichting:** Dit project focust op het zichtbaar maken van AI-waarde (samenvatten, structureren, plan genereren) in een herkenbare GGZ-workflow. De demo duurt maximaal 10 minuten en toont hoe AI zorgmedewerkers kan ondersteunen bij administratieve taken. Het systeem wordt gebouwd met fictieve data voor demonstratiedoeleinden.
**Belangrijkste doelen:**
- Demonstreren van AI-toegevoegde waarde in ECD-processen
- Herkenbare workflow voor GGZ-professionals
- Inspiratie bieden voor AI-integratie in bestaande systemen
- Direct bruikbare output (samenvattingen, behandelplannen) genereren
---
## 2. Uitgangspunten
### 2.1 Technische Stack
🎯 **Doel:** Complete technologie stack voor het mini-EPD prototype.
**Frontend:**
- **Framework:** Next.js 14+ (App Router)
- **Styling:** Tailwind CSS v3.4 (fallback vanaf v4 bij problemen)
- **UI Componenten:** shadcn/ui of eigen headless componenten
- **Rich Text Editor:** TipTap (ProseMirror basis)
- **Iconen:** lucide-react
- **State Management:** Zustand + React Context API
**Backend:**
- **API:** Next.js Route Handlers (server-side)
- **Database:** Supabase (PostgreSQL)
- **Auth:** Supabase Auth
- **Storage:** Supabase Storage
- **AI Integration:** Claude API (Anthropic)
**DevOps & Tooling:**
- **Hosting:** Vercel (EU region)
- **Version Control:** Git/GitHub
- **Type Safety:** TypeScript
- **Validation:** Zod
- **Testing:** Vitest (unit) + Playwright (E2E)
- **PDF Export (stretch):** Chromium via Playwright/Puppeteer
### 2.2 Projectkaders
🎯 **Doel:** Vaste kaders waarbinnen het project wordt ontwikkeld.
- **Tijd:** 3 weken totale bouwtijd voor MVP
- **Demo deadline:** Augustus 2025 (AI-inspiratiesessie)
- **Budget:** Beperkt voor externe API calls (Claude AI)
- **Team:** 1-2 developers + 1 consultant/product owner
- **Data:** Uitsluitend fictieve demo-data (geen productiegegevens)
- **Scope:** MVP features voor 10-minuten demo
- **Gebruikers:** Demo-users met volledige toegang (simplified auth)
- **Compliance:** Geen medische certificering vereist (demo only)
### 2.3 Programmeer Uitgangspunten
🎯 **Doel:** Code-kwaliteit principes en development best practices.
**Core Principles:**
- **DRY (Don't Repeat Yourself)**
- Herbruikbare React componenten in `/src/components/ui/`
- Shared utility functions in `/src/lib/utils/`
- Centrale API client voor Supabase queries
- Gedeelde prompt templates voor AI calls
- **SOC (Separation of Concerns)**
- UI componenten gescheiden van business logic
- Database queries in dedicated service layers (`/src/lib/services/`)
- AI prompts in `/src/lib/ai/prompts/`
- Styling via Tailwind classes, geen inline styles
- Route handlers voor server-side operaties
- **KISS (Keep It Simple, Stupid)**
- Directe Supabase queries zonder ORM overhead
- Eenvoudige state management met Zustand
- Minimale abstractie voor MVP scope
- Clear component naming (e.g., `ClientList`, `IntakeEditor`)
- **YAGNI (You Aren't Gonna Need It)**
- Geen multi-tenant setup voor demo
- Basis auth zonder rollenbeheer
- Skip complex caching voor MVP
- Geen realtime features voor eerste versie
- **Security**
- API keys alleen server-side (`ANTHROPIC_API_KEY`, `SUPABASE_SERVICE_ROLE_KEY`)
- Input sanitization met Zod schemas
- Row Level Security (RLS) policies in Supabase
- CORS configuratie voor API endpoints
- XSS protection via React's default escaping
---
## 3. Epics & Stories Overzicht
🎯 **Doel:** Complete overzicht van alle development epics met technische details.
| Epic ID | Epic Naam | Stories | Points | Status | Priority | Dependencies |
|---------|-----------|---------|--------|--------|----------|--------------|
| EP00 | Project Setup & Configuration | 5 | 13 | Done | Critical | - |
| EP01 | Database & Data Model | 4 | 21 | Not Started | Critical | EP00 |
| EP02 | Authentication & Authorization | 3 | 8 | Not Started | High | EP00, EP01 |
| EP03 | Client Management | 5 | 21 | Not Started | High | EP01, EP02 |
| EP04 | Intake Module | 6 | 34 | Not Started | Critical | EP03 |
| EP05 | Problem Profile (DSM-light) | 4 | 21 | Not Started | High | EP04 |
| EP06 | Treatment Plan Module | 5 | 34 | Not Started | High | EP05 |
| EP07 | AI Integration | 5 | 34 | Not Started | Critical | EP04 |
| EP08 | Dashboard & Navigation | 4 | 13 | Not Started | Medium | EP03 |
| EP09 | UI Components & Styling | 5 | 21 | Not Started | Medium | EP00 |
| EP10 | Testing & Quality Assurance | 4 | 13 | Not Started | High | All |
| EP11 | Deployment & Demo Prep | 4 | 13 | Not Started | Critical | All |
| EP12 | Stretch Features | 3 | 21 | Not Started | Low | EP06 |
**Totaal:** 57 stories | 257 story points
---
## 4. Epics & Stories (Uitwerking)
### Epic EP00 — Project Setup & Configuration
**Epic Doel:** Complete development omgeving met alle tools en dependencies geconfigureerd.
| Story ID | Story Title | Points | Status | Dependencies |
|----------|-------------|--------|--------|--------------|
| EP00-ST01 | Next.js project opzetten | 3 | Done | - |
| EP00-ST02 | Tailwind CSS en UI libraries installeren | 3 | Done | EP00-ST01 |
| EP00-ST03 | Supabase project aanmaken | 3 | Done | EP00-ST01 |
| EP00-ST04 | Environment variables configureren | 2 | Done | EP00-ST03 |
| EP00-ST05 | Git repository opzetten | 2 | Done | EP00-ST01 |
**Story Details:**
**EP00-ST01:** Als developer wil ik een Next.js project opzetten zodat ik kan beginnen met development
- ✅ Next.js 14+ met App Router
- ✅ TypeScript configuratie
- ✅ Folder structuur volgens conventions
- ✅ Development server draait op localhost:3000
**EP00-ST02:** Als developer wil ik Tailwind CSS en UI libraries installeren zodat ik consistent kan stylen
- ✅ Tailwind CSS v3.4 werkend
- ✅ tailwind.config.ts met custom theme
- ✅ lucide-react icons beschikbaar
- ✅ shadcn/ui setup (components.json, utils.ts)
**EP00-ST03:** Als developer wil ik Supabase project aanmaken zodat ik database en auth kan gebruiken
- ✅ Supabase project in EU region (dqugbrpwtisgyxscpefg)
- ✅ Connection string in .env.local
- ✅ Supabase client configured (lib/supabase/client.ts + server.ts)
- ✅ TypeScript types generation script (pnpm run types:generate)
**EP00-ST04:** Als developer wil ik environment variables configureren zodat services veilig verbonden zijn
- ✅ .env.local met alle keys (SUPABASE_URL, ANON_KEY, SERVICE_ROLE_KEY)
- ✅ .env.example voor team
- ⏳ Vercel environment variables (bij deployment EP11)
- ✅ Validation bij startup (throws error if missing)
**EP00-ST05:** Als developer wil ik Git repository opzetten zodat code versiebeheerd is
- ✅ GitHub repository
- ✅ .gitignore configuratie
- ⏳ Branch protection rules
- ✅ Initial commit met setup
**Technische implementatie details:**
- **Database:** Gebruik Supabase EU-region (Frankfurt/London)
- **Environment variables:**
```
NEXT_PUBLIC_SUPABASE_URL
NEXT_PUBLIC_SUPABASE_ANON_KEY
SUPABASE_SERVICE_ROLE_KEY
ANTHROPIC_API_KEY
```
- **Folder structuur:**
```
/src
/app (routes)
/components
/lib (utilities, services)
/types
```
---
### Epic EP01 — Database & Data Model
**Epic Doel:** Complete database schema met alle tabellen en relaties volgens TO specificatie.
| Story ID | Story Title | Points | Status | Dependencies |
|----------|-------------|--------|--------|--------------|
| EP01-ST01 | Database tabellen creëren | 8 | Not Started | EP00-ST03 |
| EP01-ST02 | Row Level Security policies implementeren | 5 | Not Started | EP01-ST01 |
| EP01-ST03 | Database migrations opzetten | 3 | Not Started | EP01-ST01 |
| EP01-ST04 | Demo data seeden | 5 | Not Started | EP01-ST01 |
**Story Details:**
**EP01-ST01:** Als developer wil ik database tabellen creëren zodat data opgeslagen kan worden
- ⏳ Tables: clients, intake_notes, problem_profiles, treatment_plans, ai_events
- ⏳ Correct data types (UUID, JSONB, etc.)
- ⏳ Foreign key constraints
- ⏳ Timestamps (created_at, updated_at)
**EP01-ST02:** Als developer wil ik Row Level Security policies implementeren zodat data veilig is
- ⏳ RLS enabled op alle tables
- ⏳ Policies voor authenticated users
- ⏳ Test queries werken correct
- ⏳ Service role bypass werkt
**EP01-ST03:** Als developer wil ik database migrations opzetten zodat schema versiebeheerd is
- ⏳ Supabase migrations folder
- ⏳ Initial migration script
- ⏳ Rollback mogelijk
- ⏳ Documentation
**EP01-ST04:** Als developer wil ik demo data seeden zodat er test content beschikbaar is
- ⏳ 3+ test cliënten
- ⏳ Intake notes per cliënt
- ⏳ Minimaal 1 compleet dossier
- ⏳ Seed script: `npm run seed`
**Technische implementatie details:**
- **Database Schema (zie TO §2.3):**
- `clients`: id (UUID), first_name, last_name, birth_date, created_at, updated_at
- `intake_notes`: id, client_id (FK), title, tag (CHECK), content_json (JSONB), content_text
- `problem_profiles`: id, client_id (FK), category (CHECK), severity (CHECK), remarks
- `treatment_plans`: id, client_id (FK), version, status (CHECK), plan (JSONB)
- `ai_events`: id, kind, client_id, request, response, duration_ms
- **RLS Policies (zie TO §2.4):**
```sql
CREATE POLICY "Allow all for authenticated users" ON [table]
FOR ALL USING (auth.uid() IS NOT NULL);
```
---
### Epic EP02 — Authentication & Authorization
**Epic Doel:** Werkende authenticatie met Supabase Auth voor demo gebruikers.
| Story ID | Story Title | Points | Status | Dependencies |
|----------|-------------|--------|--------|--------------|
| EP02-ST01 | Login implementeren | 3 | Not Started | EP00-ST03, EP01-ST02 |
| EP02-ST02 | Protected routes implementeren | 3 | Not Started | EP02-ST01 |
| EP02-ST03 | Logout functionaliteit | 2 | Not Started | EP02-ST01 |
**Story Details:**
**EP02-ST01:** Als gebruiker wil ik kunnen inloggen zodat ik toegang krijg tot het systeem
- ⏳ Login pagina op /auth/login
- ⏳ Email/password of magic link
- ⏳ Session management
- ⏳ Redirect naar dashboard
**EP02-ST02:** Als developer wil ik protected routes implementeren zodat alleen ingelogde users toegang hebben
- ⏳ Middleware voor auth check
- ⏳ Redirect naar login indien nodig
- ⏳ Loading states tijdens auth
- ⏳ Session refresh
**EP02-ST03:** Als gebruiker wil ik kunnen uitloggen zodat mijn sessie beëindigd wordt
- ⏳ Logout button in header
- ⏳ Session cleanup
- ⏳ Redirect naar login
- ⏳ Clear local state
**Technische implementatie details:**
- **Auth flow:** Email/password voor demo (magic link als backup)
- **Middleware:** Check auth in `middleware.ts`
- **Protected routes:** Alles behalve `/auth/*`
- **Session:** Supabase JWT tokens
---
### Epic EP03 — Client Management
**Epic Doel:** Complete CRUD functionaliteit voor cliëntbeheer.
| Story ID | Story Title | Points | Status | Dependencies |
|----------|-------------|--------|--------|--------------|
| EP03-ST01 | Cliëntenlijst tonen | 5 | Not Started | EP01-ST01, EP02-ST02 |
| EP03-ST02 | Nieuwe cliënt aanmaken | 5 | Not Started | EP03-ST01 |
| EP03-ST03 | Cliëntgegevens bekijken | 5 | Not Started | EP03-ST01 |
| EP03-ST04 | Cliëntgegevens bewerken | 3 | Not Started | EP03-ST03 |
| EP03-ST05 | Zustand store voor client state | 3 | Not Started | EP00-ST01 |
**Story Details:**
**EP03-ST01:** Als behandelaar wil ik een cliëntenlijst zien zodat ik overzicht heb
- ⏳ Tabel met: ClientID, Naam, Geboortedatum, Laatste update
- ⏳ Zoekbalk voor naam/ID
- ⏳ Pagination bij >20 items
- ⏳ Loading skeleton
**EP03-ST02:** Als behandelaar wil ik een nieuwe cliënt aanmaken zodat ik kan starten met intake
- ⏳ Modal/drawer met formulier
- ⏳ Velden: Voornaam, Achternaam, Geboortedatum
- ⏳ Auto-generated UUID
- ⏳ Validatie met Zod
- ⏳ Success toast
**EP03-ST03:** Als behandelaar wil ik cliëntgegevens bekijken zodat ik het dossier kan inzien
- ⏳ Route: /clients/[id]
- ⏳ Breadcrumb navigatie
- ⏳ Tabs: Overzicht, Intakes, Profiel, Plan
- ⏳ 404 handling
**EP03-ST04:** Als behandelaar wil ik cliëntgegevens bewerken zodat ik updates kan maken
- ⏳ Edit mode in detail view
- ⏳ Form validation
- ⏳ Optimistic updates
- ⏳ Error handling
**EP03-ST05:** Als developer wil ik Zustand store voor client state zodat data consistent blijft
- ⏳ clientStore.ts setup
- ⏳ Actions: setSelectedClient, updateClient
- ⏳ Persistent state waar nodig
- ⏳ TypeScript types
**Technische implementatie details:**
- **API endpoints:**
- `POST /api/clients` - Create
- `GET /api/clients` - List with search
- `GET /api/clients/[id]` - Get single
- `PATCH /api/clients/[id]` - Update
- **Zustand store:** Central state voor selected client
- **Validatie:** Zod schemas voor alle forms
---
### Epic EP04 — Intake Module
**Epic Doel:** Rich text editor voor intake verslagen met TipTap integratie.
| Story ID | Story Title | Points | Status | Dependencies |
|----------|-------------|--------|--------|--------------|
| EP04-ST01 | TipTap editor implementeren | 8 | Not Started | EP03-ST03 |
| EP04-ST02 | Intake verslagen opslaan | 5 | Not Started | EP04-ST01 |
| EP04-ST03 | Tags toevoegen aan verslagen | 3 | Not Started | EP04-ST02 |
| EP04-ST04 | Oude intakes bekijken | 5 | Not Started | EP04-ST02 |
| EP04-ST05 | Tekst extractie voor search | 5 | Not Started | EP04-ST02 |
| EP04-ST06 | AI-rail implementeren | 8 | Not Started | EP04-ST01 |
**Story Details:**
**EP04-ST01:** Als behandelaar wil ik TipTap editor gebruiken zodat ik rijk opgemaakte notities kan maken
- ⏳ TipTap met StarterKit
- ⏳ Toolbar: Bold, Italic, Lists, etc.
- ⏳ Placeholder text
- ⏳ Content als ProseMirror JSON
**EP04-ST02:** Als behandelaar wil ik intake verslagen opslaan zodat ze bewaard blijven
- ⏳ Save button + Ctrl/Cmd+S
- ⏳ Store in intake_notes table
- ⏳ Auto-save indicator
- ⏳ Success/error toasts
**EP04-ST03:** Als behandelaar wil ik tags toevoegen aan verslagen zodat ik ze kan categoriseren
- ⏳ Tag dropdown: Intake/Evaluatie/Plan
- ⏳ Tag badge in lijst
- ⏳ Filter op tag mogelijk
- ⏳ Validation
**EP04-ST04:** Als behandelaar wil ik oude intakes bekijken zodat ik historie kan inzien
- ⏳ Lijst van intakes per cliënt
- ⏳ Sorteer op datum
- ⏳ Click to view/edit
- ⏳ Read-only mode optie
**EP04-ST05:** Als developer wil ik tekst extractie implementeren voor search
- ⏳ Extract plain text van ProseMirror
- ⏳ Store in content_text field
- ⏳ Full-text search mogelijk
- ⏳ Performance optimization
**EP04-ST06:** Als behandelaar wil ik de AI-rail zien zodat AI-resultaten preview kan bekijken
- ⏳ Rechter paneel (40% breedte)
- ⏳ Collapsible/expandable
- ⏳ Preview area voor AI output
- ⏳ Action buttons: Invoegen/Annuleren
**Technische implementatie details:**
- **TipTap setup:**
```typescript
import StarterKit from '@tiptap/starter-kit'
const editor = useEditor({
extensions: [StarterKit],
content: prosemirrorJSON
})
```
- **Storage:** content_json (JSONB) + content_text (TEXT)
- **API:** `/api/intakes` endpoints
---
### Epic EP05 — Problem Profile (DSM-light)
**Epic Doel:** DSM-light categorisatie systeem met severity bepaling.
| Story ID | Story Title | Points | Status | Dependencies |
|----------|-------------|--------|--------|--------------|
| EP05-ST01 | Probleem categorie selecteren | 5 | Not Started | EP04-ST02 |
| EP05-ST02 | Severity aangeven | 3 | Not Started | EP05-ST01 |
| EP05-ST03 | Opmerkingen toevoegen | 3 | Not Started | EP05-ST01 |
| EP05-ST04 | AI-suggestie paneel | 10 | Not Started | EP04-ST02, EP07-ST03 |
**Story Details:**
**EP05-ST01:** Als behandelaar wil ik een probleem categorie selecteren zodat ik kan classificeren
- ⏳ Dropdown met 6 categorieën (zie FO §4.4)
- ⏳ Beschrijving per categorie
- ⏳ Validation required field
- ⏳ Store in problem_profiles
**EP05-ST02:** Als behandelaar wil ik severity aangeven zodat ernst duidelijk is
- ⏳ Button group: Laag/Middel/Hoog
- ⏳ Kleur-coded badges
- ⏳ Hover tooltips met uitleg
- ⏳ Required validation
**EP05-ST03:** Als behandelaar wil ik opmerkingen toevoegen zodat ik context kan geven
- ⏳ Textarea voor vrije tekst
- ⏳ Character limit (500)
- ⏳ Optional field
- ⏳ Markdown support
**EP05-ST04:** Als behandelaar wil ik AI-suggestie paneel gebruiken zodat classificatie sneller gaat
- ⏳ Knop "AI > Analyseer intake"
- ⏳ Suggestie paneel rechts
- ⏳ Shows: categorie, severity, rationale
- ⏳ Accepteer/Negeer buttons
- ⏳ Source highlighting in intake (zie TO §5.4)
**Technische implementatie details:**
- **Categorieën (enum):**
- stemming_depressie
- angst
- gedrag_impuls
- middelen_gebruik
- cognitief
- context_psychosociaal
- **Severity badges:** Tailwind classes volgens UX stylesheet
- **AI highlighting:** TipTap Decorations API
---
### Epic EP06 — Treatment Plan Module
**Epic Doel:** Genereren en beheren van gestructureerde behandelplannen.
| Story ID | Story Title | Points | Status | Dependencies |
|----------|-------------|--------|--------|--------------|
| EP06-ST01 | Behandelplan genereren | 10 | Not Started | EP05-ST01, EP07-ST04 |
| EP06-ST02 | Doelen bewerken | 8 | Not Started | EP06-ST01 |
| EP06-ST03 | Interventies specificeren | 5 | Not Started | EP06-ST01 |
| EP06-ST04 | Meetmomenten plannen | 5 | Not Started | EP06-ST01 |
| EP06-ST05 | Plan publiceren | 6 | Not Started | EP06-ST02 |
**Story Details:**
**EP06-ST01:** Als behandelaar wil ik een behandelplan genereren zodat ik snel een opzet heb
- ⏳ Knop "AI > Genereer behandelplan"
- ⏳ Uses intake + profile als context
- ⏳ Genereert 4 secties
- ⏳ Loading state tijdens generatie
**EP06-ST02:** Als behandelaar wil ik doelen bewerken zodat ze SMART geformuleerd zijn
- ⏳ Lijst van doelen (bullets)
- ⏳ Inline editing mogelijk
- ⏳ Add/remove doelen
- ⏳ Regenerate per doel optie
**EP06-ST03:** Als behandelaar wil ik interventies specificeren zodat behandeling duidelijk is
- ⏳ Interventie lijst
- ⏳ Type + frequentie + duur
- ⏳ Voorgestelde interventies
- ⏳ Custom toevoegen
**EP06-ST04:** Als behandelaar wil ik meetmomenten plannen zodat voortgang gemeten wordt
- ⏳ Timeline met meetmomenten
- ⏳ Na X sessies format
- ⏳ Evaluatie types
- ⏳ Calendar integration (stretch)
**EP06-ST05:** Als behandelaar wil ik plan publiceren zodat het definitief wordt
- ⏳ Concept vs Gepubliceerd status
- ⏳ Versioning (v1, v2, etc.)
- ⏳ Published timestamp
- ⏳ Read-only na publicatie
- ⏳ Nieuwe versie mogelijk
**Technische implementatie details:**
- **Plan structuur (JSONB):**
```typescript
{
doelen: string[],
interventies: string[],
frequentie: string,
meetmomenten: string[]
}
```
- **Status flow:** concept → gepubliceerd → nieuwe versie
- **API:** `/api/treatment-plan` endpoints
---
### Epic EP07 — AI Integration
**Epic Doel:** Claude AI integratie voor alle AI-powered features.
| Story ID | Story Title | Points | Status | Dependencies |
|----------|-------------|--------|--------|--------------|
| EP07-ST01 | Claude API client configureren | 5 | Not Started | EP00-ST04 |
| EP07-ST02 | Intake samenvatten met AI | 8 | Not Started | EP07-ST01, EP04-ST06 |
| EP07-ST03 | Problemen extraheren met AI | 8 | Not Started | EP07-ST01 |
| EP07-ST04 | Behandelplan genereren met AI | 8 | Not Started | EP07-ST01 |
| EP07-ST05 | AI events loggen | 5 | Not Started | EP07-ST01, EP01-ST01 |
**Story Details:**
**EP07-ST01:** Als developer wil ik Claude API client configureren zodat AI calls mogelijk zijn
- ⏳ Anthropic SDK setup
- ⏳ Server-side only implementation
- ⏳ Error handling
- ⏳ Rate limiting logic
**EP07-ST02:** Als behandelaar wil ik intake samenvatten met AI zodat ik snel overzicht heb
- ⏳ Endpoint: /api/ai/summarize
- ⏳ 5-8 bullet points output
- ⏳ Nederlands, klinisch neutraal
- ⏳ Max 5 sec response time
**EP07-ST03:** Als behandelaar wil ik problemen extraheren met AI zodat classificatie sneller gaat
- ⏳ Endpoint: /api/ai/extract
- ⏳ Returns: category, severity, rationale
- ⏳ Source sentences identificatie
- ⏳ Highlighting support
**EP07-ST04:** Als behandelaar wil ik behandelplan genereren met AI zodat ik een goede basis heb
- ⏳ Endpoint: /api/ai/generate-plan
- ⏳ SMART doelen formulering
- ⏳ Evidence-based interventies
- ⏳ Structured JSON output
**EP07-ST05:** Als developer wil ik AI events loggen zodat gebruik gemonitord wordt
- ⏳ Store in ai_events table
- ⏳ Track: prompt, response, duration
- ⏳ Cost calculation
- ⏳ Error logging
**Technische implementatie details:**
- **Claude model:** claude-3-5-sonnet-20241022
- **Prompt templates:** `/src/lib/ai/prompts/`
- **Temperature:** 0.3 (deterministic)
- **Max tokens:** Per endpoint verschillend
- **Security:** API key alleen server-side
---
### Epic EP08 — Dashboard & Navigation
**Epic Doel:** Configureerbaar dashboard met tegels en navigatie.
| Story ID | Story Title | Points | Status | Dependencies |
|----------|-------------|--------|--------|--------------|
| EP08-ST01 | Dashboard met tegels | 5 | Not Started | EP03-ST03 |
| EP08-ST02 | Tegels configureren | 3 | Not Started | EP08-ST01 |
| EP08-ST03 | Breadcrumb navigatie | 2 | Not Started | EP03-ST03 |
| EP08-ST04 | Sidebar navigatie | 3 | Not Started | EP03-ST03 |
**Story Details:**
**EP08-ST01:** Als behandelaar wil ik een dashboard zien zodat ik overzicht heb per cliënt
- ⏳ 5 tegels (zie FO §4.2)
- ⏳ Responsive grid layout
- ⏳ Data uit verschillende tables
- ⏳ Click naar detail
**EP08-ST02:** Als behandelaar wil ik tegels configureren zodat ik kan personaliseren
- ⏳ Settings icon → modal
- ⏳ Checkboxes per tegel
- ⏳ LocalStorage persistence
- ⏳ Instant preview
**EP08-ST03:** Als gebruiker wil ik breadcrumb navigatie zodat ik weet waar ik ben
- ⏳ Breadcrumb in header
- ⏳ Clickable segments
- ⏳ Current page highlight
- ⏳ Responsive truncation
**EP08-ST04:** Als gebruiker wil ik sidebar navigatie zodat ik tussen modules kan wisselen
- ⏳ Vertical navigation
- ⏳ Active state indicator
- ⏳ Icons + labels
- ⏳ Collapsible op mobile
**Technische implementatie details:**
- **Tegels:** Basisgegevens, Laatste Intake, Probleemprofiel, Behandelplan, Afspraken
- **Grid:** Tailwind Grid met responsive breakpoints
- **State:** Zustand voor tegel configuratie
---
### Epic EP09 — UI Components & Styling
**Epic Doel:** Consistente UI componenten volgens UX stylesheet.
| Story ID | Story Title | Points | Status | Dependencies |
|----------|-------------|--------|--------|--------------|
| EP09-ST01 | Basis componenten bouwen | 5 | Not Started | EP00-ST02 |
| EP09-ST02 | Toast notificaties | 3 | Not Started | EP09-ST01 |
| EP09-ST03 | Loading states | 3 | Not Started | EP09-ST01 |
| EP09-ST04 | Formulier componenten | 5 | Not Started | EP09-ST01 |
| EP09-ST05 | Dark mode (stretch) | 5 | Not Started | EP09-ST01 |
**Story Details:**
**EP09-ST01:** Als developer wil ik basis componenten bouwen zodat UI consistent is
- ⏳ Button, Card, Input, Select
- ⏳ Consistent met UX stylesheet
- ⏳ TypeScript props
- ⏳ Storybook (optional)
**EP09-ST02:** Als developer wil ik toast notificaties implementeren zodat feedback duidelijk is
- ⏳ Success/Error/Info/Warning
- ⏳ Auto-dismiss na 5 sec
- ⏳ Queue multiple toasts
- ⏳ Accessible (aria-live)
**EP09-ST03:** Als developer wil ik loading states implementeren zodat gebruiker weet dat er geladen wordt
- ⏳ Skeleton loaders
- ⏳ Spinners voor buttons
- ⏳ Progress bars voor AI
- ⏳ Consistent animation
**EP09-ST04:** Als developer wil ik formulier componenten maken zodat input consistent is
- ⏳ Form wrapper met validation
- ⏳ Error messages styling
- ⏳ Required field indicators
- ⏳ Help text support
**EP09-ST05:** Als developer wil ik dark mode ondersteunen (stretch) zodat gebruikers kunnen kiezen
- ⏳ Theme toggle button
- ⏳ System preference detect
- ⏳ Persist preference
- ⏳ All components support
**Technische implementatie details:**
- **Kleuren:** Zie UX stylesheet (§2-4)
- **Component library:** shadcn/ui of custom
- **Icons:** lucide-react consistent gebruik
---
### Epic EP10 — Testing & Quality Assurance
**Epic Doel:** Comprehensive testing voor stabiele demo.
| Story ID | Story Title | Points | Status | Dependencies |
|----------|-------------|--------|--------|--------------|
| EP10-ST01 | Unit tests schrijven | 5 | Not Started | All features |
| EP10-ST02 | E2E tests schrijven | 5 | Not Started | All features |
| EP10-ST03 | Smoke tests uitvoeren | 2 | Not Started | All features |
| EP10-ST04 | Accessibility testen | 1 | Not Started | EP09 |
**Story Details:**
**EP10-ST01:** Als developer wil ik unit tests schrijven zodat business logic getest is
- ⏳ Vitest setup
- ⏳ Utils & services tests
- ⏳ 80% coverage /lib folder
- ⏳ CI integration
**EP10-ST02:** Als developer wil ik E2E tests schrijven zodat kritieke flows werken
- ⏳ Playwright setup
- ⏳ Happy path: intake → profile → plan
- ⏳ Error scenarios
- ⏳ Cross-browser
**EP10-ST03:** Als team wil ik smoke tests uitvoeren zodat demo stabiel is
- ⏳ Manual test checklist
- ⏳ All features tested
- ⏳ Performance acceptable
- ⏳ No console errors
**EP10-ST04:** Als developer wil ik accessibility testen zodat app toegankelijk is
- ⏳ Keyboard navigation
- ⏳ Screen reader support
- ⏳ WCAG AA contrast
- ⏳ Focus management
**Technische implementatie details:**
- **Test scenarios:** Zie FO §9 demo-scenario
- **Performance:** <3s initial load, <5s AI responses
- **Browser support:** Chrome, Firefox, Safari latest
---
### Epic EP11 — Deployment & Demo Prep
**Epic Doel:** Production-ready deployment en demo voorbereiding.
| Story ID | Story Title | Points | Status | Dependencies |
|----------|-------------|--------|--------|--------------|
| EP11-ST01 | Vercel deployment configureren | 3 | Not Started | All features |
| EP11-ST02 | Demo data prepareren | 5 | Not Started | EP01-ST04 |
| EP11-ST03 | Demo script schrijven | 3 | Not Started | All features |
| EP11-ST04 | Dry-run uitvoeren | 2 | Not Started | EP11-ST01 |
**Story Details:**
**EP11-ST01:** Als developer wil ik Vercel deployment configureren zodat app live is
- ⏳ Vercel project setup
- ⏳ EU region (Amsterdam)
- ⏳ Environment variables
- ⏳ Custom domain (optional)
**EP11-ST02:** Als team wil ik demo data prepareren zodat presentatie smooth verloopt
- ⏳ 3 complete test cliënten
- ⏳ Realistic intake texts
- ⏳ Pre-generated AI responses
- ⏳ Backup data ready
**EP11-ST03:** Als presenter wil ik demo script hebben zodat presentatie gestructureerd is
- ⏳ 10-minute script
- ⏳ Key talking points
- ⏳ Backup scenarios
- ⏳ Q&A anticipatie
**EP11-ST04:** Als team wil ik dry-run doen zodat demo succesvol verloopt
- ⏳ Complete run-through
- ⏳ Timing verified (< 10 min)
- ⏳ Technical issues fixed
- ⏳ Feedback processed
**Technische implementatie details:**
- **Deployment checklist:**
- Environment variables set
- Database migrations run
- Seed data loaded
- SSL certificate active
- Monitoring enabled
---
### Epic EP12 — Stretch Features (Optional)
**Epic Doel:** Extra features indien tijd beschikbaar.
| Story ID | Story Title | Points | Status | Dependencies |
|----------|-------------|--------|--------|--------------|
| EP12-ST01 | Afspraken plannen | 8 | Not Started | EP08-ST01 |
| EP12-ST02 | PDF export | 8 | Not Started | EP06-ST05 |
| EP12-ST03 | Leesbaarheid verbeteren met AI | 5 | Not Started | EP07-ST01 |
**Story Details:**
**EP12-ST01:** Als behandelaar wil ik afspraken kunnen plannen zodat agenda gekoppeld is
- ⏳ Calendar view
- ⏳ Create/edit appointments
- ⏳ Link to client
- ⏳ Dashboard widget
**EP12-ST02:** Als behandelaar wil ik PDF export zodat ik rapporten kan delen
- ⏳ Export button
- ⏳ Professional layout
- ⏳ All sections included
- ⏳ Download trigger
**EP12-ST03:** Als behandelaar wil ik leesbaarheid verbeteren met AI zodat tekst B1-niveau wordt
- ⏳ Endpoint: /api/ai/readability
- ⏳ B1 niveau output
- ⏳ Preserve medical accuracy
- ⏳ Preview before apply
---
## 5. Kwaliteit & Testplan
🎯 **Doel:** Borging van kwaliteit voor stabiele demo.
### Test Types
| Test Type | Scope | Tools | Coverage Target |
|-----------|-------|-------|-----------------|
| Unit Tests | Services, utilities, validators | Vitest | 80% /lib folder |
| Integration Tests | API endpoints, database queries | Vitest + MSW | All critical endpoints |
| E2E Tests | Complete user flows | Playwright | 3 happy paths, 2 error paths |
| Performance Tests | Load time, API response | Lighthouse | LCP <2.5s, FID <100ms |
| Accessibility Tests | WCAG compliance | axe-core | AA compliance |
| Security Tests | Auth, XSS, SQL injection | Manual + automated | OWASP top 10 |
### Critical Test Scenarios
1. **New Client Flow**
- Create client → Add intake → Generate summary → Extract problems → Create plan
- Expected time: <2 minutes
- All data persisted correctly
2. **AI Integration Flow**
- Large intake text (2000+ words) → All AI features work
- Response time <5 seconds per call
- Graceful degradation if AI fails
3. **Error Handling**
- Network failure → Appropriate error messages
- Invalid input → Clear validation feedback
- AI timeout → Fallback behavior
### Demo Checklist
- [ ] Login with demo account works
- [ ] Create new client (auto-generated ID)
- [ ] Write intake with TipTap editor
- [ ] AI summarize returns Dutch bullets
- [ ] Problem extraction with highlighting
- [ ] Treatment plan generation (SMART goals)
- [ ] Publish plan (version 1)
- [ ] Dashboard shows all data correctly
- [ ] Navigation breadcrumbs work
- [ ] No console errors
- [ ] Performance acceptable (<3s loads)
- [ ] Mobile view responsive
---
## 6. Demo & Presentatieplan
🎯 **Doel:** Succesvolle 10-minuten demo tijdens AI-inspiratiesessie.
### Demo Timeline
| Time | Activity | Key Points | Backup Plan |
|------|----------|------------|-------------|
| 0:00-1:00 | **Intro** | Context mini-EPD, AI-toegevoegde waarde | Slides ready |
| 1:00-2:30 | **Nieuwe cliënt** | Quick entry, auto ClientID, immediate start | Pre-created client |
| 2:30-5:00 | **Intake + AI** | TipTap editor, AI summarize, source highlighting | Cached AI response |
| 5:00-7:00 | **Profile + Plan** | DSM categorization, AI-generated plan, SMART goals | Manual input ready |
| 7:00-8:30 | **Publiceren** | Version control, status change, dashboard update | Screenshots |
| 8:30-10:00 | **Q&A** | Interactive discussion, next steps | FAQ prepared |
### Technical Setup
- **Primary:** Live on Vercel (stable internet required)
- **Backup 1:** Local development server
- **Backup 2:** Recorded video demo
- **Backup 3:** Static screenshots
### Key Messages
1. AI vermindert administratieve last met 50%
2. Consistente kwaliteit van documentatie
3. Meer tijd voor cliëntcontact
4. Evidence-based suggesties
5. Privacy-first design (geen echte data)
---
## 7. Risico's & Mitigatie
🎯 **Doel:** Proactieve risico management voor succesvolle oplevering.
| Risico | Kans | Impact | Mitigatie | Owner |
|--------|------|--------|-----------|-------|
| **Claude API rate limits** | Hoog | Hoog | Response caching, queue implementation, fallback to OpenAI | Developer |
| **TipTap complexiteit** | Medium | Hoog | Start simple, incremental features, fallback to textarea | Developer |
| **Supabase RLS policies fout** | Medium | Hoog | Extensive testing, service role fallback, monitoring | Developer |
| **AI output inconsistent** | Hoog | Medium | Prompt versioning, temperature tuning, validation layer | Developer |
| **Demo internet uitval** | Laag | Hoog | Local setup ready, mobile hotspot backup, video recording | Presenter |
| **Tijd tekort voor features** | Medium | Medium | MoSCoW prioritization, MVP focus, stretch clearly marked | PM |
| **Browser compatibility** | Laag | Medium | Test on Chrome/Safari/Firefox, polyfills where needed | QA |
| **Performance issues** | Medium | Medium | Lazy loading, code splitting, CDN for assets | Developer |
| **Security vulnerability** | Laag | Hoog | Pen test, OWASP checklist, security headers | Developer |
---
## 8. Referenties
🎯 **Doel:** Koppeling naar alle relevante projectdocumentatie.
### Mission Control Documents
- **PRD** — [Product Requirements Document](./prd-mini-ecd.md) - Business requirements en scope
- **FO** — [Functioneel Ontwerp](./fo-mini-ecd.md) - User flows en functionele specificaties
- **TO** — [Technisch Ontwerp](./to-mini-ecd.md) - Architectuur en database design
- **UX/UI** — [Stylesheet](./ux-stylesheet.md) - Kleuren en design system
- **API** — [API Access Document](./api-acces-mini-ecd.md) - Endpoints en authenticatie
### External Resources
- **Repository:** `https://github.com/pinkroccade/mini-epd-prototype`
- **Deployment:** `https://mini-epd.vercel.app`
- **Supabase:** `https://app.supabase.com/project/[project-id]`
- **Claude AI:** `https://docs.anthropic.com/claude/reference`
- **TipTap Docs:** `https://tiptap.dev`
- **Next.js Docs:** `https://nextjs.org/docs`
### Development Resources
- **Component Library:** `https://ui.shadcn.com`
- **Icons:** `https://lucide.dev`
- **Tailwind:** `https://tailwindcss.com`
---
## 9. Technische Notities
### Database Queries Examples
```typescript
// Get client with full dossier
const { data: client } = await supabase
.from('clients')
.select(`
*,
intake_notes (*),
problem_profiles (*),
treatment_plans (*)
`)
.eq('id', clientId)
.single()
// Search clients
const { data: clients } = await supabase
.from('clients')
.select('*')
.ilike('last_name', `%${searchQuery}%`)
.order('updated_at', { ascending: false })
```
### AI Prompt Templates
```typescript
// Summarize prompt
const SUMMARIZE_PROMPT = `
Vat het onderstaande intake-verslag samen in 5-8 bullets.
Schrijf in Nederlands, klinisch neutraal, zonder persoonlijke informatie.
Intake verslag:
{intakeText}
`
// Extract problems prompt
const EXTRACT_PROMPT = `
Analyseer de intake en bepaal:
1. DSM-light categorie (kies uit: stemming_depressie, angst, gedrag_impuls, middelen_gebruik, cognitief, context_psychosociaal)
2. Severity (laag, middel, hoog)
3. Rationale (2-3 zinnen)
4. Bronzinnen uit de tekst
Intake:
{intakeText}
`
```
### Component Structure
```typescript
// Example component with proper typing
interface ClientCardProps {
client: Client
onClick?: (id: string) => void
isSelected?: boolean
}
export function ClientCard({ client, onClick, isSelected }: ClientCardProps) {
return (
<Card
className={cn(
"cursor-pointer transition-shadow",
isSelected && "ring-2 ring-primary"
)}
onClick={() => onClick?.(client.id)}
>
<CardHeader>
<CardTitle>{client.first_name} {client.last_name}</CardTitle>
<CardDescription>
{format(new Date(client.birth_date), 'dd-MM-yyyy')}
</CardDescription>
</CardHeader>
</Card>
)
}
```
---
**Versiehistorie:**
| Versie | Datum | Auteur | Wijziging |
|--------|-------|--------|-----------|
| v1.0 | 10-11-2025 | Development Team | Initiële versie met complete epic breakdown |

View File

@@ -0,0 +1,618 @@
# 🚀 Mission Control Bouwplan AI Speedrun / Mini-ECD
🎯 **Projectnaam:** AI Speedrun - Mini-ECD Prototype
**Versie:** v1.1 (Actueel)
**Datum:** 15-11-2024
**Auteur:** Colin van der Heijden (AI Speedrun / ikbenlit.nl)
**Laatste Update:** 15-11-2024
---
## 1. Doel en context
🎯 **Doel:** Een werkend EPD-prototype bouwen in 4 weken dat demonstreert hoe "Software on Demand" traditionele ontwikkeling disrupts: van €100.000+ en 12-24 maanden naar €200 build cost en 4 weken doorlooptijd.
📘 **Toelichting:** Dit project dient een drievoudig doel:
1. **Demo voor GGZ-sector:** Tonen van AI-waarde in EPD-workflows (intake → profiel → plan) tijdens inspiratiesessies
2. **LinkedIn Build in Public:** Wekelijkse transparante updates die viral marketing genereren voor AI consultancy
3. **Software on Demand Proof:** Bewijs dat enterprise-kwaliteit software nu in weken ipv jaren gebouwd kan worden
Het systeem toont praktische AI-integratie: intake samenvattingen in seconden ipv uren, automatische DSM-classificatie, en behandelplannen die direct bruikbaar zijn. Alles met fictieve demo-data, privacy-first design.
---
## 2. Uitgangspunten
### 2.1 Technische Stack
🎯 **Doel:** Modern, bewezen technologie stack voor snelle development en lage run costs.
**Frontend:**
- **Framework:** Next.js 15 (App Router) - Single repo voor marketing + EPD
- **Styling:** Tailwind CSS v3.4 (fallback van v4 bij problemen)
- **UI Components:** shadcn/ui voor snelheid + consistentie
- **Rich Text:** TipTap editor (ProseMirror basis)
- **Icons:** Lucide React
- **State:** Zustand + React Context (simpel maar effectief)
**Backend:**
- **API:** Next.js Route Handlers (server-side)
- **Database:** Supabase (PostgreSQL + Auth + Storage) - EU region
- **AI:** Claude 3.5 Sonnet (Anthropic) - Superieur voor Nederlands
- **Hosting:** Vercel (EU region Amsterdam)
**Development & Tools:**
- **Version Control:** GitHub (public repo voor transparantie)
- **Type Safety:** TypeScript overal
- **Package Manager:** pnpm (sneller dan npm)
- **AI Pair Programming:** Cursor IDE
- **Testing:** Vitest + Playwright (basis coverage)
### 2.2 Projectkaders
🎯 **Doel:** Realistische constraints voor 4-weken sprint.
- **Tijd:** 4 weken part-time (80-120 uur totaal)
- **Budget:** €200 totaal (€50/maand runtime target)
- **Team:** 1 developer (Colin) + AI tools als co-pilot
- **Data:** 100% fictieve demo data
- **Scope:** MVP voor 10-min demo + marketing site
- **Launch:** LinkedIn viral series + demo sessies
### 2.3 Programmeer Uitgangspunten
🎯 **Doel:** Code quality zonder over-engineering voor MVP.
**Core Principles:**
- **DRY:** Herbruikbare componenten, centrale configs
- **KISS:** Simpele oplossingen boven complexiteit
- **SOC:** UI/logic/data layers gescheiden
- **YAGNI:** Alleen bouwen wat nu nodig is
**Development Practices:**
- **Iteratief:** Ship daily, perfect later
- **AI-First:** Laat Claude/Cursor heavy lifting doen
- **Copy-Paste OK:** Voor MVP snelheid > perfectie
- **Error Handling:** User-friendly messages overal
- **Security:** API keys server-side, RLS in Supabase
---
## 3. Epics & Stories Overzicht
🎯 **Doel:** 8 duidelijke epics voor 4-weken development sprint - **Marketing First Strategy**.
| Epic ID | Titel | Doel | Status | Story Count | Week |
|---------|-------|------|--------|-------------|------|
| **WEEK 1 - FOUNDATION & MARKETING** |||||
| E0 | Project Setup | Next.js + Supabase + Vercel running | 🔄 In Progress (60%) | 5 | 1 |
| E1 | Marketing Website | Landing + build log + lead capture | ⏳ To Do | 6 | 1 |
| **WEEK 2 - EPD CORE** |||||
| E2 | Database & Auth | Schema + RLS + demo users | ⏳ To Do | 4 | 2 |
| E3 | Core UI & Client Module | Layout + Client CRUD + Navigation | ⏳ To Do | 5 | 2 |
| **WEEK 3 - AI MAGIC** |||||
| E4 | Intake & AI Integration | TipTap + Claude API + Prompts | ⏳ To Do | 6 | 3 |
| E5 | Profile & Plan | DSM + behandelplan flows | ⏳ To Do | 4 | 3 |
| **WEEK 4 - POLISH & LAUNCH** |||||
| E6 | Onboarding System | Walkthrough + tooltips + help | ⏳ To Do | 4 | 4 |
| E7 | Performance & Launch | Optimization + demo prep | ⏳ To Do | 4 | 4 |
---
## 4. Epics & Stories (Uitwerking)
### Epic 0 Project Setup 🔄
**Epic Doel:** Development environment volledig operationeel.
| Story ID | Beschrijving | Acceptatiecriteria | Status | Story Points |
|----------|--------------|---------------------|--------|--------------|
| E0.S1 | Next.js 15 project init | App Router, TypeScript, dev server draait | ✅ Af | 2 |
| E0.S2 | Tailwind + shadcn setup | Custom theme, componenten installeren | 🔄 Gedeeltelijk | 3 |
| E0.S3 | Supabase project aanmaken | EU region, connection string werkend | ✅ Af | 2 |
| E0.S4 | GitHub repo + Vercel deploy | Auto-deploy on push, preview URLs | ✅ Af | 2 |
| E0.S5 | Environment variables | .env.local + Vercel secrets configured | ✅ Af | 1 |
**Technical Notes:**
- Supabase project ID: `dqugbrpwtisgyxscpefg`
- Deploy URL: `https://aispeedrun.vercel.app`
- Package manager: `pnpm` voor snelheid
**Implementation Status:**
- ✅ Next.js 15 + TypeScript initialized
- ✅ Tailwind CSS v3.4 + PostCSS configured
- ⏳ shadcn/ui: basis setup gedaan, componenten nog niet geinstaleerd
- ✅ Supabase clients (server + client) aangemaakt
- ⏳ Migrations folder aangemaakt, nog geen database schema
- ✅ Environment variables geconfigureerd
---
### Epic 1 Marketing Website ⏳
**Epic Doel:** Public facing website voor Software on Demand story - WEEK 1 PRIORITY.
| Story ID | Beschrijving | Acceptatiecriteria | Status | Story Points |
|----------|--------------|---------------------|--------|--------------|
| E1.S1 | Landing page hero | Comparison table, live counter, CTAs | ⏳ To Do | 5 |
| E1.S2 | Build metrics backend | Supabase table, API endpoint, tracking | ⏳ To Do | 3 |
| E1.S3 | Build log timeline | Week entries, expandable sections | ⏳ To Do | 3 |
| E1.S4 | ROI calculator | Interactive inputs, real-time calculation | ⏳ To Do | 3 |
| E1.S5 | Contact form + leads | Form validation, Supabase storage | ⏳ To Do | 2 |
| E1.S6 | Demo info page | Credentials, video embed, feature comparison | ⏳ To Do | 2 |
**Content Strategy Week 1:**
- **Day 1-2:** Landing page live → LinkedIn post "Building in public starts NOW"
- **Day 3-4:** Build log structure → LinkedIn post "Transparantie: alle uren en kosten"
- **Day 5-6:** ROI calculator → LinkedIn post "Bereken zelf: €100k vs €200"
- **Day 7:** Week 1 retrospective → LinkedIn post "Week 1: Marketing site in 30 uur"
**Implementation Details:**
```typescript
// Route structure (nog aanmaken)
/app
/(marketing)
/page.tsx // Landing page
/build-log/page.tsx // Timeline
/demo/page.tsx // Demo info
/how-it-works/page.tsx // Explainer + ROI
/contact/page.tsx // Lead capture
```
**Current Status:**
- ⏳ Standaard Next.js homepage nog in plaats
- ⏳ Geen marketing routes aangemaakt
- ⏳ Geen database tables voor build_metrics en leads
**Next Steps:**
1. Standaard homepage vervangen met Landing page
2. Marketing routes structure opzetten
3. Hero section component bouwen
4. Database schema aanmaken voor build_metrics
---
### Epic 2 Database & Auth
**Epic Doel:** Complete database schema met auth en demo data - WEEK 2 START.
| Story ID | Beschrijving | Acceptatiecriteria | Status | Story Points |
|----------|--------------|---------------------|--------|--------------|
| E2.S1 | Database schema creëren | 5 tables volgens TO, migrations | ⏳ To Do | 5 |
| E2.S2 | RLS policies implementeren | Secure by default, auth.uid() checks | ⏳ To Do | 3 |
| E2.S3 | Demo auth flow | Magic link login, demo users | ⏳ To Do | 3 |
| E2.S4 | Seed data script | 3+ clients met complete dossiers | ⏳ To Do | 2 |
**Database Tables:**
```sql
- clients (id, first_name, last_name, birth_date, client_id)
- intake_notes (id, client_id, content_json, content_text, ai_summary)
- problem_profiles (id, client_id, category, severity, rationale)
- treatment_plans (id, client_id, version, status, plan_json)
- ai_events (id, kind, request, response, duration_ms, cost_cents)
```
**Current Status:**
- ⏳ Supabase migrations folder leeg
- ⏳ Geen SQL schema aangemaakt
- ⏳ Geen RLS policies
---
### Epic 3 Core UI & Client Module
**Epic Doel:** Responsive layout met client management - WEEK 2 PARALLEL.
| Story ID | Beschrijving | Acceptatiecriteria | Status | Story Points |
|----------|--------------|---------------------|--------|--------------|
| E3.S1 | Layout skeleton | Topbar + sidebar + main content area | ⏳ To Do | 3 |
| E3.S2 | Navigation routing | /clients, /clients/[id] werkend | ⏳ To Do | 2 |
| E3.S3 | Client list view | Search, filter, pagination | ⏳ To Do | 3 |
| E3.S4 | Create client flow | Form validation, auto client-ID | ⏳ To Do | 2 |
| E3.S5 | Responsive design | Mobile + tablet + desktop perfect | ⏳ To Do | 3 |
**UX Principles:**
- Primary color: `#22C55E` (green-500)
- Mobile-first approach
- Keyboard shortcuts support
---
### Epic 4 Intake & AI Integration 🎯
**Epic Doel:** TipTap editor met Claude AI volledig werkend - WEEK 3 FOCUS.
| Story ID | Beschrijving | Acceptatiecriteria | Status | Story Points |
|----------|--------------|---------------------|--------|--------------|
| E4.S1 | TipTap editor setup | Rich text, auto-save, formatting | ⏳ To Do | 5 |
| E4.S2 | Claude API setup | Server-side calls, error handling | ⏳ To Do | 3 |
| E4.S3 | Intake summarization | 5-8 bullets, source highlighting | ⏳ To Do | 5 |
| E4.S4 | Problem extraction | DSM categories, severity scoring | ⏳ To Do | 5 |
| E4.S5 | B1 readability rewrite | Simplify language on demand | ⏳ To Do | 3 |
| E4.S6 | Cost tracking | Log tokens, estimate costs | ⏳ To Do | 2 |
**Prompt Engineering Week 3:**
```typescript
const SUMMARIZE_PROMPT = `
Vat het intakeverslag samen in 5-8 bullets.
Focus op: hoofdklacht, triggers, impact, context.
Schrijf neutraal, professioneel, Nederlands B1.
`;
const EXTRACT_PROMPT = `
Analyseer de intake en bepaal:
1. DSM-light categorie
2. Severity (laag, middel, hoog)
3. Rationale (2-3 zinnen)
`;
```
---
### Epic 5 Profile & Treatment Plan
**Epic Doel:** Complete workflow van intake naar behandelplan - WEEK 3 COMPLETION.
| Story ID | Beschrijving | Acceptatiecriteria | Status | Story Points |
|----------|--------------|---------------------|--------|--------------|
| E5.S1 | Problem profile UI | DSM cards, severity badges | ⏳ To Do | 3 |
| E5.S2 | Manual profile editing | Override AI suggestions | ⏳ To Do | 2 |
| E5.S3 | Treatment plan UI | Goals, interventions, timeline | ⏳ To Do | 3 |
| E5.S4 | Publish workflow | Concept → Published states | ⏳ To Do | 2 |
**DSM-Light Categories:**
- Stemming/Depressie
- Angst
- Gedrag/Impuls
- Middelen
- Cognitief
- Context/Psychosociaal
---
### Epic 6 Onboarding System
**Epic Doel:** Modern onboarding experience - WEEK 4 UX FOCUS.
| Story ID | Beschrijving | Acceptatiecriteria | Status | Story Points |
|----------|--------------|---------------------|--------|--------------|
| E6.S1 | Onboarding walkthrough | 5 steps, 3 minutes, react-joyride | ⏳ To Do | 5 |
| E6.S2 | Context tooltips | First-use hints, dismissable | ⏳ To Do | 3 |
| E6.S3 | Help icons system | On-demand help panels | ⏳ To Do | 2 |
| E6.S4 | Progress tracking | LocalStorage + Supabase sync | ⏳ To Do | 2 |
**Onboarding Features:**
- Welcome modal met skip optie
- Contextual tooltips bij eerste gebruik
- Help iconen op complexe features
- Progress tracking in localStorage
---
### Epic 7 Performance & Launch
**Epic Doel:** Production ready met perfecte demo - WEEK 4 FINALE.
| Story ID | Beschrijving | Acceptatiecriteria | Status | Story Points |
|----------|--------------|---------------------|--------|--------------|
| E7.S1 | Performance optimization | <3s loads, code splitting, lazy loading | ⏳ To Do | 3 |
| E7.S2 | Mobile responsive check | All screens perfect on mobile | ⏳ To Do | 2 |
| E7.S3 | Demo dry-run | Full 10-min demo zonder issues | ⏳ To Do | 2 |
| E7.S4 | Production deployment | Environment vars, monitoring setup | ⏳ To Do | 2 |
**Launch Checklist Week 4:**
- [ ] Performance audit (Lighthouse > 90)
- [ ] Mobile responsive check
- [ ] Demo script finalized
- [ ] LinkedIn announcement post ready
---
## 5. Kwaliteit & Testplan
🎯 **Doel:** MVP kwaliteit met focus op demo-stabiliteit.
### Test Strategy
| Type | Coverage | Priority | Tools |
|------|----------|----------|-------|
| Unit Tests | Business logic (80%) | Medium | Vitest |
| Integration | API endpoints | High | Supertest |
| E2E Tests | Happy paths | Critical | Playwright |
| Manual | Complete demo flow | Critical | Checklist |
### Demo Checklist
- [ ] Login werkt foutloos
- [ ] Client aanmaken < 10 seconden
- [ ] AI samenvatting < 5 seconden
- [ ] Behandelplan generatie < 10 seconden
- [ ] Alle UI elementen responsive
- [ ] Geen console errors
- [ ] Performance > 90 Lighthouse
---
## 6. Demo & Presentatieplan
🎯 **Doel:** Perfecte 10-minuten demo voor meerdere doelgroepen.
### Demo Scenario's
**A. GGZ Professional Demo (10 min)**
1. **Intro** (1 min): "Van 30 min documentatie naar 3 minuten"
2. **Live intake** (2 min): TipTap editor, real-time typing
3. **AI magic** (4 min): Samenvatting → Profiel → Plan
4. **ROI pitch** (2 min): Tijdsbesparing calculator
5. **Q&A** (1 min): "Hoe past dit in jullie workflow?"
**B. LinkedIn Audience Demo (5 min)**
1. **Problem** (30s): "Enterprise software is broken"
2. **Solution** (30s): "Software on Demand"
3. **Speed run** (2 min): Week 1-4 highlights
4. **Live product** (1 min): Quick tour
5. **CTA** (1 min): "Build YOUR software in 4 weeks"
**C. Tech Consultancy Pitch (15 min)**
1. **Market opportunity** (3 min): SaaS disruption
2. **Technical deep-dive** (5 min): Architecture choices
3. **Cost breakdown** (3 min): TCO analysis
4. **Case study** (3 min): EPD build metrics
5. **Partnership model** (1 min): White-label options
### Backup Plans
- **Plan A:** Live on aispeedrun.nl
- **Plan B:** Local development server
- **Plan C:** Recorded video (Loom)
- **Plan D:** Screenshots deck
---
## 6.5 Week 1: Marketing Website Implementation Guide
🎯 **Doel:** Marketing site live in 30 uur met directe LinkedIn content generatie.
### Day 1-2: Landing Page Foundation
**Focus:** Hero section + comparison table werkend
```typescript
// app/(marketing)/page.tsx
export default function LandingPage() {
return (
<main>
<HeroSection /> // "Software on Demand" pitch
<ComparisonTable /> // Traditional vs AI Speedrun
<ProblemSection /> // Why enterprise software fails
<SolutionSection /> // How we fix it
<LiveProofSection /> // Real-time metrics
<CTASection /> // Lead capture
</main>
)
}
```
**Key Components Day 1:**
- `HeroSection`: Animated counter, gradient background
- `ComparisonTable`: Responsive table met visual contrast
- `LiveMetricsDisplay`: Hardcoded initially, database later
**LinkedIn Post Day 1:**
"🚀 Building a €100k EPD for €200. Day 1: Marketing site live.
Traditional: 6 months planning. Us: 6 hours coding.
Follow along: [link]"
### Day 3-4: Build Log & Metrics
**Focus:** Transparantie dashboard + build tracking
```typescript
// Database schema for metrics
create table build_metrics (
week_number int unique,
development_hours decimal,
infrastructure_cost decimal,
ai_api_cost decimal,
features_completed text[],
blog_post_url text
);
// API endpoint
app/api/build-metrics/route.ts
```
**LinkedIn Post Day 3:**
"📊 Radical transparency: Every hour tracked, every euro counted.
Week 1: 12 hours, €35 costs so far.
Check our build log: [link]"
### Day 5-6: ROI Calculator & Lead Capture
**Focus:** Interactive calculator + contact form
```typescript
// components/marketing/ROICalculator.tsx
export function ROICalculator() {
const [hours, setHours] = useState(10)
const [rate, setRate] = useState(75)
const [users, setUsers] = useState(5)
const savings = hours * 4 * rate * users
const breakEven = 200 / (savings - 50)
return (
// Interactive sliders + real-time calculation
)
}
```
**LinkedIn Post Day 5:**
"💰 Calculate YOUR savings: Our ROI calculator is live.
Average result: 5400% ROI in year 1.
Try it: [link]"
### Day 7: Week 1 Retrospective
**Focus:** Polish + performance + retrospective post
**Checklist:**
- [ ] Lighthouse score > 90
- [ ] Mobile responsive perfect
- [ ] Form submissions working
- [ ] Analytics tracking active
- [ ] Week 1 metrics in database
**LinkedIn Post Day 7:**
"✅ Week 1 complete: Marketing site from 0 to production.
- 30 hours development
- €50 total costs
- 5 leads already
Next week: Building the actual EPD. Who's watching? 👀"
### Technical Deliverables Week 1:
1. **Routes Created:**
- `/` - Landing page
- `/build-log` - Timeline view
- `/demo` - Demo information
- `/how-it-works` - Explainer + ROI
- `/contact` - Lead form
2. **Database Tables:**
- `build_metrics` - Week tracking
- `leads` - Form submissions
3. **Components Library:**
- Marketing layout wrapper
- Metric cards
- Timeline entry
- ROI calculator
- Lead capture form
4. **Content Created:**
- 4 LinkedIn posts
- Landing page copy
- Demo video script
- Email templates
---
## 7. Risico's & Mitigatie
🎯 **Doel:** Proactief risicomanagement voor succesvolle launch.
| Risico | Kans | Impact | Mitigatie | Owner |
|--------|------|--------|-----------|-------|
| **TipTap complexiteit** | Hoog | Hoog | Start basic, incrementeel uitbreiden | Colin |
| **Claude API kosten** | Medium | Medium | Caching layer, response limits | Colin |
| **Vercel build limiet** | Laag | Hoog | Optimize bundle, lazy loading | Colin |
| **Demo timing (>10 min)** | Medium | Medium | Oefen 10x, timer visible | Colin |
| **LinkedIn algorithm change** | Laag | Medium | Multi-channel: Twitter/email | Colin |
| **Supabase RLS bugs** | Medium | Hoog | Extensive testing, fallback auth | Colin |
| **AI output inconsistent** | Hoog | Medium | Prompt versioning, examples | Colin |
| **Scope creep** | Hoog | High | Strict MVP focus, "Phase 2" list | Colin |
**Mitigatie Strategie:**
- Daily commits (ship small)
- Weekly LinkedIn updates (build momentum)
- Feature flags (disable broken features)
- Public repo (community help)
---
## 8. Evaluatie & Lessons Learned
🎯 **Doel:** Continue verbetering en kennisdeling.
### Week 1 Review (Te documenteren)
- [ ] Setup sneller/langzamer dan verwacht?
- [ ] Supabase vs Firebase trade-offs?
- [ ] shadcn/ui productivity boost?
### Week 2 Review
- [ ] TipTap learning curve?
- [ ] Client module complexiteit?
- [ ] UI/UX feedback van early testers?
### Week 3 Review
- [ ] Claude API betrouwbaarheid?
- [ ] Prompt engineering iterations?
- [ ] Performance bottlenecks?
### Week 4 Review
- [ ] Marketing site conversie?
- [ ] Demo feedback?
- [ ] Total hours vs estimate?
### Post-Launch Metrics
- **Development:** ___ uur totaal (target: 80-120)
- **Costs:** €___ totaal (target: <€200)
- **LinkedIn:** ___ followers gained
- **Leads:** ___ Software on Demand inquiries
- **Demo's:** ___ uitgevoerd
- **Media:** ___ mentions/articles
---
## 9. Referenties
🎯 **Doel:** Alle projectdocumentatie op één plek.
### Mission Control Documents
- **PRD v1.2** Product Requirements (Business & Marketing)
- **FO v2.0** Functioneel Ontwerp (Flows & Features)
- **TO v1.2** Technisch Ontwerp (Architecture & Database)
- **UX Stylesheet** Design System & Components
- **API Access** Endpoints & Authentication
### Project Resources
- **Repository:** `github.com/colinvanderheijden/aispeedrun`
- **Production:** `https://aispeedrun.nl`
- **Staging:** `https://aispeedrun-staging.vercel.app`
- **Supabase:** `app.supabase.com/project/dqugbrpwtisgyxscpefg`
- **LinkedIn Series:** `linkedin.com/in/colinvanderheijden`
### External Documentation
- [Next.js 15 Docs](https://nextjs.org/docs)
- [Supabase Docs](https://supabase.com/docs)
- [Claude API](https://docs.anthropic.com)
- [TipTap Editor](https://tiptap.dev)
- [Vercel Docs](https://vercel.com/docs)
---
## 10. Glossary & Abbreviations
| Term | Betekenis |
|------|-----------|
| **EPD** | Elektronisch Patiënten Dossier |
| **ECD** | Elektronisch Cliënten Dossier |
| **DSM** | Diagnostic and Statistical Manual |
| **GGZ** | Geestelijke Gezondheidszorg |
| **SMART** | Specifiek, Meetbaar, Acceptabel, Realistisch, Tijdgebonden |
| **RLS** | Row Level Security (Supabase) |
| **ISR** | Incremental Static Regeneration |
| **CTA** | Call To Action |
| **TCO** | Total Cost of Ownership |
| **MVP** | Minimum Viable Product |
| **B1** | Taal niveau (intermediate Dutch) |
---
## 11. Voortgang Samenvatting
### Huidige Status (15-11-2024)
- **Algemeen:** Project geïnitieerd, 10% compleet
- **Epic 0 (Project Setup):** 60% compleet - Basis infrastructure klaar, migrations nog leeg
- **Epic 1-7:** 0% compleet - Nog niet begonnen
### Voltooide Items
- ✅ Next.js 15 project initialized met App Router
- ✅ Tailwind CSS v3.4 + PostCSS configured
- ✅ Supabase project aangemaakt (dqugbrpwtisgyxscpefg)
- ✅ Supabase clients (server & browser) aangemaakt
- ✅ Environment variables setup
- ✅ GitHub repo initialized
- ✅ Vercel connected
### Lopende Werk
- 🔄 shadcn/ui setup completen
- 🔄 Database schema finaliseren
### Volgende Prioriteiten (Week 1)
1. ⏳ Standaard Next.js homepage vervangen
2. ⏳ Marketing routes setup
3. ⏳ Landing page hero section bouwen
4. ⏳ Database schema implementeren
5. ⏳ Supabase tables aanmaken met migrations
---
**Versiehistorie:**
| Versie | Datum | Auteur | Wijziging |
|--------|-------|--------|-----------|
| v1.0 | 15-11-2024 | Colin | Initiële versie op basis van PRD v1.2 + FO v2.0 + TO v1.2 |
| v1.1 | 15-11-2024 | Colin | Actualisering met huidige implementatiestatus en voortgang |

View File

@@ -1,608 +0,0 @@
# 🚀 Mission Control — Bouwplan Mini-EPD Prototype
**Projectnaam:** Mini-EPD Prototype
**Versie:** v1.0
**Datum:** 10-11-2025
**Auteur:** Development Team PinkRoccade GGZ
---
## 1. Doel en context
🎯 **Doel:** Een werkend mini-EPD prototype bouwen dat tijdens de AI-inspiratiesessie bij PinkRoccade GGZ de kernprocessen uit de GGZ demonstreert: **intake → probleemclassificatie → behandelplan**.
📘 **Toelichting:** Dit project focust op het zichtbaar maken van AI-waarde (samenvatten, structureren, plan genereren) in een herkenbare GGZ-workflow. De demo duurt maximaal 10 minuten en toont hoe AI zorgmedewerkers kan ondersteunen bij administratieve taken. Het systeem wordt gebouwd met fictieve data voor demonstratiedoeleinden.
**Belangrijkste doelen:**
- Demonstreren van AI-toegevoegde waarde in ECD-processen
- Herkenbare workflow voor GGZ-professionals
- Inspiratie bieden voor AI-integratie in bestaande systemen
- Direct bruikbare output (samenvattingen, behandelplannen) genereren
---
## 2. Uitgangspunten
### 2.1 Technische Stack
🎯 **Doel:** Complete technologie stack voor het mini-EPD prototype.
**Frontend:**
- **Framework:** Next.js 14+ (App Router)
- **Styling:** Tailwind CSS v3.4 (fallback vanaf v4 bij problemen)
- **UI Componenten:** shadcn/ui of eigen headless componenten
- **Rich Text Editor:** TipTap (ProseMirror basis)
- **Iconen:** lucide-react
- **State Management:** Zustand + React Context API
**Backend:**
- **API:** Next.js Route Handlers (server-side)
- **Database:** Supabase (PostgreSQL)
- **Auth:** Supabase Auth
- **Storage:** Supabase Storage
- **AI Integration:** Claude API (Anthropic)
**DevOps & Tooling:**
- **Hosting:** Vercel (EU region)
- **Version Control:** Git/GitHub
- **Type Safety:** TypeScript
- **Validation:** Zod
- **Testing:** Vitest (unit) + Playwright (E2E)
- **PDF Export (stretch):** Chromium via Playwright/Puppeteer
### 2.2 Projectkaders
🎯 **Doel:** Vaste kaders waarbinnen het project wordt ontwikkeld.
- **Tijd:** 3 weken totale bouwtijd voor MVP
- **Demo deadline:** Augustus 2025 (AI-inspiratiesessie)
- **Budget:** Beperkt voor externe API calls (Claude AI)
- **Team:** 1-2 developers + 1 consultant/product owner
- **Data:** Uitsluitend fictieve demo-data (geen productiegegevens)
- **Scope:** MVP features voor 10-minuten demo
- **Gebruikers:** Demo-users met volledige toegang (simplified auth)
- **Compliance:** Geen medische certificering vereist (demo only)
### 2.3 Programmeer Uitgangspunten
🎯 **Doel:** Code-kwaliteit principes en development best practices.
**Core Principles:**
- **DRY (Don't Repeat Yourself)**
- Herbruikbare React componenten in `/src/components/ui/`
- Shared utility functions in `/src/lib/utils/`
- Centrale API client voor Supabase queries
- Gedeelde prompt templates voor AI calls
- **SOC (Separation of Concerns)**
- UI componenten gescheiden van business logic
- Database queries in dedicated service layers (`/src/lib/services/`)
- AI prompts in `/src/lib/ai/prompts/`
- Styling via Tailwind classes, geen inline styles
- Route handlers voor server-side operaties
- **KISS (Keep It Simple, Stupid)**
- Directe Supabase queries zonder ORM overhead
- Eenvoudige state management met Zustand
- Minimale abstractie voor MVP scope
- Clear component naming (e.g., `ClientList`, `IntakeEditor`)
- **YAGNI (You Aren't Gonna Need It)**
- Geen multi-tenant setup voor demo
- Basis auth zonder rollenbeheer
- Skip complex caching voor MVP
- Geen realtime features voor eerste versie
- **Security**
- API keys alleen server-side (`ANTHROPIC_API_KEY`, `SUPABASE_SERVICE_ROLE_KEY`)
- Input sanitization met Zod schemas
- Row Level Security (RLS) policies in Supabase
- CORS configuratie voor API endpoints
- XSS protection via React's default escaping
---
## 3. Epics & Stories Overzicht
🎯 **Doel:** Complete overzicht van alle development epics met technische details.
| Epic ID | Epic Naam | Totaal Stories | Story Points | Status | Priority | Dependencies |
|---------|-----------|----------------|--------------|--------|----------|--------------|
| EP00 | Project Setup & Configuration | 5 | 13 | Not Started | Critical | - |
| EP01 | Database & Data Model | 4 | 21 | Not Started | Critical | EP00 |
| EP02 | Authentication & Authorization | 3 | 8 | Not Started | High | EP00, EP01 |
| EP03 | Client Management | 5 | 21 | Not Started | High | EP01, EP02 |
| EP04 | Intake Module | 6 | 34 | Not Started | Critical | EP03 |
| EP05 | Problem Profile (DSM-light) | 4 | 21 | Not Started | High | EP04 |
| EP06 | Treatment Plan Module | 5 | 34 | Not Started | High | EP05 |
| EP07 | AI Integration | 5 | 34 | Not Started | Critical | EP04 |
| EP08 | Dashboard & Navigation | 4 | 13 | Not Started | Medium | EP03 |
| EP09 | UI Components & Styling | 5 | 21 | Not Started | Medium | EP00 |
| EP10 | Testing & Quality Assurance | 4 | 13 | Not Started | High | All |
| EP11 | Deployment & Demo Prep | 4 | 13 | Not Started | Critical | All |
| EP12 | Stretch Features | 3 | 21 | Not Started | Low | EP06 |
**Totaal:** 57 stories | 257 story points
---
## 4. Epics & Stories (Uitwerking)
### Epic EP00 — Project Setup & Configuration
**Epic Doel:** Complete development omgeving met alle tools en dependencies geconfigureerd.
| Story ID | Story Description | Acceptance Criteria | Story Points | Status | Dependencies |
|----------|-------------------|---------------------|--------------|--------|--------------|
| EP00-ST01 | **Als developer wil ik een Next.js project opzetten zodat ik kan beginnen met development** | ✅ Next.js 14+ met App Router<br>✅ TypeScript configuratie<br>✅ Folder structuur volgens conventions<br>✅ Development server draait op localhost:3000 | 3 | Not Started | - |
| EP00-ST02 | **Als developer wil ik Tailwind CSS en UI libraries installeren zodat ik consistent kan stylen** | ✅ Tailwind CSS v3.4 werkend<br>✅ tailwind.config.ts met custom theme<br>✅ lucide-react icons beschikbaar<br>✅ shadcn/ui setup (of besluit voor custom) | 3 | Not Started | EP00-ST01 |
| EP00-ST03 | **Als developer wil ik Supabase project aanmaken zodat ik database en auth kan gebruiken** | ✅ Supabase project in EU region<br>✅ Connection string in .env.local<br>✅ Supabase client configured<br>✅ TypeScript types generation script | 3 | Not Started | EP00-ST01 |
| EP00-ST04 | **Als developer wil ik environment variables configureren zodat services veilig verbonden zijn** | ✅ .env.local met alle keys<br>✅ .env.example voor team<br>✅ Vercel environment variables<br>✅ Validation bij startup | 2 | Not Started | EP00-ST03 |
| EP00-ST05 | **Als developer wil ik Git repository opzetten zodat code versiebeheerd is** | ✅ GitHub repository<br>✅ .gitignore configuratie<br>✅ Branch protection rules<br>✅ Initial commit met setup | 2 | Not Started | EP00-ST01 |
**Technische implementatie details:**
- **Database:** Gebruik Supabase EU-region (Frankfurt/London)
- **Environment variables:**
```
NEXT_PUBLIC_SUPABASE_URL
NEXT_PUBLIC_SUPABASE_ANON_KEY
SUPABASE_SERVICE_ROLE_KEY
ANTHROPIC_API_KEY
```
- **Folder structuur:**
```
/src
/app (routes)
/components
/lib (utilities, services)
/types
```
---
### Epic EP01 — Database & Data Model
**Epic Doel:** Complete database schema met alle tabellen en relaties volgens TO specificatie.
| Story ID | Story Description | Acceptance Criteria | Story Points | Status | Dependencies |
|----------|-------------------|---------------------|--------------|--------|--------------|
| EP01-ST01 | **Als developer wil ik database tabellen creëren zodat data opgeslagen kan worden** | ✅ Tables: clients, intake_notes, problem_profiles, treatment_plans, ai_events<br>✅ Correct data types (UUID, JSONB, etc.)<br>✅ Foreign key constraints<br>✅ Timestamps (created_at, updated_at) | 8 | Not Started | EP00-ST03 |
| EP01-ST02 | **Als developer wil ik Row Level Security policies implementeren zodat data veilig is** | ✅ RLS enabled op alle tables<br>✅ Policies voor authenticated users<br>✅ Test queries werken correct<br>✅ Service role bypass werkt | 5 | Not Started | EP01-ST01 |
| EP01-ST03 | **Als developer wil ik database migrations opzetten zodat schema versiebeheerd is** | ✅ Supabase migrations folder<br>✅ Initial migration script<br>✅ Rollback mogelijk<br>✅ Documentation | 3 | Not Started | EP01-ST01 |
| EP01-ST04 | **Als developer wil ik demo data seeden zodat er test content beschikbaar is** | ✅ 3+ test cliënten<br>✅ Intake notes per cliënt<br>✅ Minimaal 1 compleet dossier<br>✅ Seed script: `npm run seed` | 5 | Not Started | EP01-ST01 |
**Technische implementatie details:**
- **Database Schema (zie TO §2.3):**
- `clients`: id (UUID), first_name, last_name, birth_date, created_at, updated_at
- `intake_notes`: id, client_id (FK), title, tag (CHECK), content_json (JSONB), content_text
- `problem_profiles`: id, client_id (FK), category (CHECK), severity (CHECK), remarks
- `treatment_plans`: id, client_id (FK), version, status (CHECK), plan (JSONB)
- `ai_events`: id, kind, client_id, request, response, duration_ms
- **RLS Policies (zie TO §2.4):**
```sql
CREATE POLICY "Allow all for authenticated users" ON [table]
FOR ALL USING (auth.uid() IS NOT NULL);
```
---
### Epic EP02 — Authentication & Authorization
**Epic Doel:** Werkende authenticatie met Supabase Auth voor demo gebruikers.
| Story ID | Story Description | Acceptance Criteria | Story Points | Status | Dependencies |
|----------|-------------------|---------------------|--------------|--------|--------------|
| EP02-ST01 | **Als gebruiker wil ik kunnen inloggen zodat ik toegang krijg tot het systeem** | ✅ Login pagina op /auth/login<br>✅ Email/password of magic link<br>✅ Session management<br>✅ Redirect naar dashboard | 3 | Not Started | EP00-ST03, EP01-ST02 |
| EP02-ST02 | **Als developer wil ik protected routes implementeren zodat alleen ingelogde users toegang hebben** | ✅ Middleware voor auth check<br>✅ Redirect naar login indien nodig<br>✅ Loading states tijdens auth<br>✅ Session refresh | 3 | Not Started | EP02-ST01 |
| EP02-ST03 | **Als gebruiker wil ik kunnen uitloggen zodat mijn sessie beëindigd wordt** | ✅ Logout button in header<br>✅ Session cleanup<br>✅ Redirect naar login<br>✅ Clear local state | 2 | Not Started | EP02-ST01 |
**Technische implementatie details:**
- **Auth flow:** Email/password voor demo (magic link als backup)
- **Middleware:** Check auth in `middleware.ts`
- **Protected routes:** Alles behalve `/auth/*`
- **Session:** Supabase JWT tokens
---
### Epic EP03 — Client Management
**Epic Doel:** Complete CRUD functionaliteit voor cliëntbeheer.
| Story ID | Story Description | Acceptance Criteria | Story Points | Status | Dependencies |
|----------|-------------------|---------------------|--------------|--------|--------------|
| EP03-ST01 | **Als behandelaar wil ik een cliëntenlijst zien zodat ik overzicht heb** | ✅ Tabel met: ClientID, Naam, Geboortedatum, Laatste update<br>✅ Zoekbalk voor naam/ID<br>✅ Pagination bij >20 items<br>✅ Loading skeleton | 5 | Not Started | EP01-ST01, EP02-ST02 |
| EP03-ST02 | **Als behandelaar wil ik een nieuwe cliënt aanmaken zodat ik kan starten met intake** | ✅ Modal/drawer met formulier<br>✅ Velden: Voornaam, Achternaam, Geboortedatum<br>✅ Auto-generated UUID<br>✅ Validatie met Zod<br>✅ Success toast | 5 | Not Started | EP03-ST01 |
| EP03-ST03 | **Als behandelaar wil ik cliëntgegevens bekijken zodat ik het dossier kan inzien** | ✅ Route: /clients/[id]<br>✅ Breadcrumb navigatie<br>✅ Tabs: Overzicht, Intakes, Profiel, Plan<br>✅ 404 handling | 5 | Not Started | EP03-ST01 |
| EP03-ST04 | **Als behandelaar wil ik cliëntgegevens bewerken zodat ik updates kan maken** | ✅ Edit mode in detail view<br>✅ Form validation<br>✅ Optimistic updates<br>✅ Error handling | 3 | Not Started | EP03-ST03 |
| EP03-ST05 | **Als developer wil ik Zustand store voor client state zodat data consistent blijft** | ✅ clientStore.ts setup<br>✅ Actions: setSelectedClient, updateClient<br>✅ Persistent state waar nodig<br>✅ TypeScript types | 3 | Not Started | EP00-ST01 |
**Technische implementatie details:**
- **API endpoints:**
- `POST /api/clients` - Create
- `GET /api/clients` - List with search
- `GET /api/clients/[id]` - Get single
- `PATCH /api/clients/[id]` - Update
- **Zustand store:** Central state voor selected client
- **Validatie:** Zod schemas voor alle forms
---
### Epic EP04 — Intake Module
**Epic Doel:** Rich text editor voor intake verslagen met TipTap integratie.
| Story ID | Story Description | Acceptance Criteria | Story Points | Status | Dependencies |
|----------|-------------------|---------------------|--------------|--------|--------------|
| EP04-ST01 | **Als behandelaar wil ik TipTap editor gebruiken zodat ik rijk opgemaakte notities kan maken** | ✅ TipTap met StarterKit<br>✅ Toolbar: Bold, Italic, Lists, etc.<br>✅ Placeholder text<br>✅ Content als ProseMirror JSON | 8 | Not Started | EP03-ST03 |
| EP04-ST02 | **Als behandelaar wil ik intake verslagen opslaan zodat ze bewaard blijven** | ✅ Save button + Ctrl/Cmd+S<br>✅ Store in intake_notes table<br>✅ Auto-save indicator<br>✅ Success/error toasts | 5 | Not Started | EP04-ST01 |
| EP04-ST03 | **Als behandelaar wil ik tags toevoegen aan verslagen zodat ik ze kan categoriseren** | ✅ Tag dropdown: Intake/Evaluatie/Plan<br>✅ Tag badge in lijst<br>✅ Filter op tag mogelijk<br>✅ Validation | 3 | Not Started | EP04-ST02 |
| EP04-ST04 | **Als behandelaar wil ik oude intakes bekijken zodat ik historie kan inzien** | ✅ Lijst van intakes per cliënt<br>✅ Sorteer op datum<br>✅ Click to view/edit<br>✅ Read-only mode optie | 5 | Not Started | EP04-ST02 |
| EP04-ST05 | **Als developer wil ik tekst extractie implementeren voor search** | ✅ Extract plain text van ProseMirror<br>✅ Store in content_text field<br>✅ Full-text search mogelijk<br>✅ Performance optimization | 5 | Not Started | EP04-ST02 |
| EP04-ST06 | **Als behandelaar wil ik de AI-rail zien zodat AI-resultaten preview kan bekijken** | ✅ Rechter paneel (40% breedte)<br>✅ Collapsible/expandable<br>✅ Preview area voor AI output<br>✅ Action buttons: Invoegen/Annuleren | 8 | Not Started | EP04-ST01 |
**Technische implementatie details:**
- **TipTap setup:**
```typescript
import StarterKit from '@tiptap/starter-kit'
const editor = useEditor({
extensions: [StarterKit],
content: prosemirrorJSON
})
```
- **Storage:** content_json (JSONB) + content_text (TEXT)
- **API:** `/api/intakes` endpoints
---
### Epic EP05 — Problem Profile (DSM-light)
**Epic Doel:** DSM-light categorisatie systeem met severity bepaling.
| Story ID | Story Description | Acceptance Criteria | Story Points | Status | Dependencies |
|----------|-------------------|---------------------|--------------|--------|--------------|
| EP05-ST01 | **Als behandelaar wil ik een probleem categorie selecteren zodat ik kan classificeren** | ✅ Dropdown met 6 categorieën (zie FO §4.4)<br>✅ Beschrijving per categorie<br>✅ Validation required field<br>✅ Store in problem_profiles | 5 | Not Started | EP04-ST02 |
| EP05-ST02 | **Als behandelaar wil ik severity aangeven zodat ernst duidelijk is** | ✅ Button group: Laag/Middel/Hoog<br>✅ Kleur-coded badges<br>✅ Hover tooltips met uitleg<br>✅ Required validation | 3 | Not Started | EP05-ST01 |
| EP05-ST03 | **Als behandelaar wil ik opmerkingen toevoegen zodat ik context kan geven** | ✅ Textarea voor vrije tekst<br>✅ Character limit (500)<br>✅ Optional field<br>✅ Markdown support | 3 | Not Started | EP05-ST01 |
| EP05-ST04 | **Als behandelaar wil ik AI-suggestie paneel gebruiken zodat classificatie sneller gaat** | ✅ Knop "AI > Analyseer intake"<br>✅ Suggestie paneel rechts<br>✅ Shows: categorie, severity, rationale<br>✅ Accepteer/Negeer buttons<br>✅ Source highlighting in intake (zie TO §5.4) | 10 | Not Started | EP04-ST02, EP07-ST03 |
**Technische implementatie details:**
- **Categorieën (enum):**
- stemming_depressie
- angst
- gedrag_impuls
- middelen_gebruik
- cognitief
- context_psychosociaal
- **Severity badges:** Tailwind classes volgens UX stylesheet
- **AI highlighting:** TipTap Decorations API
---
### Epic EP06 — Treatment Plan Module
**Epic Doel:** Genereren en beheren van gestructureerde behandelplannen.
| Story ID | Story Description | Acceptance Criteria | Story Points | Status | Dependencies |
|----------|-------------------|---------------------|--------------|--------|--------------|
| EP06-ST01 | **Als behandelaar wil ik een behandelplan genereren zodat ik snel een opzet heb** | ✅ Knop "AI > Genereer behandelplan"<br>✅ Uses intake + profile als context<br>✅ Genereert 4 secties<br>✅ Loading state tijdens generatie | 10 | Not Started | EP05-ST01, EP07-ST04 |
| EP06-ST02 | **Als behandelaar wil ik doelen bewerken zodat ze SMART geformuleerd zijn** | ✅ Lijst van doelen (bullets)<br>✅ Inline editing mogelijk<br>✅ Add/remove doelen<br>✅ Regenerate per doel optie | 8 | Not Started | EP06-ST01 |
| EP06-ST03 | **Als behandelaar wil ik interventies specificeren zodat behandeling duidelijk is** | ✅ Interventie lijst<br>✅ Type + frequentie + duur<br>✅ Voorgestelde interventies<br>✅ Custom toevoegen | 5 | Not Started | EP06-ST01 |
| EP06-ST04 | **Als behandelaar wil ik meetmomenten plannen zodat voortgang gemeten wordt** | ✅ Timeline met meetmomenten<br>✅ Na X sessies format<br>✅ Evaluatie types<br>✅ Calendar integration (stretch) | 5 | Not Started | EP06-ST01 |
| EP06-ST05 | **Als behandelaar wil ik plan publiceren zodat het definitief wordt** | ✅ Concept vs Gepubliceerd status<br>✅ Versioning (v1, v2, etc.)<br>✅ Published timestamp<br>✅ Read-only na publicatie<br>✅ Nieuwe versie mogelijk | 6 | Not Started | EP06-ST02 |
**Technische implementatie details:**
- **Plan structuur (JSONB):**
```typescript
{
doelen: string[],
interventies: string[],
frequentie: string,
meetmomenten: string[]
}
```
- **Status flow:** concept → gepubliceerd → nieuwe versie
- **API:** `/api/treatment-plan` endpoints
---
### Epic EP07 — AI Integration
**Epic Doel:** Claude AI integratie voor alle AI-powered features.
| Story ID | Story Description | Acceptance Criteria | Story Points | Status | Dependencies |
|----------|-------------------|---------------------|--------------|--------|--------------|
| EP07-ST01 | **Als developer wil ik Claude API client configureren zodat AI calls mogelijk zijn** | ✅ Anthropic SDK setup<br>✅ Server-side only implementation<br>✅ Error handling<br>✅ Rate limiting logic | 5 | Not Started | EP00-ST04 |
| EP07-ST02 | **Als behandelaar wil ik intake samenvatten met AI zodat ik snel overzicht heb** | ✅ Endpoint: /api/ai/summarize<br>✅ 5-8 bullet points output<br>✅ Nederlands, klinisch neutraal<br>✅ Max 5 sec response time | 8 | Not Started | EP07-ST01, EP04-ST06 |
| EP07-ST03 | **Als behandelaar wil ik problemen extraheren met AI zodat classificatie sneller gaat** | ✅ Endpoint: /api/ai/extract<br>✅ Returns: category, severity, rationale<br>✅ Source sentences identificatie<br>✅ Highlighting support | 8 | Not Started | EP07-ST01 |
| EP07-ST04 | **Als behandelaar wil ik behandelplan genereren met AI zodat ik een goede basis heb** | ✅ Endpoint: /api/ai/generate-plan<br>✅ SMART doelen formulering<br>✅ Evidence-based interventies<br>✅ Structured JSON output | 8 | Not Started | EP07-ST01 |
| EP07-ST05 | **Als developer wil ik AI events loggen zodat gebruik gemonitord wordt** | ✅ Store in ai_events table<br>✅ Track: prompt, response, duration<br>✅ Cost calculation<br>✅ Error logging | 5 | Not Started | EP07-ST01, EP01-ST01 |
**Technische implementatie details:**
- **Claude model:** claude-3-5-sonnet-20241022
- **Prompt templates:** `/src/lib/ai/prompts/`
- **Temperature:** 0.3 (deterministic)
- **Max tokens:** Per endpoint verschillend
- **Security:** API key alleen server-side
---
### Epic EP08 — Dashboard & Navigation
**Epic Doel:** Configureerbaar dashboard met tegels en navigatie.
| Story ID | Story Description | Acceptance Criteria | Story Points | Status | Dependencies |
|----------|-------------------|---------------------|--------------|--------|--------------|
| EP08-ST01 | **Als behandelaar wil ik een dashboard zien zodat ik overzicht heb per cliënt** | ✅ 5 tegels (zie FO §4.2)<br>✅ Responsive grid layout<br>✅ Data uit verschillende tables<br>✅ Click naar detail | 5 | Not Started | EP03-ST03 |
| EP08-ST02 | **Als behandelaar wil ik tegels configureren zodat ik kan personaliseren** | ✅ Settings icon → modal<br>✅ Checkboxes per tegel<br>✅ LocalStorage persistence<br>✅ Instant preview | 3 | Not Started | EP08-ST01 |
| EP08-ST03 | **Als gebruiker wil ik breadcrumb navigatie zodat ik weet waar ik ben** | ✅ Breadcrumb in header<br>✅ Clickable segments<br>✅ Current page highlight<br>✅ Responsive truncation | 2 | Not Started | EP03-ST03 |
| EP08-ST04 | **Als gebruiker wil ik sidebar navigatie zodat ik tussen modules kan wisselen** | ✅ Vertical navigation<br>✅ Active state indicator<br>✅ Icons + labels<br>✅ Collapsible op mobile | 3 | Not Started | EP03-ST03 |
**Technische implementatie details:**
- **Tegels:** Basisgegevens, Laatste Intake, Probleemprofiel, Behandelplan, Afspraken
- **Grid:** Tailwind Grid met responsive breakpoints
- **State:** Zustand voor tegel configuratie
---
### Epic EP09 — UI Components & Styling
**Epic Doel:** Consistente UI componenten volgens UX stylesheet.
| Story ID | Story Description | Acceptance Criteria | Story Points | Status | Dependencies |
|----------|-------------------|---------------------|--------------|--------|--------------|
| EP09-ST01 | **Als developer wil ik basis componenten bouwen zodat UI consistent is** | ✅ Button, Card, Input, Select<br>✅ Consistent met UX stylesheet<br>✅ TypeScript props<br>✅ Storybook (optional) | 5 | Not Started | EP00-ST02 |
| EP09-ST02 | **Als developer wil ik toast notificaties implementeren zodat feedback duidelijk is** | ✅ Success/Error/Info/Warning<br>✅ Auto-dismiss na 5 sec<br>✅ Queue multiple toasts<br>✅ Accessible (aria-live) | 3 | Not Started | EP09-ST01 |
| EP09-ST03 | **Als developer wil ik loading states implementeren zodat gebruiker weet dat er geladen wordt** | ✅ Skeleton loaders<br>✅ Spinners voor buttons<br>✅ Progress bars voor AI<br>✅ Consistent animation | 3 | Not Started | EP09-ST01 |
| EP09-ST04 | **Als developer wil ik formulier componenten maken zodat input consistent is** | ✅ Form wrapper met validation<br>✅ Error messages styling<br>✅ Required field indicators<br>✅ Help text support | 5 | Not Started | EP09-ST01 |
| EP09-ST05 | **Als developer wil ik dark mode ondersteunen (stretch) zodat gebruikers kunnen kiezen** | ✅ Theme toggle button<br>✅ System preference detect<br>✅ Persist preference<br>✅ All components support | 5 | Not Started | EP09-ST01 |
**Technische implementatie details:**
- **Kleuren:** Zie UX stylesheet (§2-4)
- **Component library:** shadcn/ui of custom
- **Icons:** lucide-react consistent gebruik
---
### Epic EP10 — Testing & Quality Assurance
**Epic Doel:** Comprehensive testing voor stabiele demo.
| Story ID | Story Description | Acceptance Criteria | Story Points | Status | Dependencies |
|----------|-------------------|---------------------|--------------|--------|--------------|
| EP10-ST01 | **Als developer wil ik unit tests schrijven zodat business logic getest is** | ✅ Vitest setup<br>✅ Utils & services tests<br>✅ 80% coverage /lib folder<br>✅ CI integration | 5 | Not Started | All features |
| EP10-ST02 | **Als developer wil ik E2E tests schrijven zodat kritieke flows werken** | ✅ Playwright setup<br>✅ Happy path: intake → profile → plan<br>✅ Error scenarios<br>✅ Cross-browser | 5 | Not Started | All features |
| EP10-ST03 | **Als team wil ik smoke tests uitvoeren zodat demo stabiel is** | ✅ Manual test checklist<br>✅ All features tested<br>✅ Performance acceptable<br>✅ No console errors | 2 | Not Started | All features |
| EP10-ST04 | **Als developer wil ik accessibility testen zodat app toegankelijk is** | ✅ Keyboard navigation<br>✅ Screen reader support<br>✅ WCAG AA contrast<br>✅ Focus management | 1 | Not Started | EP09 |
**Technische implementatie details:**
- **Test scenarios:** Zie FO §9 demo-scenario
- **Performance:** <3s initial load, <5s AI responses
- **Browser support:** Chrome, Firefox, Safari latest
---
### Epic EP11 — Deployment & Demo Prep
**Epic Doel:** Production-ready deployment en demo voorbereiding.
| Story ID | Story Description | Acceptance Criteria | Story Points | Status | Dependencies |
|----------|-------------------|---------------------|--------------|--------|--------------|
| EP11-ST01 | **Als developer wil ik Vercel deployment configureren zodat app live is** | ✅ Vercel project setup<br>✅ EU region (Amsterdam)<br>✅ Environment variables<br>✅ Custom domain (optional) | 3 | Not Started | All features |
| EP11-ST02 | **Als team wil ik demo data prepareren zodat presentatie smooth verloopt** | ✅ 3 complete test cliënten<br>✅ Realistic intake texts<br>✅ Pre-generated AI responses<br>✅ Backup data ready | 5 | Not Started | EP01-ST04 |
| EP11-ST03 | **Als presenter wil ik demo script hebben zodat presentatie gestructureerd is** | ✅ 10-minute script<br>✅ Key talking points<br>✅ Backup scenarios<br>✅ Q&A anticipatie | 3 | Not Started | All features |
| EP11-ST04 | **Als team wil ik dry-run doen zodat demo succesvol verloopt** | ✅ Complete run-through<br>✅ Timing verified (< 10 min)<br>✅ Technical issues fixed<br>✅ Feedback processed | 2 | Not Started | EP11-ST01 |
**Technische implementatie details:**
- **Deployment checklist:**
- Environment variables set
- Database migrations run
- Seed data loaded
- SSL certificate active
- Monitoring enabled
---
### Epic EP12 — Stretch Features (Optional)
**Epic Doel:** Extra features indien tijd beschikbaar.
| Story ID | Story Description | Acceptance Criteria | Story Points | Status | Dependencies |
|----------|-------------------|---------------------|--------------|--------|--------------|
| EP12-ST01 | **Als behandelaar wil ik afspraken kunnen plannen zodat agenda gekoppeld is** | ✅ Calendar view<br>✅ Create/edit appointments<br>✅ Link to client<br>✅ Dashboard widget | 8 | Not Started | EP08-ST01 |
| EP12-ST02 | **Als behandelaar wil ik PDF export zodat ik rapporten kan delen** | ✅ Export button<br>✅ Professional layout<br>✅ All sections included<br>✅ Download trigger | 8 | Not Started | EP06-ST05 |
| EP12-ST03 | **Als behandelaar wil ik leesbaarheid verbeteren met AI zodat tekst B1-niveau wordt** | ✅ Endpoint: /api/ai/readability<br>✅ B1 niveau output<br>✅ Preserve medical accuracy<br>✅ Preview before apply | 5 | Not Started | EP07-ST01 |
---
## 5. Kwaliteit & Testplan
🎯 **Doel:** Borging van kwaliteit voor stabiele demo.
### Test Types
| Test Type | Scope | Tools | Coverage Target |
|-----------|-------|-------|-----------------|
| Unit Tests | Services, utilities, validators | Vitest | 80% /lib folder |
| Integration Tests | API endpoints, database queries | Vitest + MSW | All critical endpoints |
| E2E Tests | Complete user flows | Playwright | 3 happy paths, 2 error paths |
| Performance Tests | Load time, API response | Lighthouse | LCP <2.5s, FID <100ms |
| Accessibility Tests | WCAG compliance | axe-core | AA compliance |
| Security Tests | Auth, XSS, SQL injection | Manual + automated | OWASP top 10 |
### Critical Test Scenarios
1. **New Client Flow**
- Create client → Add intake → Generate summary → Extract problems → Create plan
- Expected time: <2 minutes
- All data persisted correctly
2. **AI Integration Flow**
- Large intake text (2000+ words) → All AI features work
- Response time <5 seconds per call
- Graceful degradation if AI fails
3. **Error Handling**
- Network failure → Appropriate error messages
- Invalid input → Clear validation feedback
- AI timeout → Fallback behavior
### Demo Checklist
- [ ] Login with demo account works
- [ ] Create new client (auto-generated ID)
- [ ] Write intake with TipTap editor
- [ ] AI summarize returns Dutch bullets
- [ ] Problem extraction with highlighting
- [ ] Treatment plan generation (SMART goals)
- [ ] Publish plan (version 1)
- [ ] Dashboard shows all data correctly
- [ ] Navigation breadcrumbs work
- [ ] No console errors
- [ ] Performance acceptable (<3s loads)
- [ ] Mobile view responsive
---
## 6. Demo & Presentatieplan
🎯 **Doel:** Succesvolle 10-minuten demo tijdens AI-inspiratiesessie.
### Demo Timeline
| Time | Activity | Key Points | Backup Plan |
|------|----------|------------|-------------|
| 0:00-1:00 | **Intro** | Context mini-EPD, AI-toegevoegde waarde | Slides ready |
| 1:00-2:30 | **Nieuwe cliënt** | Quick entry, auto ClientID, immediate start | Pre-created client |
| 2:30-5:00 | **Intake + AI** | TipTap editor, AI summarize, source highlighting | Cached AI response |
| 5:00-7:00 | **Profile + Plan** | DSM categorization, AI-generated plan, SMART goals | Manual input ready |
| 7:00-8:30 | **Publiceren** | Version control, status change, dashboard update | Screenshots |
| 8:30-10:00 | **Q&A** | Interactive discussion, next steps | FAQ prepared |
### Technical Setup
- **Primary:** Live on Vercel (stable internet required)
- **Backup 1:** Local development server
- **Backup 2:** Recorded video demo
- **Backup 3:** Static screenshots
### Key Messages
1. AI vermindert administratieve last met 50%
2. Consistente kwaliteit van documentatie
3. Meer tijd voor cliëntcontact
4. Evidence-based suggesties
5. Privacy-first design (geen echte data)
---
## 7. Risico's & Mitigatie
🎯 **Doel:** Proactieve risico management voor succesvolle oplevering.
| Risico | Kans | Impact | Mitigatie | Owner |
|--------|------|--------|-----------|-------|
| **Claude API rate limits** | Hoog | Hoog | Response caching, queue implementation, fallback to OpenAI | Developer |
| **TipTap complexiteit** | Medium | Hoog | Start simple, incremental features, fallback to textarea | Developer |
| **Supabase RLS policies fout** | Medium | Hoog | Extensive testing, service role fallback, monitoring | Developer |
| **AI output inconsistent** | Hoog | Medium | Prompt versioning, temperature tuning, validation layer | Developer |
| **Demo internet uitval** | Laag | Hoog | Local setup ready, mobile hotspot backup, video recording | Presenter |
| **Tijd tekort voor features** | Medium | Medium | MoSCoW prioritization, MVP focus, stretch clearly marked | PM |
| **Browser compatibility** | Laag | Medium | Test on Chrome/Safari/Firefox, polyfills where needed | QA |
| **Performance issues** | Medium | Medium | Lazy loading, code splitting, CDN for assets | Developer |
| **Security vulnerability** | Laag | Hoog | Pen test, OWASP checklist, security headers | Developer |
---
## 8. Referenties
🎯 **Doel:** Koppeling naar alle relevante projectdocumentatie.
### Mission Control Documents
- **PRD** — [Product Requirements Document](./prd-mini-ecd.md) - Business requirements en scope
- **FO** — [Functioneel Ontwerp](./fo-mini-ecd.md) - User flows en functionele specificaties
- **TO** — [Technisch Ontwerp](./to-mini-ecd.md) - Architectuur en database design
- **UX/UI** — [Stylesheet](./ux-stylesheet.md) - Kleuren en design system
- **API** — [API Access Document](./api-acces-mini-ecd.md) - Endpoints en authenticatie
### External Resources
- **Repository:** `https://github.com/pinkroccade/mini-epd-prototype`
- **Deployment:** `https://mini-epd.vercel.app`
- **Supabase:** `https://app.supabase.com/project/[project-id]`
- **Claude AI:** `https://docs.anthropic.com/claude/reference`
- **TipTap Docs:** `https://tiptap.dev`
- **Next.js Docs:** `https://nextjs.org/docs`
### Development Resources
- **Component Library:** `https://ui.shadcn.com`
- **Icons:** `https://lucide.dev`
- **Tailwind:** `https://tailwindcss.com`
---
## 9. Technische Notities
### Database Queries Examples
```typescript
// Get client with full dossier
const { data: client } = await supabase
.from('clients')
.select(`
*,
intake_notes (*),
problem_profiles (*),
treatment_plans (*)
`)
.eq('id', clientId)
.single()
// Search clients
const { data: clients } = await supabase
.from('clients')
.select('*')
.ilike('last_name', `%${searchQuery}%`)
.order('updated_at', { ascending: false })
```
### AI Prompt Templates
```typescript
// Summarize prompt
const SUMMARIZE_PROMPT = `
Vat het onderstaande intake-verslag samen in 5-8 bullets.
Schrijf in Nederlands, klinisch neutraal, zonder persoonlijke informatie.
Intake verslag:
{intakeText}
`
// Extract problems prompt
const EXTRACT_PROMPT = `
Analyseer de intake en bepaal:
1. DSM-light categorie (kies uit: stemming_depressie, angst, gedrag_impuls, middelen_gebruik, cognitief, context_psychosociaal)
2. Severity (laag, middel, hoog)
3. Rationale (2-3 zinnen)
4. Bronzinnen uit de tekst
Intake:
{intakeText}
`
```
### Component Structure
```typescript
// Example component with proper typing
interface ClientCardProps {
client: Client
onClick?: (id: string) => void
isSelected?: boolean
}
export function ClientCard({ client, onClick, isSelected }: ClientCardProps) {
return (
<Card
className={cn(
"cursor-pointer transition-shadow",
isSelected && "ring-2 ring-primary"
)}
onClick={() => onClick?.(client.id)}
>
<CardHeader>
<CardTitle>{client.first_name} {client.last_name}</CardTitle>
<CardDescription>
{format(new Date(client.birth_date), 'dd-MM-yyyy')}
</CardDescription>
</CardHeader>
</Card>
)
}
```
---
**Versiehistorie:**
| Versie | Datum | Auteur | Wijziging |
|--------|-------|--------|-----------|
| v1.0 | 10-11-2025 | Development Team | Initiële versie met complete epic breakdown |

File diff suppressed because it is too large Load Diff

1119
docs/specs/fo-mini-ecd-v2.md Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,448 @@
# 📄 Product Requirements Document (PRD)
**Product:** Mini-ECD Prototype
**Doel:** Demo tijdens AI-inspiratiesessie bij PinkRoccade GGZ + Live Build Serie
**Versie:** 1.2 (MVP met DSM-light simulatie + Onboarding + Marketing Site)
**Datum:** nov 2025
---
## 1. Doelstelling
**Primair doel:** Bewijzen dat **Software on Demand** de toekomst is door live te demonstreren hoe één developer met AI-tooling een werkend EPD bouwt in 4 weken voor €50/maand.
**Het contrast:**
- **Traditioneel:** Team van 5+ developers, €100k+ budget, 2 jaar implementatie
- **Software on Demand:** 1 developer + AI tools, €50/mnd, 4 weken
**De build als bewijs:** Via een **"Build in Public" LinkedIn-serie** tonen we elke week concrete voortgang. Het mini-ECD (intake → probleemclassificatie → behandelplan) dient als herkenbaar voorbeeld uit de GGZ-sector, maar de boodschap is universeel: **custom software is nu voor iedereen betaalbaar en snel leverbaar**.
**Secundair doel:** Positioneren van ikbenlit.nl als expert in Software on Demand en AI-gedreven development.
---
## 2. Doelgroep
**Primaire doelgroep (LinkedIn Build Serie):**
* **Ondernemers & MKB** → bewijzen dat custom software betaalbaar is
* **IT-managers & CTO's** → alternatief voor dure development teams
* **Startup founders** → snel MVP bouwen zonder €100k+ investment
* **Developers** → leren hoe AI-tooling development versnelt
**Secundaire doelgroep (EPD use case):**
* **GGZ-professionals** → herkenbaar voorbeeld, potentiële early adopters
* **Consultants** → inzicht in mogelijkheden voor hun klanten
**Tertaire doelgroep:**
* **Investeerders** → tonen van nieuwe development economics
* **Potentiële klanten ikbenlit.nl** → Software on Demand consultancy
---
## 3. Kernfunctionaliteiten (MVP)
### 3.1 EPD Core Features
1. **Cliënt inschrijven**
* Velden: Voornaam, Achternaam, Geboortedatum.
* Automatische ClientID.
* Verschijnt in Cliëntenlijst.
2. **Overzicht (Cliëntdashboard)**
* Tegels:
* Basisgegevens: ClientID, Naam, Geboortedatum.
* Intake: verkorte weergave laatste intakeverslag.
* Probleemprofiel: DSM-light categorie + severity-badge.
* Behandelplan: doelen in bullets + status.
* Afspraken: laatste afspraak + eerstvolgende 3 afspraken.
* Configuratie: gebruiker kan via een instellingen-knop kiezen welke tegels zichtbaar zijn.
3. **Intake-verslag maken**
* Rich text editor (TipTap).
* Tags: Intake / Evaluatie / Plan.
* Opslaan & koppelen aan cliënt.
4. **Probleemprofiel (DSM-light simulatie)**
* Dropdown categorieën (simulatie DSM-5 hoofdcategorieën):
* Stemming / Depressieve klachten
* Angststoornissen
* Gedrags- en impulsstoornissen
* Middelengebruik / Verslaving
* Cognitieve stoornissen
* Context / Psychosociaal
* Severity: Laag / Middel / Hoog.
* Vrij veld: opmerkingen.
* **AI-suggestie:** intake analyseren → voorstel categorie + severity.
5. **AI-ondersteuning bij verslag**
* Knoppen:
* *Samenvatten* (in bullets).
* *Verbeter leesbaarheid* (B1-niveau).
* *Extract problemen* (AI vult categorie/severity suggestie in).
6. **AI-voorstel behandelplan**
* Genereert secties: Doelen, Interventies, Frequentie/Duur, Meetmomenten.
* Gebruiker kan bewerken of accepteren.
7. **Mini-agenda (optioneel, stretch)**
* Afspraak plannen gekoppeld aan cliënt.
8. **Rapport export (stretch)**
* PDF: cliëntgegevens + intake + probleemprofiel + behandelplan.
### 3.2 Onboarding & UX Guidance (NIEUW)
**Doel:** Onderscheiden van legacy EPD's met slechte onboarding door slimme, context-aware begeleiding.
1. **Eenmalige Walkthrough**
* Start automatisch bij eerste login
* Skipbaar + opnieuw starten via user menu
* Stappen (3 minuten totaal):
1. Welkom + AI-waarde uitleg (15 sec)
2. Cliënt aanmaken (live demo, 45 sec)
3. Intake schrijven + AI samenvatten (60 sec)
4. Dashboard tonen (30 sec)
5. "Je bent klaar!" + link naar docs
2. **Context-aware Tooltips**
* Verschijnen automatisch bij eerste gebruik van complexe features
* Dismissable met "Toon niet meer" optie
* Voorbeelden:
* Eerste keer AI-knop → "AI kan je intake samenvatten in 5 seconden"
* Eerste keer DSM-dropdown → "Laat AI een suggestie doen op basis van intake"
* Eerste keer publiceren → "Dit maakt het plan definitief en verhoogt versienummer"
3. **Help-iconen op vaste plekken**
* Klein (?) icoontje naast complexe features
* Hover = korte tooltip, klik = uitgebreidere uitleg
* Locaties:
* DSM-light categorieën uitleg
* SMART doelen criteria
* Severity-bepaling richtlijnen
* AI-features (waarom/wanneer gebruiken)
**Technische basis:**
* State tracking in localStorage: `{ onboardingCompleted: boolean, tooltipsSeen: string[] }`
* Centraal config bestand voor alle guidance content
* Herbruikbare componenten: `<OnboardingProvider>`, `<Tooltip id="">`, `<HelpIcon topic="">`
* Library: react-joyride voor walkthrough
**Voordelen voor demo:**
* Direct contrast met "200-pagina PDF handleiding" van legacy systemen
* Zichtbaar verschil in gebruikerservaring
* Laat zien hoe moderne UX werkt
### 3.3 Marketing Website (Build in Public Hub)
**Doel:** Centrale hub voor LinkedIn Build Serie + lead generation voor Software on Demand consultancy.
**Structuur binnen zelfde Next.js app:**
1. **Landing Page** (`/`)
* **Hero Section:**
- "Software on Demand: Van idee naar werkend product in weken, niet maanden"
- Live counter: "Week X van 4 | Y uur development | €Z kosten"
- Comparison table: "Traditioneel vs. Software on Demand"
* **The Problem:**
- Enterprise software: €100k+ budgets, 2 jaar implementatie
- Vendor lock-in, rigide roadmaps, verouderde tech stacks
- Kleine bedrijven kunnen custom software niet betalen
* **The Solution:**
- AI-assisted development: 10x sneller, 95% goedkoper
- One-developer teams met AI tools = enterprise quality
- Pay-as-you-grow: €50/mnd start, scale when needed
* **Live Proof (EPD Example):**
- "Zie hoe we een €100k EPD bouwen voor €50/mnd"
- Real-time progress updates
- Transparante cost tracking
* **Stack Showcase:**
- Next.js + Claude AI + Supabase = modern foundation
- "Same tools big tech uses, now for small business"
* **CTA's:**
- Primary: "Volg de build op LinkedIn"
- Secondary: "Bespreek jouw Software on Demand project"
- Tertiary: "Probeer live demo"
2. **Build Log** (`/build-log`)
* **Week-by-week breakdown:**
- Week 1: "Foundation - 8 uur, €0 kosten"
- Week 2: "AI Integration - 12 uur, €25 API kosten"
- Week 3: "Core Features - 15 uur, €35 API kosten"
- Week 4: "Polish & Launch - 10 uur, €15 kosten"
* **Per entry:**
- What we built (features delivered)
- How we built it (tools, AI prompts, decisions)
- Time spent vs. traditional estimate
- Code snippets (educational value)
- Challenges & solutions (authenticity)
- LinkedIn post embedded
* **Running totals:**
- Total development hours
- Total costs (infrastructure + AI)
- Features completed
- Traditional estimate comparison
3. **Live Demo** (`/demo`)
* "Try it yourself" pitch
* Demo credentials (read-only access)
* Video walkthrough (2 min)
* Feature comparison with enterprise EPD's
* "This took 4 weeks. Traditional build: 24 months"
4. **Software on Demand Explained** (`/how-it-works`)
* What is Software on Demand
* When it makes sense (vs. SaaS, vs. traditional custom)
* Pricing model transparency
* Case study: EPD build breakdown
* ROI calculator (interactive)
5. **Request Your Build** (`/contact`)
* Lead capture form
* "Describe your software need in 3 sentences"
* Estimated timeline + cost preview
* Calendar booking for intake call
* Trust signals: LinkedIn recommendations, previous builds
**Content Strategy:**
* Wekelijkse LinkedIn post → immediate blog entry
* Radical transparency: share costs, time, failures
* Educational focus: teach while you build
* Open-source key components (drive traffic + credibility)
**Conversion Funnel:**
```
LinkedIn Post → Landing Page → Build Log → "Request Your Build"
Live Demo → Conviction → Contact
```
**Metrics Tracking:**
- Visitor source (LinkedIn, organic, direct)
- Time on build-log pages
- Demo usage (how many try it)
- Form submissions
- LinkedIn follower growth correlation
---
## 4. Build & Demo Flows
**Wekelijkse LinkedIn Build Flow:**
**Week 1: Foundation & First Intake**
1. Setup Next.js + Supabase + Claude API
2. Database schema + eerste cliënt aanmaken
3. Intake editor met TipTap werkend
4. **LinkedIn post:** "Van 0 naar werkende intake in 8 uur"
**Week 2: AI Integration**
1. AI samenvatting implementeren
2. Probleem extractie met source highlighting
3. DSM-light classificatie
4. **LinkedIn post:** "AI genereert samenvatting in 3 seconden vs. 30 minuten handmatig"
**Week 3: Treatment Planning**
1. Behandelplan generatie
2. SMART doelen formulering
3. Versioning & publicatie flow
4. **LinkedIn post:** "Complete behandelplan in 10 minuten vs. 2 uur traditioneel"
**Week 4: Polish & Launch**
1. Onboarding system
2. Dashboard met configureerbare tegels
3. Performance optimalisatie
4. **LinkedIn post:** "Van idee naar werkend product: 4 weken, €200 totaal"
**Live Demo Flow (voor geïnteresseerden):**
1. Login met demo credentials
2. Onboarding walkthrough (3 min)
3. Nieuwe cliënt → Intake → AI samenvatten (2 min)
4. Probleemprofiel met AI-suggestie (2 min)
5. Behandelplan genereren & publiceren (2 min)
6. Dashboard tonen met alle data (1 min)
**Totaal: 10 minuten hands-on**
---
## 5. Niet in scope
* Autorisaties en rollenbeheer (demo auth only).
* Externe koppelingen (Teams, TOPdesk, etc.).
* Volledige DSM-5 implementatie (alleen simulatie).
* Dit prototype is geen gevalideerd medisch hulpmiddel en dient enkel voor demonstratiedoeleinden.
* Marketing website SEO optimalisatie (fase 1).
* Analytics/tracking op marketing site (tenzij simpel via Vercel Analytics).
---
## 6. Technische randvoorwaarden
* **Framework:** Next.js (App Router) - single repo voor marketing + EPD
* **Styling:** Tailwind CSS
* **Database:** Supabase (PostgreSQL)
* **AI:** Claude AI (Anthropic)
* **Hosting:** Vercel (EU region)
* **Onboarding:** react-joyride + custom tooltip system
* **Marketing:** Dezelfde Next.js app, `/marketing` routes
**Routing structuur:**
```
/app
/(marketing)
/page.tsx → Landing
/build-log/page.tsx → Timeline
/demo/page.tsx → Demo info
/(app)
/clients/... → Protected EPD
```
---
## 7. Succescriteria
**Bewijs van Software on Demand concept:**
* ✅ Werkend EPD gebouwd in max 4 weken part-time (80-120 uur totaal)
* ✅ Totale kosten ≤ €200 (infrastructure + AI API)
* ✅ Maandelijkse run-kosten ≤ €50
* ✅ Feature-pariteit met basis EPD flow (intake → plan)
* ✅ Performance vergelijkbaar met enterprise EPD's (<3s loads, <5s AI)
**LinkedIn Build Serie impact:**
* 🎯 Minimaal 250 LinkedIn volgers gedurende build
* 🎯 Gemiddeld 100+ likes per wekelijkse post
* 🎯 Minimaal 10 comments/post met inhoudelijke vragen
* 🎯 5+ shares per post (viral potential)
* 🎯 3+ media vermeldingen of podcast invites
**Business impact (ikbenlit.nl):**
* 💰 Minimaal 10 leads voor Software on Demand consultancy
* 💰 2+ contracten binnen 2 maanden na launch
* 💰 Case study gebruikt in minimaal 3 pitches
* 💰 Landing page conversie >5% (visitor → lead)
**Technische kwaliteit:**
* ⚙️ 0 critical bugs tijdens live demo's
* ⚙️ >80% code coverage op business logic
* ⚙️ Lighthouse score >90 op marketing site
* ⚙️ Mobile responsive op alle schermen
* ⚙️ WCAG AA toegankelijkheid
**Proof points voor messaging:**
* 📊 "X% sneller dan traditionele development"
* 📊 "Y% goedkoper dan enterprise EPD"
* 📊 "Z uur totale development tijd vs. W maanden traditioneel"
* 📊 "Maandelijkse kosten €50 vs. €X.000 enterprise licentie"
---
## 8. Risico's
**Build & Technical:**
* **Scope creep:** Blijf bij MVP features, geen "nice to have" tijdens 4 weken
* **AI-output inconsistent:** Prompt versioning + fallback strategies
* **Time underestimation:** Buffer 20% extra voor onverwachte issues
* **Claude API costs exceed budget:** Implement caching + rate limiting
**Marketing & Messaging:**
* **LinkedIn engagement laag:** Backup content strategie, paid promotion indien nodig
* **Verkeerde doelgroep bereikt:** A/B test messaging, refine targeting
* **Sceptici: "AI code is slechte code":** Show test coverage, performance metrics, live demo
* **Traditional developers defensive:** Frame als evolution, not replacement
**Business Impact:**
* **Geen leads binnen 2 weken:** Adjust CTA's, offer free consultation
* **Leads maar geen conversies:** Re-evaluate pricing/positioning
* **Concurrent bouwt sneller/goedkoper:** Emphasize quality + domain expertise
**Privacy & Compliance:**
* **Fictieve data lijkt te echt:** Disclaimer op elke pagina, obvious fake names
* **GDPR issues met LinkedIn tracking:** Comply with cookie consent, minimal tracking
**Mitigatie:**
- Weekly retrospective: wat werkt, wat niet
- Transparent over setbacks in build-log (authenticity)
- Pre-written backup posts if week goes badly
- Video demo backup if live demo fails
---
## 9. Roadmap (post-demo)
**EPD uitbreidingen:**
* Autorisaties en auditlog.
* Trendanalyse (stemming/voortgang).
* Integratie met PinkRoccade modules.
* Compliance en security uitbreiden.
**Marketing site:**
* SEO optimalisatie voor zoekwoorden
* Lead magnet (gratis "AI in Healthcare" whitepaper)
* Case study pagina met ROI berekening
* Video testimonials van demo deelnemers
* Newsletter signup voor wekelijkse updates
**LinkedIn serie vervolg:**
* Post-launch: "Wat we leerden" reflectie
* Cost breakdown transparantie
* Open-source delen van componenten
* Follow-up serie: "Van prototype naar productie"
---
## 10. Meetbare doelen
| Categorie | Metric | Target | Meetmoment |
|-----------|--------|--------|------------|
| **Build Efficiency** | Total development hours | ≤120h (part-time 4 wks) | Week 4 |
| **Build Efficiency** | Cost per feature | <€50/feature | Week 4 |
| **Build Efficiency** | Traditional estimate | >500h (proof of 4x speed) | Week 4 |
| **Cost Proof** | Total build cost | ≤€200 | Week 4 |
| **Cost Proof** | Monthly run cost | ≤€50 | Month 1-3 |
| **Cost Proof** | Cost vs enterprise EPD | >99% cheaper | Week 4 |
| **LinkedIn Impact** | Followers gained | 250+ | Week 4 |
| **LinkedIn Impact** | Avg post engagement | 100+ likes, 10+ comments | Per week |
| **LinkedIn Impact** | Share rate | 5+ shares/post | Per week |
| **LinkedIn Impact** | Profile views | 500+/week | Week 2-4 |
| **Lead Generation** | Software on Demand inquiries | 10+ | Within 2 weeks post-launch |
| **Lead Generation** | Qualified leads | 5+ | Within 4 weeks |
| **Lead Generation** | Conversion to contract | 2+ | Within 8 weeks |
| **Lead Generation** | Landing page conversion | >5% | Continuous |
| **Technical Quality** | Lighthouse performance | >90 | Week 4 |
| **Technical Quality** | Code coverage | >80% business logic | Week 4 |
| **Technical Quality** | Critical bugs | 0 | Week 4 |
| **Technical Quality** | API response time | <5s (AI), <1s (CRUD) | Week 4 |
| **Proof Validation** | Live demo success rate | >95% | Post-launch |
| **Proof Validation** | User onboarding completion | >70% | Month 1 |
| **Media Attention** | Podcast/interview invites | 3+ | Within 8 weeks |
| **Media Attention** | Blog/article mentions | 5+ | Within 12 weeks |
---
## 11. Stakeholders & Communicatie
| Stakeholder | Interesse | Communicatie | Priority |
|-------------|-----------|--------------|----------|
| **LinkedIn netwerk** | Software on Demand proof | Wekelijkse posts + live updates | Critical |
| **Potentiële klanten** | Custom software affordability | Landing page + demo + case study | Critical |
| **ikbenlit.nl prospects** | AI consultancy services | Website + LinkedIn + sales funnel | High |
| **Developers** | AI-assisted development learning | Build-log technical details + code snippets | Medium |
| **GGZ professionals** | EPD use case validation | Optional feedback, niet primary focus | Low |
| **Media/Podcasts** | Thought leadership | Press kit + interview availability | Medium |
| **Traditional dev agencies** | Market disruption awareness | Indirect via content, not confrontational | Low |
---
## Wijzigingslog
| Versie | Datum | Wijzigingen |
|--------|-------|-------------|
| 1.0 | aug 2025 | Initiële versie MVP |
| 1.1 | aug 2025 | DSM-light simulatie toegevoegd |
| 1.2 | nov 2025 | Onboarding system + Marketing website geïntegreerd, LinkedIn Build Serie strategie toegevoegd |

File diff suppressed because it is too large Load Diff

756
docs/templates/aispeedrun-manifesto.html vendored Normal file
View File

@@ -0,0 +1,756 @@
<!DOCTYPE html>
<html lang="nl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AI Speedrun - Het Software Manifesto</title>
<!-- Fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;900&family=Playfair+Display:wght@400;700;900&family=JetBrains+Mono:wght@400;600&display=swap" rel="stylesheet">
<style>
:root {
/* Core colors from UX stylesheet */
--primary-blue: #3B82F6;
--primary-blue-hover: #2563EB;
--green-accent: #16A34A;
--yellow-accent: #F59E0B;
--text-primary: #0F172A;
--text-secondary: #475569;
--background: #F8FAFC;
--surface: #FFFFFF;
--border-color: #E2E8F0;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
::selection {
background: var(--yellow-accent);
color: white;
}
body {
font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
color: var(--text-primary);
background: white;
overflow-x: hidden;
line-height: 1.6;
}
/* Manifesto Typography */
.manifesto-statement {
font-family: 'Inter', sans-serif;
font-weight: 900;
font-size: clamp(3rem, 8vw, 7rem);
line-height: 0.9;
letter-spacing: -0.04em;
text-transform: uppercase;
}
.manifesto-subtitle {
font-family: 'Playfair Display', serif;
font-weight: 400;
font-size: clamp(1.5rem, 3vw, 2.5rem);
line-height: 1.3;
font-style: italic;
}
.mono-accent {
font-family: 'JetBrains Mono', monospace;
font-weight: 600;
background: var(--yellow-accent);
color: white;
padding: 0.2em 0.4em;
white-space: nowrap;
}
/* Navigation - Minimal */
nav {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 1000;
padding: 2rem 3rem;
background: transparent;
mix-blend-mode: difference;
}
.nav-inner {
display: flex;
justify-content: space-between;
align-items: center;
max-width: 1600px;
margin: 0 auto;
}
.logo {
font-weight: 900;
font-size: 1.2rem;
color: white;
text-decoration: none;
letter-spacing: -0.02em;
}
.nav-action {
display: flex;
gap: 2rem;
align-items: center;
}
.nav-action a {
color: white;
text-decoration: none;
font-weight: 600;
font-size: 0.9rem;
text-transform: uppercase;
letter-spacing: 0.05em;
}
/* Opening Statement */
.opening {
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
background: var(--text-primary);
color: white;
position: relative;
overflow: hidden;
}
.opening::before {
content: '2024';
position: absolute;
top: -10%;
right: -5%;
font-size: 30rem;
font-weight: 900;
opacity: 0.03;
letter-spacing: -0.05em;
}
.opening-content {
max-width: 1200px;
padding: 4rem 2rem;
z-index: 1;
position: relative;
}
.opening .manifesto-statement {
margin-bottom: 2rem;
}
.opening .manifesto-subtitle {
opacity: 0.7;
max-width: 600px;
}
.scroll-indicator {
position: absolute;
bottom: 2rem;
left: 50%;
transform: translateX(-50%);
font-size: 0.8rem;
text-transform: uppercase;
letter-spacing: 0.1em;
opacity: 0.5;
animation: bounce 2s infinite;
}
@keyframes bounce {
0%, 100% { transform: translateX(-50%) translateY(0); }
50% { transform: translateX(-50%) translateY(-10px); }
}
/* The Problem Statement */
.problem {
padding: 8rem 2rem;
background: white;
}
.problem-content {
max-width: 1400px;
margin: 0 auto;
}
.problem-header {
margin-bottom: 6rem;
}
.problem-header h2 {
font-size: clamp(2.5rem, 6vw, 5rem);
font-weight: 900;
line-height: 1;
margin-bottom: 2rem;
letter-spacing: -0.03em;
}
.highlight-yellow {
background: linear-gradient(180deg, transparent 60%, var(--yellow-accent) 60%);
padding: 0 0.2em;
}
.problem-grid {
display: grid;
grid-template-columns: 1fr 1px 1fr;
gap: 4rem;
margin-bottom: 6rem;
position: relative;
}
.divider-vertical {
background: var(--border-color);
width: 1px;
height: 100%;
}
.problem-column h3 {
font-size: 1.8rem;
margin-bottom: 2rem;
font-weight: 700;
}
.problem-list {
list-style: none;
font-size: 1.1rem;
line-height: 2;
}
.problem-list li {
padding-left: 2rem;
position: relative;
margin-bottom: 0.5rem;
}
.problem-list li::before {
content: '→';
position: absolute;
left: 0;
color: var(--yellow-accent);
font-weight: 700;
}
/* Cost Statement */
.cost-statement {
background: var(--text-primary);
color: white;
padding: 4rem;
text-align: center;
position: relative;
overflow: hidden;
}
.cost-statement::after {
content: '€€€';
position: absolute;
bottom: -20%;
right: -5%;
font-size: 20rem;
opacity: 0.05;
font-weight: 900;
}
.cost-amount {
font-size: clamp(4rem, 10vw, 8rem);
font-weight: 900;
letter-spacing: -0.04em;
margin-bottom: 1rem;
}
/* Personal Story */
.story {
padding: 8rem 2rem;
background: var(--background);
}
.story-content {
max-width: 900px;
margin: 0 auto;
font-size: 1.3rem;
line-height: 1.8;
}
.story-content p {
margin-bottom: 2rem;
}
.story-highlight {
font-size: 2rem;
font-weight: 700;
color: var(--green-accent);
margin: 3rem 0;
text-align: center;
}
/* The Solution */
.solution {
padding: 8rem 2rem;
background: white;
}
.solution-header {
text-align: center;
margin-bottom: 6rem;
}
.solution-header h2 {
font-size: clamp(3rem, 7vw, 6rem);
font-weight: 900;
margin-bottom: 1rem;
background: linear-gradient(135deg, var(--primary-blue), var(--green-accent));
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.solution-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 3rem;
max-width: 1200px;
margin: 0 auto;
}
.solution-card {
padding: 2rem;
background: white;
border: 2px solid var(--border-color);
position: relative;
transition: all 0.3s;
}
.solution-card:hover {
border-color: var(--primary-blue);
transform: translateY(-5px);
}
.solution-number {
position: absolute;
top: -20px;
left: 20px;
background: var(--yellow-accent);
color: white;
width: 40px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
font-weight: 900;
font-size: 1.2rem;
}
/* Timeline */
.timeline {
padding: 8rem 2rem;
background: linear-gradient(135deg, var(--text-primary) 0%, #1e3a5f 100%);
color: white;
position: relative;
}
.timeline-content {
max-width: 1200px;
margin: 0 auto;
}
.week-blocks {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 2rem;
margin-top: 4rem;
}
.week-block {
background: rgba(255,255,255,0.1);
backdrop-filter: blur(10px);
padding: 2rem;
text-align: center;
position: relative;
border: 2px solid transparent;
transition: all 0.3s;
}
.week-block.active {
border-color: var(--yellow-accent);
background: rgba(255,255,255,0.15);
}
.week-number {
font-size: 3rem;
font-weight: 900;
opacity: 0.3;
margin-bottom: 1rem;
}
.week-block.active .week-number {
opacity: 1;
color: var(--yellow-accent);
}
/* Call to Action */
.cta-section {
padding: 12rem 2rem;
background: white;
text-align: center;
position: relative;
}
.cta-content h2 {
font-size: clamp(3rem, 8vw, 7rem);
font-weight: 900;
margin-bottom: 2rem;
line-height: 0.9;
letter-spacing: -0.04em;
}
.cta-buttons {
display: flex;
gap: 2rem;
justify-content: center;
margin-top: 4rem;
}
.btn-primary {
background: var(--primary-blue);
color: white;
padding: 1.5rem 3rem;
font-size: 1.2rem;
font-weight: 700;
text-decoration: none;
text-transform: uppercase;
letter-spacing: 0.05em;
transition: all 0.3s;
border: 3px solid var(--primary-blue);
}
.btn-primary:hover {
background: var(--primary-blue-hover);
transform: scale(1.05);
}
.btn-secondary {
background: transparent;
color: var(--text-primary);
padding: 1.5rem 3rem;
font-size: 1.2rem;
font-weight: 700;
text-decoration: none;
text-transform: uppercase;
letter-spacing: 0.05em;
transition: all 0.3s;
border: 3px solid var(--text-primary);
}
.btn-secondary:hover {
background: var(--text-primary);
color: white;
}
/* Footer */
footer {
padding: 4rem 2rem;
background: var(--text-primary);
color: white;
text-align: center;
}
.footer-content {
max-width: 800px;
margin: 0 auto;
}
.footer-content p {
opacity: 0.7;
margin-bottom: 1rem;
}
.signature {
margin-top: 2rem;
font-size: 1.2rem;
font-weight: 700;
}
/* Responsive */
@media (max-width: 768px) {
.problem-grid {
grid-template-columns: 1fr;
}
.divider-vertical {
display: none;
}
.week-blocks {
grid-template-columns: 1fr;
}
.cta-buttons {
flex-direction: column;
align-items: center;
}
}
/* Animations */
.fade-in {
opacity: 0;
animation: fadeIn 1s ease-out forwards;
}
@keyframes fadeIn {
to {
opacity: 1;
}
}
</style>
</head>
<body>
<!-- Minimal Navigation -->
<nav>
<div class="nav-inner">
<a href="#" class="logo">AI SPEEDRUN</a>
<div class="nav-action">
<a href="#manifesto">Manifesto</a>
<a href="#timeline">Build</a>
<a href="#demo">Demo →</a>
</div>
</div>
</nav>
<!-- Opening Statement -->
<section class="opening">
<div class="opening-content">
<h1 class="manifesto-statement">
Software<br>
is<br>
<span style="color: var(--yellow-accent);">Kapot.</span>
</h1>
<p class="manifesto-subtitle">
En iedereen weet het.
</p>
</div>
<div class="scroll-indicator">↓ Scroll</div>
</section>
<!-- The Problem -->
<section class="problem" id="manifesto">
<div class="problem-content">
<div class="problem-header">
<h2>
Ik werk al <span class="highlight-yellow">15 jaar</span> in de GGZ.
</h2>
<p style="font-size: 1.5rem; color: var(--text-secondary);">
PinkRoccade, Nedap, Zorgdomein, Caress—ik heb ze allemaal voorbij zien komen.
</p>
</div>
<div class="problem-grid">
<div class="problem-column">
<h3>De Belofte</h3>
<ul class="problem-list">
<li>€100.000/jaar licentiekosten</li>
<li>6 maanden implementatie</li>
<li>€50.000 setup & training</li>
<li>5-jarig contract</li>
<li>"Alles wat je nodig hebt"</li>
</ul>
</div>
<div class="divider-vertical"></div>
<div class="problem-column">
<h3>De Realiteit</h3>
<ul class="problem-list">
<li>Behandelaren haten de workflow</li>
<li>IT worstelt met integraties</li>
<li>200 features, 20 gebruikt</li>
<li>18 maanden voor een "kleine" aanpassing</li>
<li>Vendor lock-in tot in de eeuwigheid</li>
</ul>
</div>
</div>
<div class="cost-statement">
<div class="cost-amount">€500.000+</div>
<p style="font-size: 1.5rem;">Over 5 jaar. Voor software die niet past.</p>
</div>
</div>
</section>
<!-- Personal Story -->
<section class="story">
<div class="story-content">
<p>
<strong>Als behandelaar</strong> vulde ik formulieren in die niemand las.
</p>
<p>
<strong>Als product owner</strong> probeerde ik systemen te fixen die fundamenteel broken waren.
</p>
<p>
<strong>Als consultant</strong> zag ik organisaties worstelen met exact dezelfde problemen.
</p>
<div class="story-highlight">
"Dit moet toch sneller kunnen?"
</div>
<p style="text-align: center; font-size: 1.5rem;">
Telkens dezelfde vraag. Telkens hetzelfde antwoord: <strong>"Nee, zo werkt het nu eenmaal."</strong>
</p>
<p style="text-align: center; font-size: 2rem; font-weight: 900; color: var(--text-primary); margin-top: 3rem;">
Bullshit.
</p>
</div>
</section>
<!-- The Solution -->
<section class="solution">
<div class="solution-header">
<h2>NU KAN HET WEL</h2>
<p style="font-size: 1.5rem; color: var(--text-secondary);">
4 weken. €50/maand. Klaar.
</p>
</div>
<div class="solution-grid">
<div class="solution-card">
<span class="solution-number">1</span>
<h3 style="margin-bottom: 1rem; margin-top: 1rem;">AI-Powered Intake</h3>
<p>45 minuten gesprek → 2 minuten samenvatting</p>
<code class="mono-accent" style="display: inline-block; margin-top: 1rem;">WEEK 1</code>
</div>
<div class="solution-card">
<span class="solution-number">2</span>
<h3 style="margin-bottom: 1rem; margin-top: 1rem;">DSM-5 Suggesties</h3>
<p>Automatische diagnose-ondersteuning</p>
<code class="mono-accent" style="display: inline-block; margin-top: 1rem;">WEEK 2</code>
</div>
<div class="solution-card">
<span class="solution-number">3</span>
<h3 style="margin-bottom: 1rem; margin-top: 1rem;">Behandelplannen</h3>
<p>AI genereert, jij verfijnt</p>
<code class="mono-accent" style="display: inline-block; margin-top: 1rem;">WEEK 3</code>
</div>
<div class="solution-card">
<span class="solution-number">4</span>
<h3 style="margin-bottom: 1rem; margin-top: 1rem;">Live & Werkend</h3>
<p>Geen jarenlange implementatie</p>
<code class="mono-accent" style="display: inline-block; margin-top: 1rem;">WEEK 4</code>
</div>
</div>
</section>
<!-- Timeline -->
<section class="timeline" id="timeline">
<div class="timeline-content">
<h2 style="font-size: 3rem; font-weight: 900; margin-bottom: 1rem;">
Build in Public
</h2>
<p style="font-size: 1.3rem; opacity: 0.9;">
Geen geheimen. Alles op LinkedIn. Live.
</p>
<div class="week-blocks">
<div class="week-block active">
<div class="week-number">01</div>
<h3>Setup</h3>
<p style="opacity: 0.7;">Database, Auth, UI</p>
</div>
<div class="week-block active">
<div class="week-number">02</div>
<h3>AI Core</h3>
<p style="opacity: 0.7;">Claude integratie</p>
</div>
<div class="week-block">
<div class="week-number">03</div>
<h3>Workflows</h3>
<p style="opacity: 0.7;">Intake → Plan</p>
</div>
<div class="week-block">
<div class="week-number">04</div>
<h3>Launch</h3>
<p style="opacity: 0.7;">Live demo</p>
</div>
</div>
</div>
</section>
<!-- Call to Action -->
<section class="cta-section">
<div class="cta-content">
<h2>
Stop met<br>
<span style="color: var(--text-secondary);">wachten op</span><br>
verandering
</h2>
<p style="font-size: 1.5rem; max-width: 600px; margin: 2rem auto; color: var(--text-secondary);">
Bouw hem gewoon zelf. In 4 weken.
</p>
<div class="cta-buttons">
<a href="#demo" class="btn-primary">Watch Live Demo</a>
<a href="https://linkedin.com" class="btn-secondary">Volg de Build</a>
</div>
</div>
</section>
<!-- Footer -->
<footer>
<div class="footer-content">
<p>Dit is geen startup pitch.</p>
<p>Dit is geen vendor lock-in.</p>
<p>Dit is een statement.</p>
<div class="signature">
Colin Lindo<br>
<span style="opacity: 0.7; font-weight: 400;">15 jaar GGZ. 10 jaar development.</span><br>
<span style="color: var(--yellow-accent);">4 weken to change everything.</span>
</div>
</div>
</footer>
<script>
// Smooth scroll
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function (e) {
e.preventDefault();
const target = document.querySelector(this.getAttribute('href'));
if (target) {
target.scrollIntoView({
behavior: 'smooth',
block: 'start'
});
}
});
});
// Fade in on scroll
const observerOptions = {
threshold: 0.1,
rootMargin: '0px 0px -50px 0px'
};
const observer = new IntersectionObserver(entries => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('fade-in');
}
});
}, observerOptions);
document.querySelectorAll('.solution-card, .week-block').forEach(el => {
observer.observe(el);
});
</script>
</body>
</html>

View File

@@ -1,10 +1,4 @@
# 🚀 Mission Control — Bouwplan Template
💡 **Tip:** Dit document kun je samenstellen met hulp van AI-tools zoals **ChatGPT, Claude, Cursor** of **Gemini**.
Gebruik ze als **sparringpartner** om de bouw van je software te plannen, te documenteren en te verbeteren — zelfs als je geen ontwikkelaar bent.
Afhankelijk van de **complexiteit van je software** bepaal je zelf hoe gedetailleerd je elk onderdeel uitwerkt. Voor kleine prototypes volstaat een beknopt overzicht; voor grotere projecten kun je per fase en subfase inzoomen.
---
# 📄 Product Requirements Document (PRD) Template
**Projectnaam:** _[vul in]_
**Versie:** _v1.0_
@@ -13,357 +7,103 @@ Afhankelijk van de **complexiteit van je software** bepaal je zelf hoe gedetaill
---
## 1. Doel en context
🎯 **Doel:** Leg uit wat je gaat bouwen en waarom.
📘 **Toelichting:** Beschrijf kort de aanleiding voor het project en hoe het past binnen je organisatie of productstrategie. Verwijs hier naar het PRD of FO voor achtergrond.
## 1. Doelstelling
🎯 **Doel van deze sectie:** Beschrijf waarom dit product of prototype wordt gebouwd en wat het beoogde resultaat is.
📘 **Toelichting:** Geef een korte samenvatting van het *waarom* van dit project. Wat wil je aantonen, oplossen of verbeteren? Benoem ook of het om een demo, MVP of productieversie gaat.
**Voorbeeld:**
> Het doel is een werkend MVP te bouwen van de AI-assistent voor zorgdossiers. We tonen de meerwaarde van AI binnen de intake → profiel → plan workflow.
> Een werkend prototype dat de waarde van AI toont binnen het zorgdossierproces: intake → analyse → behandelplan. De focus ligt op snelheid, eenvoud en AI-toepasbaarheid.
---
## 2. Uitgangspunten
### 2.1 Technische Stack
🎯 **Doel:** Benoem de technologieën en frameworks die worden gebruikt.
📘 **Toelichting:** Denk aan frontend, backend, database, hosting en externe services.
## 2. Doelgroep
🎯 **Doel:** Schets wie de eindgebruikers, stakeholders en testers zijn.
📘 **Toelichting:** Omschrijf de primaire doelgroepen (bijv. zorgprofessionals, developers, managers) en hun belangrijkste behoeften of problemen. Vermeld eventueel personas of gebruikersscenarios.
**Voorbeeld:**
- **Frontend:** SvelteKit + Tailwind CSS + Lucide Icons
- **Backend:** Firebase Functions / Next.js API Routes
- **Database:** Firestore / PostgreSQL
- **AI/ML:** Vertex AI (Gemini) / OpenAI API
- **Hosting:** Vercel / Firebase Hosting
- **Auth:** Firebase Auth / Supabase Auth
> - **Product Owners & Managers:** inzicht in AI als hulpmiddel.
> - **Developers:** inspiratie voor AI-integratie.
> - **Zorgprofessionals:** herkenbare workflows met directe meerwaarde.
### 2.2 Projectkaders
🎯 **Doel:** Benoem de vaste kaders waarbinnen het project wordt ontwikkeld.
📘 **Toelichting:** Denk aan beperkingen (tijd, budget, resources) en aannames.
---
## 3. Kernfunctionaliteiten (MVP-scope)
🎯 **Doel:** Afbakenen van de minimale werkende functies.
📘 **Toelichting:** Maak een genummerde lijst van functies die in deze versie moeten werken. Beschrijf elke functie kort (input, output, interactie) en markeer *stretch-features* of optionele uitbreidingen.
**Voorbeeld:**
- **Tijd:** 3 weken bouwtijd voor MVP
- **Budget:** €X voor externe services (API calls, hosting)
- **Team:** 1 developer + 1 consultant/sparringpartner
- **Data:** Geen productiegegevens (alle data fictief voor demo)
- **Doel:** Demo op AI-inspiratiesessie
### 2.3 Programmeer Uitgangspunten
🎯 **Doel:** Vastleggen van code-kwaliteit principes en development best practices.
📘 **Toelichting:** Deze principes gelden voor alle code die in dit project wordt geschreven.
**Code Quality Principles:**
- **DRY (Don't Repeat Yourself)**
- Herbruikbare componenten en functies
- Centrale configuratie voor herhaalde waarden
- Utility functions voor gemeenschappelijke logica
- **KISS (Keep It Simple, Stupid)**
- Eenvoudige oplossingen boven complexe architectuur
- Duidelijke naamgeving (spreekt voor zich)
- Vermijd premature optimization
- **SOC (Separation of Concerns)**
- UI-componenten gescheiden van business logic
- API-calls in dedicated service layers
- Database queries in repository/model layers
- Styling gescheiden van functionaliteit
- **YAGNI (You Aren't Gonna Need It)**
- Bouw alleen wat nu nodig is
- Geen features "voor later"
- Iteratief uitbreiden op basis van feedback
**Development Practices:**
- **Code Organization**
- Consistent folder structure (`/components`, `/lib`, `/routes`, `/api`)
- Één component/functie per file waar logisch
- Index files voor clean imports
- **Error Handling**
- Try-catch blocks op alle async operaties
- User-friendly foutmeldingen in UI
- Logging van errors naar console/monitoring
- **Security**
- Nooit API keys in frontend code
- Input validation op alle user input
- Firestore/database rules voor data access control
- CORS configuratie voor API endpoints
- **Performance**
- Lazy loading waar mogelijk
- Debounce op search/input handlers
- Optimized images en assets
- Minimal bundle size (tree-shaking)
- **Testing**
- Unit tests voor kritieke business logic
- Integration tests voor API endpoints
- Smoke tests voor belangrijkste flows
- Manual testing checklist voor demo
- **Documentation**
- README met setup instructies
- Inline comments voor complexe logica
- JSDoc/TypeScript types voor public APIs
- Architecture Decision Records (ADR) voor belangrijke keuzes
**Voorbeeld implementatie:**
```typescript
// ❌ NIET - Violation of DRY
if (user.role === 'admin') { /* ... */ }
if (user.role === 'admin') { /* ... */ }
// ✅ WEL - DRY principle
const isAdmin = (user) => user.role === 'admin';
if (isAdmin(user)) { /* ... */ }
// ❌ NIET - Violation of SOC
<button onClick={() => {
fetch('/api/data').then(r => r.json()).then(data => {
setState(data);
});
}}>
Load
</button>
// ✅ WEL - SOC principle
// In /lib/api.ts
export const loadData = async () => {
const response = await fetch('/api/data');
return response.json();
};
// In component
<button onClick={handleLoad}>Load</button>
```
1. **Cliëntbeheer:** aanmaken, bekijken en selecteren.
2. **Intakeverslag:** rich text editor met AI-samenvatting.
3. **Probleemprofiel:** AI-extractie van categorie/severity.
4. **Behandelplan:** AI-genereerbare doelen/interventies.
5. *(Stretch)* PDF-export en mini-agenda.
---
## 3. Epics & Stories Overzicht
🎯 **Doel:** De bouw opdelen in logische epics (fases) met stories (subfases).
📘 **Toelichting:** Elke epic bevat het doel, afhankelijkheden en status. Stories zijn de uitvoerbare taken binnen een epic.
## 4. Gebruikersflows (Demo- of MVP-flows)
🎯 **Doel:** Laten zien hoe de gebruiker stap-voor-stap door het systeem gaat.
📘 **Toelichting:** Beschrijf 24 concrete "flows" in stappen (input → actie → resultaat).
**Epic Structuur:**
| Epic ID | Titel | Doel | Status | Stories | Opmerkingen |
|---------|-------|------|--------|---------|-------------|
| E0 | Setup & Configuratie | Repo, omgeving, dependencies | ✅ Gereed | 4 | Config getest |
| E1 | Data & Database | Datamodel en demo-data | 🔄 In Progress | 3 | Rules nog aanvullen |
| E2 | UI & Layout | Interface, navigatie, componenten | ⏳ To Do | 3 | Wireframes gereed |
| E3 | AI-integratie | AI endpoints en prompt engineering | ⏳ To Do | 3 | Test met Gemini model |
| E4 | Testing & Deploy | QA, demo prep en deployment | ⏳ To Do | 3 | |
**Voorbeeld:**
1. Nieuwe cliënt aanmaken → Intake invullen → AI-samenvatten.
2. Intake analyseren → AI-suggestie → Probleemprofiel genereren.
3. Profiel bevestigen → AI-behandelplan genereren → Publiceer v1.
---
## 4. Epics & Stories (Uitwerking)
🎯 **Doel:** Verdeel complexe epics in beheersbare stories voor meer overzicht.
📘 **Toelichting:** Je bepaalt zelf het detailniveau. Kleine projecten kunnen volstaan met 2-3 stories per epic; grotere implementaties kunnen tot 10 stories bevatten.
## 5. Niet in Scope
🎯 **Doel:** Duidelijk maken wat (nog) niet wordt gebouwd.
📘 **Toelichting:** Noem features of modules die bewust buiten deze versie vallen. Dit voorkomt ruis en scope creep.
### Epic 0 — Setup & Configuratie
**Epic Doel:** Werkende development omgeving met alle benodigde tools en dependencies.
| Story ID | Beschrijving | Acceptatiecriteria | Status | Afhankelijkheden | Story Points |
|----------|--------------|---------------------|--------|------------------|--------------|
| E0.S1 | Repository aanmaken | GitHub repo + lokale clone, `.gitignore` config | ✅ | — | 1 |
| E0.S2 | Project initialisatie | `npm create` draait, dev server start | ✅ | E0.S1 | 2 |
| E0.S3 | Dependencies installeren | Tailwind, Firebase, TypeScript geïnstalleerd | 🔄 | E0.S2 | 2 |
| E0.S4 | Environment variables | `.env.local` + Vercel vars geconfigureerd | ⏳ | E0.S3 | 1 |
**Technical Notes:**
- Gebruik `pnpm` voor snellere installs
- `.env.example` committen voor team onboarding
**Voorbeeld:**
> Rollenbeheer, koppelingen met externe systemen (Teams, ECD), productie-grade beveiliging.
---
### Epic 1 — Data & Database
**Epic Doel:** Werkend datamodel met seed data voor development en demo.
## 6. Succescriteria
🎯 **Doel:** Objectieve meetlat voor een geslaagde oplevering.
📘 **Toelichting:** Formuleer concrete, toetsbare criteria.
| Story ID | Beschrijving | Acceptatiecriteria | Status | Afhankelijkheden | Story Points |
|----------|--------------|---------------------|--------|------------------|--------------|
| E1.S1 | Datamodel ontwerpen | ERD/schema gedocumenteerd, collections defined | 🔄 | E0.S4 | 3 |
| E1.S2 | Security Rules implementeren | Firestore rules geschreven en getest | ⏳ | E1.S1 | 3 |
| E1.S3 | Demo-data seeden | 3+ testcliënten met complete intake data | ⏳ | E1.S1 | 2 |
**Technical Notes:**
- Collections: `clients`, `intakes`, `plans`, `ai_events`
- Demo user heeft `all access` voor development
- Seed script: `npm run seed`
**Voorbeeld:**
- Demo duurt ≤ 10 minuten.
- AI-output zichtbaar en bewerkbaar.
- Geen fouten bij standaardflows.
- Minimaal 1 live testgebruiker.
---
### Epic 2 — UI & Layout
**Epic Doel:** Gebruiksvriendelijke interface volgens UX/FO specificatie.
## 7. Risicos & Mitigatie
🎯 **Doel:** Risicos vroeg signaleren en plannen hoe ermee om te gaan.
📘 **Toelichting:** Beschrijf de belangrijkste risicos en hoe je ze voorkomt of opvangt.
| Story ID | Beschrijving | Acceptatiecriteria | Status | Afhankelijkheden | Story Points |
|----------|--------------|---------------------|--------|------------------|--------------|
| E2.S1 | Layout skelet bouwen | Topbalk + linker navigatie responsive | ⏳ | E1.S3 | 5 |
| E2.S2 | Component library setup | Herbruikbare buttons, cards, forms | ⏳ | E2.S1 | 3 |
| E2.S3 | Routing & navigatie | `/clients/[id]` structuur werkt, breadcrumbs | ⏳ | E2.S1 | 3 |
**Technical Notes:**
- shadcn/ui componenten of custom Tailwind components
- Keyboard shortcuts: Ctrl+S (save), Cmd+K (search)
- Mobile-first approach
**Voorbeeld:**
| Risico | Impact | Mitigatie |
|--------|---------|------------|
| AI-output inconsistent | Hoog | Prompts testen, fallback responses voorbereiden |
| Scope creep | Middel | Scope afbakenen in PRD en Mission Control |
| Privacy | Laag | Alleen demo-data gebruiken |
---
### Epic 3 — AI-integratie
**Epic Doel:** Werkende AI-features voor samenvatten, extraheren en plannen genereren.
## 8. Roadmap / Vervolg (Post-MVP)
🎯 **Doel:** Richting geven aan toekomstige uitbreidingen.
📘 **Toelichting:** Beschrijf logische vervolgstappen na de MVP.
| Story ID | Beschrijving | Acceptatiecriteria | Status | Afhankelijkheden | Story Points |
|----------|--------------|---------------------|--------|------------------|--------------|
| E3.S1 | Vertex AI configuratie | GCP project + SA key, test call succesvol | ⏳ | E0.S4 | 3 |
| E3.S2 | API endpoints bouwen | `/api/summarize`, `/extract`, `/plan` werken | ⏳ | E3.S1, E1.S3 | 8 |
| E3.S3 | Logging & monitoring | AI calls loggen naar `ai_events` collection | ⏳ | E3.S2 | 2 |
**Technical Notes:**
- Model: `gemini-1.5-pro` of `gemini-2.0-flash`
- Prompt templates in `/lib/prompts/`
- Error handling voor rate limits en API failures
- Response caching voor repeated calls
**Voorbeeld:**
- Rollen & rechtenbeheer
- Auditlog + versiebeheer
- Trendanalyse
- Integratie met bestaande zorgsystemen (PinkRoccade, Nedap, etc.)
---
### Epic 4 — Testing & Deployment
**Epic Doel:** Stabiele, geteste applicatie live op productie omgeving.
## 9. Bijlagen & Referenties
🎯 **Doel:** Bronnen koppelen voor context en consistentie.
📘 **Toelichting:** Verwijs naar ondersteunende documenten of interne kennisbestanden.
| Story ID | Beschrijving | Acceptatiecriteria | Status | Afhankelijkheden | Story Points |
|----------|--------------|---------------------|--------|------------------|--------------|
| E4.S1 | Smoke tests uitvoeren | Alle happy flows werken zonder crashes | ⏳ | E3.S3 | 3 |
| E4.S2 | Demo dry-run | Volledige demo in max 10 minuten | ⏳ | E4.S1 | 2 |
| E4.S3 | Productie deployment | Live op Vercel, environment vars gezet | ⏳ | E4.S2 | 2 |
**Technical Notes:**
- Test scenarios gedocumenteerd in `/docs/test-plan.md`
- Vercel deployment: EU region (Amsterdam)
- Rollback plan als deployment faalt
---
## 5. Kwaliteit & Testplan
🎯 **Doel:** vastleggen hoe de kwaliteit van het project wordt geborgd.
📘 **Toelichting:** Licht toe welke tests je uitvoert en hoe je weet dat de build stabiel is.
### Test Types
| Test Type | Scope | Tools | Verantwoordelijke |
|-----------|-------|-------|-------------------|
| Unit Tests | Business logic, utilities | Vitest / Jest | Developer |
| Integration Tests | API endpoints, database | Playwright / Supertest | Developer |
| Smoke Tests | Kritieke user flows | Manual checklist | QA / Developer |
| Performance Tests | Load times, API response | Lighthouse, Network tab | Developer |
| Security Tests | Auth, data access, XSS | Manual + OWASP checklist | Developer |
### Test Coverage Targets
- **Unit tests:** 80%+ coverage op `/lib` folder
- **Integration tests:** Alle API endpoints
- **Smoke tests:** 3 happy flows + 2 error scenarios
### Manual Test Checklist (voor demo)
- [ ] User kan inloggen
- [ ] Nieuwe cliënt aanmaken werkt
- [ ] Intake formulier opslaan werkt
- [ ] AI samenvatting genereert binnen 5 sec
- [ ] Behandelplan wordt gegenereerd
- [ ] Navigatie werkt zonder errors
- [ ] Mobile view is responsive
- [ ] Error states tonen user-friendly messages
---
## 6. Demo & Presentatieplan
🎯 **Doel:** beschrijven hoe de demo wordt gepresenteerd of getest.
📘 **Toelichting:** Vermeld wat je laat zien, wie betrokken is en welk scenario wordt gevolgd.
### Demo Scenario
**Duur:** 10 minuten
**Doelgroep:** Zorgorganisatie stakeholders + management
**Locatie:** Live op Vercel (backup: localhost)
**Flow:**
1. **Intro** (1 min): Context en doel van de AI-assistent
2. **Nieuwe cliënt** (2 min): Aanmaken + intake invullen
3. **AI in actie** (4 min):
- Samenvatting genereren
- Belangrijkste punten extractie
- Behandelplan voorstel
4. **Interactie** (2 min): Aanpassingen maken, opslaan
5. **Afsluiting** (1 min): Vragen + next steps
**Backup Plan:**
- Lokale versie klaar bij internet issues
- Pre-seeded data als AI API niet reageert
- Screenshots als complete fallback
---
## 7. Risico's & Mitigatie
🎯 **Doel:** risico's vroeg signaleren en voorzien van oplossingen.
📘 **Toelichting:** Gebruik dit als dynamische checklist.
| Risico | Kans | Impact | Mitigatie | Owner |
|--------|------|--------|-----------|-------|
| AI-output inconsistent | Hoog | Hoog | Snapshot tests, prompt versioning, fallback responses | Developer |
| API rate limits tijdens demo | Middel | Hoog | Caching, pre-warmed responses, backup data | Developer |
| Firebase regels te open | Middel | Hoog | Strikte rules voor productie, security audit | Developer |
| Tijdsdruk deadline | Hoog | Middel | Prioriteer MVP features, cut scope indien nodig | PM |
| Browser compatibility issues | Laag | Middel | Test op Chrome, Safari, Firefox | QA |
| Environment vars niet gezet | Middel | Hoog | `.env.example` + deployment checklist | DevOps |
---
## 8. Evaluatie & Lessons Learned
🎯 **Doel:** reflecteren op het proces en verbeteringen vastleggen.
📘 **Toelichting:** noteer inzichten na elke sprint of oplevering.
**Te documenteren na project:**
- Wat ging goed? Wat niet?
- Welke AI-tools waren het meest effectief?
- Welke prompts werkten het beste?
- Waar liepen we vertraging op?
- Wat doen we volgende keer anders?
- Herbruikbare componenten voor volgende projecten
---
## 9. Referenties
🎯 **Doel:** koppelen aan de overige Mission Control-documenten.
**Mission Control Documents:**
- **PRD** — Product Requirements Document
- **FO** — Functioneel Ontwerp
- **TO** — Technisch Ontwerp
- **UX/UI** — Design specificatie
- **API Access** — Authenticatie en endpoints documentatie
**External Resources:**
- Repository: `https://github.com/[org]/[project]`
- Deployment: `https://[project].vercel.app`
- Design: Figma link
- Documentation: `/docs` folder in repo
---
## 10. Glossary & Abbreviations
| Term | Betekenis |
|------|-----------|
| Epic | Grote feature of fase in development (bevat meerdere stories) |
| Story | Kleine, uitvoerbare taak binnen een epic |
| Story Points | Schatting van complexiteit (Fibonacci: 1, 2, 3, 5, 8, 13) |
| MVP | Minimum Viable Product |
| DRY | Don't Repeat Yourself |
| KISS | Keep It Simple, Stupid |
| SOC | Separation of Concerns |
| YAGNI | You Aren't Gonna Need It |
| SA | Service Account (GCP) |
| ADR | Architecture Decision Record |
---
**Versiehistorie:**
| Versie | Datum | Auteur | Wijziging |
|--------|-------|--------|-----------|
| v1.0 | [datum] | [naam] | Initiële versie |
**Voorbeeld:**
- FO (Functioneel Ontwerp)
- TO (Technisch Ontwerp)
- UX/UI-specificatie
- Mission Control / Build Plan
- API Access Document

43
lib/content/loader.ts Normal file
View File

@@ -0,0 +1,43 @@
/**
* Content Loader Utility
*
* Loads JSON content files from the content directory structure.
* Supports server-side loading with TypeScript type safety.
*
* @example
* ```ts
* const manifesto = await getContent<ManifestoContent>('nl', 'manifesto')
* ```
*/
export async function getContent<T>(
locale: string = 'nl',
file: string
): Promise<T> {
try {
const content = await import(`@/content/${locale}/${file}.json`)
return content.default as T
} catch (error) {
console.error(`Failed to load content: ${locale}/${file}.json`, error)
throw new Error(`Content not found: ${locale}/${file}.json`)
}
}
/**
* Type-safe content loader with fallback
*
* Returns default content if file is not found (useful for development)
*/
export async function getContentWithFallback<T>(
locale: string = 'nl',
file: string,
fallback: T
): Promise<T> {
try {
return await getContent<T>(locale, file)
} catch (error) {
console.warn(`Using fallback content for: ${locale}/${file}.json`)
return fallback
}
}

67
lib/supabase/README.md Normal file
View File

@@ -0,0 +1,67 @@
# Supabase Configuration
Deze folder bevat de Supabase client configuratie voor het Mini-EPD project.
## Bestanden
- **`client.ts`** - Client-side Supabase client (browser-safe, gebruikt anon key)
- **`server.ts`** - Server-side Supabase client (admin, gebruikt service role key)
- **`types.ts`** - TypeScript types (auto-gegenereerd uit database schema)
- **`index.ts`** - Export file voor makkelijke imports
## Gebruik
### Client-side (React components)
```typescript
import { supabase } from '@/lib/supabase'
// Voorbeeld: ophalen van clients
const { data, error } = await supabase
.from('clients')
.select('*')
```
### Server-side (API routes, Server Components)
```typescript
import { supabaseAdmin } from '@/lib/supabase/server'
// Voorbeeld: admin operatie
const { data, error } = await supabaseAdmin
.from('clients')
.insert({ ... })
```
## TypeScript Types Genereren
Na het aanmaken van database schema (EP01), run:
```bash
pnpm run types:generate
```
Dit genereert TypeScript types uit je Supabase database schema.
## Environment Variables
Zorg dat deze variabelen in `.env.local` staan:
```env
NEXT_PUBLIC_SUPABASE_URL=https://dqugbrpwtisgyxscpefg.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=...
SUPABASE_SERVICE_ROLE_KEY=...
```
## Security
⚠️ **Belangrijk:**
- `NEXT_PUBLIC_*` variabelen zijn zichtbaar in de browser
- `SUPABASE_SERVICE_ROLE_KEY` moet **NOOIT** naar de client worden gestuurd
- Gebruik `supabase` (client) voor frontend operaties
- Gebruik `supabaseAdmin` (server) alleen in API routes en Server Components
## Volgende Stappen
1. ✅ EP00-ST03: Supabase configuratie (Done)
2. ⏳ EP01-ST01: Database schema aanmaken
3. ⏳ EP01-ST02: Row Level Security policies
4. ⏳ EP02-ST01: Authentication implementeren

20
lib/supabase/client.ts Normal file
View File

@@ -0,0 +1,20 @@
import { createClient } from '@supabase/supabase-js'
const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL!
const supabaseAnonKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
if (!supabaseUrl || !supabaseAnonKey) {
throw new Error('Missing Supabase environment variables. Check your .env.local file.')
}
/**
* Supabase client for client-side operations.
* Uses anon key - safe for browser/frontend.
* Row Level Security (RLS) policies apply.
*/
export const supabase = createClient(supabaseUrl, supabaseAnonKey, {
auth: {
persistSession: true,
autoRefreshToken: true,
},
})

6
lib/supabase/index.ts Normal file
View File

@@ -0,0 +1,6 @@
// Export Supabase clients
export { supabase } from './client'
export { supabaseAdmin } from './server'
// Export types (will be generated later)
export type { Database } from './types'

25
lib/supabase/server.ts Normal file
View File

@@ -0,0 +1,25 @@
import { createClient } from '@supabase/supabase-js'
const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL!
const supabaseServiceRoleKey = process.env.SUPABASE_SERVICE_ROLE_KEY!
if (!supabaseUrl || !supabaseServiceRoleKey) {
throw new Error('Missing Supabase server environment variables. Check your .env.local file.')
}
/**
* Supabase client for server-side operations.
* Uses service role key - NEVER expose to client!
* Bypasses Row Level Security (RLS) - use with caution.
*
* Use this for:
* - API routes that need admin access
* - Database migrations/seeding
* - Server-side operations
*/
export const supabaseAdmin = createClient(supabaseUrl, supabaseServiceRoleKey, {
auth: {
autoRefreshToken: false,
persistSession: false,
},
})

View File

@@ -0,0 +1,33 @@
/**
* Test script to verify Supabase connection
* Run with: node --loader tsx lib/supabase/test-connection.ts
*/
import { supabase } from './client'
async function testConnection() {
console.log('🔗 Testing Supabase connection...')
try {
// Test basic connection
const { data, error } = await supabase.from('_prisma_migrations').select('*').limit(1)
if (error && error.code !== 'PGRST204') {
// PGRST204 = table doesn't exist yet, which is fine
console.log('⚠️ Connection works, but database schema not yet created')
console.log(' Run EP01 migrations to create tables')
} else {
console.log('✅ Supabase connection successful!')
}
// Show project info
const url = process.env.NEXT_PUBLIC_SUPABASE_URL
console.log(`📍 Project: ${url}`)
} catch (err) {
console.error('❌ Connection failed:', err)
process.exit(1)
}
}
testConnection()

39
lib/supabase/types.ts Normal file
View File

@@ -0,0 +1,39 @@
/**
* Supabase Database Types
*
* This file will be auto-generated from your Supabase schema.
* Run: pnpm run types:generate
*
* For now, this is a placeholder. Once you create your database schema (EP01),
* you can generate types using the Supabase CLI.
*/
export type Json =
| string
| number
| boolean
| null
| { [key: string]: Json | undefined }
| Json[]
export interface Database {
public: {
Tables: {
// Tables will be generated here after schema is created
[key: string]: {
Row: Record<string, unknown>
Insert: Record<string, unknown>
Update: Record<string, unknown>
}
}
Views: {
[_ in never]: never
}
Functions: {
[_ in never]: never
}
Enums: {
[_ in never]: never
}
}
}

6
lib/utils.ts Normal file
View File

@@ -0,0 +1,6 @@
import { clsx, type ClassValue } from "clsx"
import { twMerge } from "tailwind-merge"
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}

View File

@@ -6,23 +6,34 @@
"dev": "next dev --webpack",
"build": "next build --webpack",
"start": "next start",
"lint": "eslint"
"lint": "eslint",
"types:generate": "npx supabase gen types typescript --project-id dqugbrpwtisgyxscpefg > lib/supabase/types.ts"
},
"dependencies": {
"@react-three/drei": "^10.7.7",
"@react-three/fiber": "^9.4.0",
"@supabase/supabase-js": "^2.81.1",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"lucide-react": "^0.553.0",
"next": "16.0.1",
"next-themes": "^0.4.6",
"react": "19.2.0",
"react-dom": "19.2.0"
"react-dom": "19.2.0",
"tailwind-merge": "^3.4.0",
"tailwindcss-animate": "^1.0.7",
"three": "^0.181.1"
},
"devDependencies": {
"@tailwindcss/postcss": "^4",
"@types/node": "^20",
"@types/react": "^19",
"@types/react-dom": "^19",
"autoprefixer": "^10.4.21",
"autoprefixer": "^10.4.22",
"eslint": "^9",
"eslint-config-next": "16.0.1",
"postcss": "^8.5.6",
"tailwindcss": "^4",
"tailwindcss": "^3.4.18",
"typescript": "^5"
}
}

1287
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

6
postcss.config.js Normal file
View File

@@ -0,0 +1,6 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}

164
tailwind.config.ts Normal file
View File

@@ -0,0 +1,164 @@
import type { Config } from 'tailwindcss'
const config: Config = {
darkMode: 'class',
content: [
'./pages/**/*.{js,ts,jsx,tsx,mdx}',
'./components/**/*.{js,ts,jsx,tsx,mdx}',
'./app/**/*.{js,ts,jsx,tsx,mdx}',
'./src/**/*.{js,ts,jsx,tsx,mdx}',
'./lib/**/*.{js,ts,jsx,tsx,mdx}',
],
theme: {
extend: {
colors: {
// Base colors
background: 'var(--background)',
foreground: 'var(--foreground)',
card: {
DEFAULT: 'var(--card)',
foreground: 'var(--card-foreground)',
},
popover: {
DEFAULT: 'var(--popover)',
foreground: 'var(--popover-foreground)',
},
primary: {
DEFAULT: 'var(--primary)',
foreground: 'var(--primary-foreground)',
},
secondary: {
DEFAULT: 'var(--secondary)',
foreground: 'var(--secondary-foreground)',
},
muted: {
DEFAULT: 'var(--muted)',
foreground: 'var(--muted-foreground)',
},
accent: {
DEFAULT: 'var(--accent)',
foreground: 'var(--accent-foreground)',
},
destructive: {
DEFAULT: 'var(--destructive)',
},
ring: 'var(--ring)',
input: 'var(--input)',
// Custom base colors
'app-background': '#F8FAFC',
surface: '#FFFFFF',
'surface-sub': '#F1F5F9',
// Text colors
'text-primary': '#0F172A',
'text-secondary': '#475569',
// Borders
border: '#E2E8F0',
// Brand & Primary
brand: {
DEFAULT: '#3B82F6',
hover: '#2563EB',
active: '#1D4ED8',
subtle: '#EFF6FF',
},
// Neutral CTA
neutral: {
DEFAULT: '#334155',
hover: '#1F2937',
},
// Module accents
module: {
appointments: {
bg: '#E8F8EF',
accent: '#16A34A',
border: '#CDECDC',
},
meds: {
bg: '#FEF6DC',
accent: '#F59E0B',
border: '#F6E7B6',
},
labs: {
bg: '#FFEBDC',
accent: '#F97316',
border: '#FFD2B8',
},
},
// Status colors
success: {
DEFAULT: '#16A34A',
subtle: '#ECFDF5',
},
warning: {
DEFAULT: '#EAB308',
subtle: '#FEFCE8',
},
error: {
DEFAULT: '#DC2626',
subtle: '#FEF2F2',
},
info: {
DEFAULT: '#3B82F6',
subtle: '#EFF6FF',
},
// Severity badges (DSM-light)
severity: {
low: {
bg: '#E5E7EB',
text: '#374151',
},
medium: {
bg: '#FEF3C7',
text: '#92400E',
},
high: {
bg: '#FEE2E2',
text: '#991B1B',
},
},
// Form elements
field: {
bg: '#FFFFFF',
text: '#0F172A',
placeholder: '#94A3B8',
border: '#CBD5E1',
'border-hover': '#94A3B8',
focus: '#3B82F6',
disabled: {
bg: '#F1F5F9',
text: '#94A3B8',
border: '#E2E8F0',
},
},
},
boxShadow: {
'sm': '0 1px 2px rgba(15,23,42,0.06)',
'md': '0 2px 6px rgba(15,23,42,0.08)',
'lg': '0 8px 20px rgba(15,23,42,0.10)',
},
ringColor: {
DEFAULT: '#3B82F6',
},
ringWidth: {
DEFAULT: '2px',
},
borderRadius: {
lg: 'var(--radius)',
md: 'calc(var(--radius) - 2px)',
sm: 'calc(var(--radius) - 4px)',
},
},
},
plugins: [require('tailwindcss-animate')],
}
export default config