41 KiB
🚀 Mission Control — Bouwplan Mini-EPD
💡 Dit bouwplan beschrijft de implementatie van een FHIR-compliant Mini-EPD voor GGZ-instellingen. Het project volgt internationale standaarden (FHIR R4) en Nederlandse specificaties (MedMIJ, ZIBs) voor toekomstige interoperabiliteit.
Projectnaam: Mini-EPD Prototype Versie: v1.0 Datum: 21 november 2024 Auteur: Colin Lit (ikbenlit.nl)
1. Doel en context
🎯 Doel: Een werkend MVP bouwen van een Elektronisch Patiënten Dossier (EPD) voor GGZ-instellingen, volledig gebaseerd op FHIR R4 standaarden. Het systeem ondersteunt de complete workflow: intake → diagnostiek → behandelplan → monitoring.
📘 Context: Het Mini-EPD is gebouwd met toekomstige integratie in gedachten:
- MedMIJ: Patiënten kunnen hun dossier raadplegen via PGO-apps
- Koppeltaal: Integratie met eHealth apps voor behandelactiviteiten
- Landelijk Schakelpunt (LSP): Medicatie-uitwisseling met andere zorgverleners
Het datamodel bestaat uit 13 FHIR resources die samen het complete GGZ-traject ondersteunen, van aanmelding tot behandelplan, inclusief doelen, toestemmingen en waarschuwingen.
Referentie documenten:
docs/datamodel-documentatie.md- Volledige uitleg van het FHIR datamodeldocs/archive/schemas/20241121_fhir_ggz_schema.sql- Database schema implementatie (archived)
2. Uitgangspunten
2.1 Technische Stack
Frontend:
- Framework: Next.js 15 (App Router)
- Styling: Tailwind CSS
- UI Components: shadcn/ui + Lucide Icons
- State Management: React Context + Zustand (voor complexe state)
- Forms: React Hook Form + Zod validation
- Datum/Tijd: date-fns
Backend:
- Database: Supabase (PostgreSQL)
- Auth: Supabase Auth (met RLS policies)
- API: Next.js API Routes + Supabase Client
- Real-time: Supabase Realtime (optioneel)
Development & Deployment:
- Package Manager: pnpm
- TypeScript: Strict mode enabled
- Linting: ESLint + Prettier
- Version Control: Git + GitHub
- Hosting: Vercel
- Database Hosting: Supabase Cloud
Security:
- Row Level Security (RLS) op alle tabellen
- BSN encryptie met pgcrypto
- HTTPS/TLS voor alle communicatie
- Environment variables voor secrets
2.2 Projectkaders
Tijd:
- Fase 1 (MVP): 6-8 weken development
- Fase 2: +4 weken voor uitbreidingen
- Fase 3: +6 weken voor integraties (MedMIJ/Koppeltaal)
Team:
- 1-2 Full-stack developers
- 1 GGZ-consultant (domeinkennis)
- 1 UX designer (parttime)
Scope MVP (Fase 1):
- Behandelaren kunnen inloggen
- Cliënten aanmaken en beheren
- Intake registreren (Encounters)
- Diagnoses vastleggen (DSM-5)
- Observaties/ROM-metingen toevoegen
- Behandelplannen opstellen met doelen
- Waarschuwingen/flags beheren
- Documenten genereren en opslaan
Out of scope voor MVP:
- AI-assistentie voor intake
- MedMIJ/Koppeltaal integratie
- Medicatie voorschrijven (alleen registreren)
- Facturatie/declaratie
- Agenda/afspraken systeem
- Multi-tenancy (meerdere instellingen)
Data:
- Fictieve demo-data voor development
- Productiedata pas na security audit
- Privacy by design: alle BSN versleuteld
2.3 Programmeer Uitgangspunten
Code Quality Principles:
-
DRY (Don't Repeat Yourself)
- Herbruikbare React componenten in
/components/shared - Shared utilities in
/lib/utils - Database queries in
/lib/dbhelpers - Zod schemas hergebruiken voor forms en API validatie
- Herbruikbare React componenten in
-
KISS (Keep It Simple, Stupid)
- Start met Server Components (RSC) waar mogelijk
- Client Components alleen waar interactiviteit nodig is
- Directe Supabase queries boven complexe ORMs
- Flat component structure (vermijd over-nesting)
-
SOC (Separation of Concerns)
/app- Next.js routing en pages/components- React componenten (split:/ui,/features,/shared)/lib- Business logic, utilities, database helpers/types- TypeScript types en interfaces/styles- Globale styles (Tailwind in components)
-
YAGNI (You Aren't Gonna Need It)
- Bouw alleen FHIR resources die nodig zijn voor MVP
- Geen premature optimalisatie (caching, CDN, etc.)
- Start zonder real-time features (toevoegen als nodig)
Development Practices:
-
Code Organization
/app /(auth) # Auth routes (login, signup) /(dashboard) # Protected routes /clients # Cliënt overzicht /clients/[id] # Cliënt detail /api # API routes /components /ui # shadcn/ui components /features # Feature-specific components /shared # Shared components /lib /db # Supabase helpers /validations # Zod schemas /utils # Utilities /types # TypeScript definitions -
Error Handling
- Try-catch op alle async database calls
- Toast notifications voor user feedback
- Error boundaries voor React component crashes
- Structured logging naar console (development) en monitoring (production)
-
Security
- Alle Supabase queries via RLS policies
- Input sanitization met Zod schemas
- BSN encryption via database function
- No sensitive data in client-side code
- CORS properly configured
- Rate limiting op API routes
-
Performance
- Server Components by default
- Dynamic imports voor zware componenten
- Optimize images met next/image
- Database indexes op frequently queried fields
- Pagination voor lijsten (100 items max per page)
-
Testing
- Unit tests:
/libutilities en helpers - Integration tests: API routes
- E2E tests: Kritieke flows (Playwright)
- Manual testing checklist voor demo
- Unit tests:
-
Documentation
- README met setup instructies
- JSDoc voor public functions
- Inline comments voor FHIR-specifieke logica
- Database schema comments (al aanwezig in SQL)
TypeScript Conventions:
// ✅ FHIR-compliant type naming
type FHIRPatient = {
id: string;
identifier_bsn: string;
name_family: string;
name_given: string[];
birth_date: string;
gender: 'male' | 'female' | 'other' | 'unknown';
// ...
};
// ✅ Database helper pattern
export async function getPatientById(id: string): Promise<FHIRPatient | null> {
const { data, error } = await supabase
.from('patients')
.select('*')
.eq('id', id)
.single();
if (error) throw new Error(`Failed to fetch patient: ${error.message}`);
return data;
}
// ✅ Form validation with Zod
const patientSchema = z.object({
identifier_bsn: z.string().length(9, 'BSN must be 9 digits'),
name_family: z.string().min(1, 'Achternaam is verplicht'),
name_given: z.array(z.string()).min(1, 'Voornaam is verplicht'),
birth_date: z.string().date(),
gender: z.enum(['male', 'female', 'other', 'unknown']),
});
3. Epics & Stories Overzicht
🎯 Overzicht van alle development fases
| Epic ID | Titel | Doel | Status | Stories | Story Points | Opmerkingen |
|---|---|---|---|---|---|---|
| E0 | Setup & Configuratie | Repo, Next.js, Supabase, TypeScript | ⏳ To Do | 5 | 10 | Foundation |
| E1 | Database Migratie | Schema toepassen, seed data, RLS testen | ⏳ To Do | 4 | 13 | FHIR schema |
| E2 | Auth & Practitioners | Login, behandelaar profiel, session management | ⏳ To Do | 4 | 13 | Supabase Auth |
| E3 | Patients & Organizations | Cliënt CRUD, instelling setup | ⏳ To Do | 3 | 13 | Basis entities |
| E4 | Encounters & Intake | Contactmoment registratie, intake workflow | ⏳ To Do | 4 | 21 | Core workflow |
| E5 | Conditions & Diagnostiek | DSM-5 diagnoses, severity, verification | ⏳ To Do | 3 | 13 | Clinical data |
| E6 | Observations & Metingen | ROM-scores, risico's, vitale functies | ⏳ To Do | 4 | 21 | Metingen |
| E7 | Medications | Medicatie registratie, dosering, status | ⏳ To Do | 3 | 8 | Med tracking |
| E8 | Care Plans & Goals | Behandelplan, doelen, activiteiten | ⏳ To Do | 4 | 21 | Planning |
| E9 | Consents & Flags | Toestemmingen, waarschuwingen, AVG | ⏳ To Do | 4 | 13 | Compliance |
| E10 | Documents | Verslagen, brieven, PDF generatie | ⏳ To Do | 3 | 13 | Documenten |
| E11 | Dashboard & UX | Overview, navigatie, search, filters | ⏳ To Do | 5 | 21 | Interface |
| E12 | Testing & QA | Unit tests, E2E, security audit | ⏳ To Do | 4 | 13 | Quality |
| E13 | Deployment & Docs | Production deploy, gebruikersdocs | ⏳ To Do | 3 | 8 | Launch |
Totaal: 53 stories, ~200 story points (~8-10 weken @ 20-25 points/week)
4. Epics & Stories (Uitwerking)
Epic 0 — Setup & Configuratie
Epic Doel: Werkende development omgeving met Next.js, Supabase en alle tooling.
| Story ID | Beschrijving | Acceptatiecriteria | Status | Afhankelijkheden | Story Points |
|---|---|---|---|---|---|
| E0.S1 | Repository aanmaken | GitHub repo + lokale clone, .gitignore, README |
⏳ | — | 1 |
| E0.S2 | Next.js 15 project setup | npx create-next-app, TypeScript, App Router |
⏳ | E0.S1 | 2 |
| E0.S3 | Tailwind + shadcn/ui installeren | Tailwind config, shadcn init, theme setup | ⏳ | E0.S2 | 2 |
| E0.S4 | Supabase project aanmaken | Supabase project, connection string, env vars | ⏳ | E0.S2 | 3 |
| E0.S5 | Development tooling | ESLint, Prettier, Husky (pre-commit), VS Code config | ⏳ | E0.S3 | 2 |
Technical Notes:
- Next.js 15 met App Router (geen Pages Router)
- pnpm als package manager voor monorepo-ready setup
.env.localtemplate:NEXT_PUBLIC_SUPABASE_URL,NEXT_PUBLIC_SUPABASE_ANON_KEY,SUPABASE_SERVICE_ROLE_KEY- ESLint config:
next/core-web-vitals+ custom rules voor FHIR naming
Acceptance:
pnpm devstart development server- Tailwind werkt, shadcn componenten importeerbaar
- Supabase client connecteert zonder errors
Epic 1 — Database Migratie
Epic Doel: FHIR schema toegepast, RLS werkend, seed data aanwezig.
| Story ID | Beschrijving | Acceptatiecriteria | Status | Afhankelijkheden | Story Points |
|---|---|---|---|---|---|
| E1.S1 | SQL schema toepassen | 20241121_fhir_ggz_schema.sql uitvoeren in Supabase |
⏳ | E0.S4 | 3 |
| E1.S2 | TypeScript types genereren | supabase gen types → /types/supabase.ts |
⏳ | E1.S1 | 2 |
| E1.S3 | RLS policies testen | Verify auth users can only see own data | ⏳ | E1.S1 | 5 |
| E1.S4 | Seed data script | Demo practitioner, organization, 3 patients | ⏳ | E1.S2 | 3 |
Technical Notes:
- Migratie via Supabase Dashboard SQL Editor of CLI
- Verify ENUMs:
gender_type,encounter_status,condition_clinical_status, etc. - Test RLS: Create test user, verify row-level filtering works
- Seed script:
/lib/db/seed.tsmet faker.js voor realistische data
Acceptance:
- Alle 13 tabellen aanwezig met indexes
- RLS enabled op alle tabellen
- Seed data zichtbaar voor test user
FHIR Resources Coverage:
- ✅ Practitioners
- ✅ Organizations
- ✅ Patients
- ✅ Encounters
- ✅ Conditions
- ✅ Observations
- ✅ MedicationStatements
- ✅ CarePlans + Activities
- ✅ Goals
- ✅ Consents
- ✅ Flags
- ✅ DocumentReferences
Epic 2 — Auth & Practitioners
Epic Doel: Behandelaren kunnen inloggen en hun profiel beheren.
| Story ID | Beschrijving | Acceptatiecriteria | Status | Afhankelijkheden | Story Points |
|---|---|---|---|---|---|
| E2.S1 | Supabase Auth setup | Email/password login, session management | ⏳ | E1.S1 | 3 |
| E2.S2 | Login/signup flows | /login, /signup pages met forms |
⏳ | E2.S1 | 5 |
| E2.S3 | Practitioner profiel koppelen | Auto-create practitioner record on signup | ⏳ | E2.S2 | 3 |
| E2.S4 | Profiel pagina | View/edit: naam, BIG-nummer, kwalificaties | ⏳ | E2.S3 | 2 |
Technical Notes:
- Supabase Auth met email magic links of password
- Database trigger: On
auth.usersinsert → createpractitionersrecord - Middleware voor protected routes:
/app/(dashboard)layout - Session stored in cookies (httpOnly, secure)
Acceptance:
- User kan signup → email verify → login
- Practitioner record automatisch aangemaakt
- Protected routes redirecten naar login als unauthenticated
- Profiel edits saven naar database
Data Model:
// practitioners table
{
id: UUID (PK)
user_id: UUID (FK → auth.users)
identifier_big: string (BIG-nummer)
identifier_agb: string
name_given: string[]
name_family: string
qualification: string[] // ["GZ-psycholoog"]
telecom_email: string
active: boolean
}
Epic 3 — Patients & Organizations
Epic Doel: Cliënten CRUD operaties en organisatie management.
| Story ID | Beschrijving | Acceptatiecriteria | Status | Afhankelijkheden | Story Points |
|---|---|---|---|---|---|
| E3.S1 | Organization seed | Default organization voor development | ⏳ | E1.S4 | 2 |
| E3.S2 | Patients lijst pagina | /clients met tabel, search, filters |
⏳ | E2.S4 | 5 |
| E3.S3 | Patient CRUD | Create/Update/Delete patient + validatie | ⏳ | E3.S2 | 6 |
Technical Notes:
- Organizations: Minimaal 1 nodig voor MVP (later multi-tenant)
- Patients lijst: Paginatie (50 per page), search op naam/BSN
- BSN validatie: 11-proef check + encryptie via pgcrypto
- Patient form: Multi-step wizard (Personal → Address → Insurance → Emergency)
Acceptance:
- Default organization in seed data
- Lijst toont alle patients met search/filter
- Nieuwe patient toevoegen werkt met volledige validatie
- BSN opgeslagen encrypted (niet leesbaar in database)
Patient Form Fields:
Stap 1: Persoonlijke gegevens
- BSN (verplicht, 9 cijfers, 11-proef)
- Achternaam, voorvoegsel, voornamen
- Geboortedatum, geslacht
Stap 2: Contactgegevens
- Adres (straat, huisnummer, postcode, plaats)
- Telefoon, email
Stap 3: Verzekering
- Zorgverzekeraar
- Polisnummer
- Huisarts (naam + AGB-code)
Stap 4: Noodcontact
- Naam contactpersoon
- Relatie
- Telefoonnummer
Epic 4 — Encounters & Intake
Epic Doel: Registratie van contactmomenten en intake workflow.
| Story ID | Beschrijving | Acceptatiecriteria | Status | Afhankelijkheden | Story Points |
|---|---|---|---|---|---|
| E4.S1 | Encounter tijdlijn | /clients/[id] toont encounters chronologisch |
⏳ | E3.S3 | 5 |
| E4.S2 | Nieuw encounter formulier | Create encounter: type, datum, reden | ⏳ | E4.S1 | 5 |
| E4.S3 | Intake workflow | Guided form: anamnese, klachten, context | ⏳ | E4.S2 | 8 |
| E4.S4 | Encounter detail pagina | View/edit encounter + gekoppelde data | ⏳ | E4.S3 | 3 |
Technical Notes:
- Encounter types:
intake,diagnostiek,behandeling,follow-up,crisis - Status flow:
planned→in-progress→completed - Intake form: Vrije tekst velden + gestructureerde data
- Linking: Encounter → Conditions/Observations/Documents
Acceptance:
- Timeline toont encounters met status badges
- Nieuw encounter aanmaken met datum/tijd picker
- Intake form volledig invulbaar en opslaanbaar
- Detail pagina toont alle gekoppelde resources
Encounter Data Model:
{
id: UUID
status: 'planned' | 'in-progress' | 'completed' | ...
class_code: 'AMB' | 'IMP' | 'EMER'
type_code: 'intake' | 'diagnostiek' | 'behandeling'
patient_id: UUID (FK)
practitioner_id: UUID (FK)
period_start: DateTime
period_end?: DateTime
reason_display: string[]
notes: string (Markdown)
}
Epic 5 — Conditions & Diagnostiek
Epic Doel: DSM-5 diagnoses vastleggen met status en ernst.
| Story ID | Beschrijving | Acceptatiecriteria | Status | Afhankelijkheden | Story Points |
|---|---|---|---|---|---|
| E5.S1 | DSM-5 codes database | Seed DSM-5 codes (top 50 GGZ diagnoses) | ⏳ | E1.S4 | 3 |
| E5.S2 | Diagnose toevoegen | Form: select DSM-5, severity, status | ⏳ | E4.S4, E5.S1 | 5 |
| E5.S3 | Problemlijst pagina | /clients/[id]/conditions - active diagnoses |
⏳ | E5.S2 | 5 |
Technical Notes:
- DSM-5 codes: Aparte lookup tabel of JSON import
- ICD-10 mapping voor facturatie (later)
- Clinical status:
active,remission,resolved - Verification:
provisional,confirmed - Link diagnose aan encounter (wanneer gesteld)
Acceptance:
- Behandelaar kan diagnose selecteren uit DSM-5 lijst
- Ernst vastleggen: mild, moderate, severe
- Status updaten: active → remission → resolved
- Problemlijst toont alleen active/relapse conditions
DSM-5 Voorbeelden:
F32.2 - Depressieve episode, ernstig
F41.1 - Gegeneraliseerde angststoornis
F60.3 - Emotioneel instabiele persoonlijkheidsstoornis
F84.0 - Autismespectrumstoornis
F20.0 - Schizofrenie
Epic 6 — Observations & Metingen
Epic Doel: ROM-metingen, risico-inschattingen en observaties registreren.
| Story ID | Beschrijving | Acceptatiecriteria | Status | Afhankelijkheden | Story Points |
|---|---|---|---|---|---|
| E6.S1 | Observation types definiëren | ROM codes, risk types, vitals | ⏳ | E1.S4 | 3 |
| E6.S2 | ROM-meting toevoegen | PHQ-9, GAD-7, OQ-45 met score | ⏳ | E4.S4, E6.S1 | 5 |
| E6.S3 | Risico-inschatting | Suïcidaliteit, agressie, verwaarlozing | ⏳ | E6.S2 | 5 |
| E6.S4 | Observaties tijdlijn | Grafiek met ROM-scores over tijd | ⏳ | E6.S3 | 8 |
Technical Notes:
- Observation categories:
survey(ROM),social-history,exam,vital-signs - Value types:
quantity(numeric),string,boolean,codeableConcept - Interpretation:
H(high),L(low),N(normal) - Charting: Recharts of Chart.js voor trend visualisatie
Acceptance:
- Behandelaar kan ROM-vragenlijst invullen met scores
- Risico-inschatting opslaan met severity (low/medium/high)
- Timeline toont metingen chronologisch
- Grafiek toont PHQ-9 trend over tijd
ROM Vragenlijsten:
const romInstruments = [
{
code: 'PHQ-9',
display: 'Patient Health Questionnaire-9',
category: 'survey',
range: { min: 0, max: 27 },
interpretation: {
'0-4': 'Minimaal',
'5-9': 'Licht',
'10-14': 'Matig',
'15-19': 'Matig-ernstig',
'20-27': 'Ernstig'
}
},
{
code: 'GAD-7',
display: 'Generalized Anxiety Disorder-7',
category: 'survey',
range: { min: 0, max: 21 },
// ...
}
];
Epic 7 — Medications
Epic Doel: Medicatie gebruik registreren (geen voorschrijf-functionaliteit).
| Story ID | Beschrijving | Acceptatiecriteria | Status | Afhankelijkheden | Story Points |
|---|---|---|---|---|---|
| E7.S1 | ATC codes database | Seed veelgebruikte GGZ medicatie | ⏳ | E1.S4 | 2 |
| E7.S2 | Medicatie toevoegen | Form: naam, dosering, status, reden | ⏳ | E4.S4, E7.S1 | 3 |
| E7.S3 | Medicatielijst | /clients/[id]/medications - active meds |
⏳ | E7.S2 | 3 |
Technical Notes:
- MedicationStatement (niet MedicationRequest - geen voorschrijven)
- ATC codes: WHO classificatie (https://www.whocc.no/atc/)
- Status:
active,completed,stopped - Dosage: Vrije tekst + gestructureerde fields
Acceptance:
- Medicatie toevoegen uit lijst of vrije tekst
- Dosering vastleggen (bijv. "50mg 1x daags")
- Lijst toont alleen active medications
- Stop-reden registreren bij status change
Veelgebruikte GGZ Medicatie:
N06AB06 - Sertraline (SSRI)
N06AB04 - Citalopram (SSRI)
N06AX16 - Venlafaxine (SNRI)
N05BA01 - Diazepam (Benzodiazepine)
N06AA09 - Amitriptyline (TCA)
N05AH03 - Olanzapine (Antipsychoticum)
Epic 8 — Care Plans & Goals
Epic Doel: Behandelplannen opstellen met doelen en activiteiten.
| Story ID | Beschrijving | Acceptatiecriteria | Status | Afhankelijkheden | Story Points |
|---|---|---|---|---|---|
| E8.S1 | CarePlan wizard | Multi-step: diagnoses selecteren, doelen opstellen | ⏳ | E5.S3 | 8 |
| E8.S2 | Goals (doelen) beheren | SMART-doelen met target metrics | ⏳ | E8.S1 | 5 |
| E8.S3 | Activities toevoegen | Behandelactiviteiten: CGT, ROM, opdrachten | ⏳ | E8.S1 | 5 |
| E8.S4 | CarePlan overzicht | Dashboard met status, voortgang, timeline | ⏳ | E8.S3 | 3 |
Technical Notes:
- CarePlan addresses multiple Conditions
- Goals linked to CarePlan with target dates
- Activities: status flow
not-started→in-progress→completed - Koppeltaal-ready: Activities kunnen externe app referenties bevatten
Acceptance:
- Wizard leidt door behandelplan opstellen
- Doelen formuleren met meetbare criteria (SMART)
- Activiteiten toevoegen met frequentie en verantwoordelijke
- Overzicht toont voortgang per doel
CarePlan Voorbeeld:
Titel: "Behandelplan Depressie"
Status: active
Periode: 2024-01-01 → 2024-06-30
Diagnoses: [F32.2 - Depressie ernstig]
Doelen:
1. PHQ-9 score < 10 binnen 12 weken
2. Herstel dagelijks functioneren (werk/sociaal)
3. Medicatie-compliance > 90%
Activiteiten:
- Individuele CGT: 1x/week, 12 sessies
- ROM-meting PHQ-9: Elke 4 weken
- Medicatie: Sertraline 50mg dagelijks
- Huiswerk: Dagboek bijhouden
Epic 9 — Consents & Flags
Epic Doel: Toestemmingen (AVG) en waarschuwingen beheren.
| Story ID | Beschrijving | Acceptatiecriteria | Status | Afhankelijkheden | Story Points |
|---|---|---|---|---|---|
| E9.S1 | Consent types definiëren | Treatment, privacy, advance directive | ⏳ | E1.S4 | 2 |
| E9.S2 | Consent registreren | Form: type, scope, geldigheid, documenten | ⏳ | E3.S3, E9.S1 | 5 |
| E9.S3 | Flags (waarschuwingen) | Create: safety, clinical, behavioral alerts | ⏳ | E4.S4, E5.S3 | 3 |
| E9.S4 | Alert banner in dossier | Rood banner bovenaan bij high-priority flags | ⏳ | E9.S3 | 3 |
Technical Notes:
- Consent scopes:
patient-privacy,treatment,advance-directive,research - Flags categories:
safety,clinical,behavioral,administrative - Priority:
high,medium,low - Flags visible on ALL patient views (banner)
Acceptance:
- Toestemming registreren met status active/inactive
- Wilsverklaring uploaden als PDF attachment
- Waarschuwing aanmaken met prioriteit
- High-priority flags tonen rode banner
Flag Voorbeelden:
const flagExamples = [
{
category: 'safety',
code: 'suicide-risk',
display: 'HOOG SUÏCIDERISICO - Concrete plannen',
priority: 'high',
description: 'Middelen aanwezig, geen steun systeem'
},
{
category: 'behavioral',
code: 'aggression',
display: 'Agressie naar vrouwelijke hulpverleners',
priority: 'medium',
description: 'Alleen mannelijke behandelaar inzetten'
},
{
category: 'clinical',
code: 'allergy',
display: 'Allergie: Penicilline (anafylaxie)',
priority: 'high'
}
];
Epic 10 — Documents
Epic Doel: Documenten genereren, opslaan en beheren.
| Story ID | Beschrijving | Acceptatiecriteria | Status | Afhankelijkheden | Story Points |
|---|---|---|---|---|---|
| E10.S1 | Document types | intake-verslag, behandelplan, brief, rapport | ⏳ | E1.S4 | 2 |
| E10.S2 | Markdown editor | Rich text editor voor verslagen (TipTap/Lexical) | ⏳ | E4.S4 | 5 |
| E10.S3 | Document genereren | Auto-generate uit encounter/careplan data | ⏳ | E8.S4, E10.S2 | 6 |
Technical Notes:
- Content stored as Markdown in
content_attachment_data - Document status:
current,superseded,entered-in-error - Templates voor: intake verslag, behandelplan, brief huisarts
- PDF export via React-PDF of Puppeteer (server-side)
Acceptance:
- Markdown editor werkt met formatting
- Template selecteren en invullen
- Auto-fill data uit intake/encounter
- PDF export downloaden
Document Templates:
# Intakeverslag
**Cliënt:** {{patient.name}}
**BSN:** {{patient.bsn}}
**Datum intake:** {{encounter.date}}
**Behandelaar:** {{practitioner.name}}
## Aanmeldingsreden
{{encounter.reason_display}}
## Klachten
{{encounter.notes}}
## Diagnose(s)
{{#conditions}}
- {{code_display}} ({{clinical_status}})
{{/conditions}}
## Behandelvoorstel
{{careplan.description}}
Epic 11 — Dashboard & UX
Epic Doel: Overzichtelijke interface met navigatie en search.
| Story ID | Beschrijving | Acceptatiecriteria | Status | Afhankelijkheden | Story Points |
|---|---|---|---|---|---|
| E11.S1 | Layout component | Sidebar nav, topbar, breadcrumbs | ⏳ | E2.S4 | 5 |
| E11.S2 | Dashboard homepage | Recent clients, stats, quick actions | ⏳ | E3.S2, E11.S1 | 5 |
| E11.S3 | Global search | Cmd+K: zoeken op cliënt, diagnose, document | ⏳ | E3.S3, E5.S3 | 8 |
| E11.S4 | Client detail tabs | Overview, Encounters, Conditions, Plans, Docs | ⏳ | E4.S4, E8.S4 | 3 |
| E11.S5 | Mobile responsive | Responsive design voor tablet/mobile | ⏳ | E11.S4 | 5 |
Technical Notes:
- Sidebar: Collapsible met icon-only mode
- Search: Algolia-style met keyboard shortcuts (Cmd+K)
- Tabs: URL-based routing (
/clients/[id]?tab=conditions) - Mobile: Bottom navigation bar voor primary actions
Acceptance:
- Layout rendering op alle schermformaten
- Dashboard toont key metrics en recent activity
- Search werkt binnen 500ms, toont relevante results
- Tabs navigation werkt met browser back/forward
- Mobile view usable op iPhone/Android
Dashboard Widgets:
const dashboardWidgets = [
{
title: 'Actieve Cliënten',
value: 42,
trend: '+3 deze week'
},
{
title: 'Geplande Afspraken',
value: 8,
subtitle: 'Vandaag'
},
{
title: 'Open Behandelplannen',
value: 15,
action: 'Bekijk alle'
}
];
Epic 12 — Testing & QA
Epic Doel: Getest en stabiel systeem klaar voor gebruik.
| Story ID | Beschrijving | Acceptatiecriteria | Status | Afhankelijkheden | Story Points |
|---|---|---|---|---|---|
| E12.S1 | Unit tests schrijven | /lib utilities en validators > 80% coverage |
⏳ | All epics | 5 |
| E12.S2 | Integration tests | API routes, database operations | ⏳ | All epics | 5 |
| E12.S3 | E2E tests (Playwright) | Happy flows: login → client → intake → plan | ⏳ | E11.S5 | 8 |
| E12.S4 | Security audit | RLS policies, input validation, XSS/injection | ⏳ | E12.S3 | 5 |
Technical Notes:
- Unit tests: Vitest + Testing Library
- Integration tests: Supabase test instance
- E2E: Playwright met test database
- Security: OWASP Top 10 checklist
Acceptance:
- 80%+ unit test coverage
- Alle API routes getest
- 3 happy flows + 2 error scenarios in E2E
- Security audit passed (geen critical findings)
Test Scenarios:
Happy Flows:
1. Login → Dashboard → Nieuwe cliënt aanmaken
2. Client selecteren → Intake registreren → Diagnose toevoegen
3. Behandelplan opstellen → Doelen definiëren → Opslaan
Error Scenarios:
1. Invalid BSN → Error message shown
2. Duplicate patient → Conflict warning
Epic 13 — Deployment & Docs
Epic Doel: Live productie omgeving + gebruikersdocumentatie.
| Story ID | Beschrijving | Acceptatiecriteria | Status | Afhankelijkheden | Story Points |
|---|---|---|---|---|---|
| E13.S1 | Vercel deployment | Production build, env vars, custom domain | ⏳ | E12.S4 | 3 |
| E13.S2 | Supabase productie | Production database, backups, monitoring | ⏳ | E12.S4 | 3 |
| E13.S3 | Gebruikersdocumentatie | Handleiding voor behandelaren (screenshots) | ⏳ | E11.S5 | 2 |
Technical Notes:
- Vercel: EU region (Amsterdam)
- Supabase: Pro plan met daily backups
- Monitoring: Sentry for errors, Vercel Analytics
- Docs: Markdown in
/docs/user-guide/
Acceptance:
- App live op custom domain
- Database backups automatisch
- Gebruikershandleiding compleet
- Monitoring dashboards configured
5. Kwaliteit & Testplan
Test Types
| Test Type | Scope | Tools | Verantwoordelijke | Coverage Target |
|---|---|---|---|---|
| Unit Tests | /lib utilities, validators, helpers |
Vitest + Testing Library | Developer | 80%+ |
| Integration Tests | API routes, Supabase queries | Vitest + Supabase Test | Developer | 100% API routes |
| E2E Tests | User flows: login → intake → plan | Playwright | QA / Developer | 5 critical flows |
| Performance Tests | Page load times, query speed | Lighthouse, React Profiler | Developer | LCP < 2.5s |
| Security Tests | RLS, input validation, auth | Manual + OWASP checklist | Security Lead | 0 critical issues |
| Accessibility Tests | WCAG 2.1 AA compliance | axe DevTools, Lighthouse | Developer | 0 violations |
Test Coverage Targets
Unit Tests (80%+ coverage):
/lib/validations/*- Zod schemas/lib/utils/*- Helper functions/lib/db/*- Database query builders
Integration Tests (100% API routes):
/app/api/patients/*- CRUD operations/app/api/encounters/*- Encounter management/app/api/conditions/*- Diagnose operations/app/api/careplans/*- Treatment planning
E2E Tests (Critical Flows):
- Authentication Flow
- Sign up → Email verify → Login → Dashboard
- Patient Management
- Create patient → Edit → Search → View details
- Clinical Workflow
- Select patient → New encounter → Add diagnosis → Save
- Treatment Planning
- Create care plan → Add goals → Add activities → Publish
- Document Generation
- Select encounter → Generate report → Export PDF
Manual Test Checklist (Pre-Release)
Functionality:
- User kan inloggen met email/password
- Nieuwe cliënt aanmaken werkt (inclusief BSN validatie)
- Intake formulier opslaan zonder data loss
- Diagnose toevoegen uit DSM-5 lijst
- ROM-meting (PHQ-9) invullen en opslaan
- Behandelplan wizard doorlopen
- Waarschuwing toont rode banner
- Document genereren en PDF downloaden
- Navigatie werkt zonder JavaScript errors
- Logout werkt en cleared session
Performance:
- Homepage load < 2.5s (LCP)
- Client lijst pagina < 1s render tijd
- Search results binnen 500ms
- Database queries < 100ms (p95)
Security:
- RLS policies: Users see only own patients
- BSN encrypted in database
- No sensitive data in browser console
- Session expires after 1 hour inactivity
- XSS prevention: User input sanitized
UX/UI:
- Mobile view responsive (iPhone 12, Pixel 5)
- Tablet view usable (iPad)
- Dark mode consistent (if implemented)
- Forms show validation errors inline
- Success/error toasts display correctly
- Keyboard navigation works (Tab, Enter, Esc)
Browser Compatibility:
- Chrome (latest)
- Firefox (latest)
- Safari (latest)
- Edge (latest)
6. Demo & Presentatieplan
Geen externe demo gepland voor MVP - intern gebruikerstest.
Internal Testing Scenario
Duur: 30 minuten Doelgroep: Interne stakeholders + 2 GGZ-behandelaren (testgebruikers) Locatie: Staging environment (Vercel preview)
Test Flow:
-
Setup (5 min)
- Test accounts aanmaken
- Demo-data seeden
- Systeem walkthrough
-
Basis Workflow (10 min)
- Login als behandelaar
- Dashboard verkennen
- Nieuwe cliënt aanmaken (fictief)
- Intake registreren
-
Klinische Data (10 min)
- Diagnose toevoegen (DSM-5)
- ROM-meting invullen
- Risico-inschatting
- Behandelplan opstellen
-
Review & Feedback (5 min)
- Wat werkt goed?
- Wat ontbreekt?
- Usability issues?
- Feature requests
Success Criteria:
- Alle test flows compleet zonder crashes
- Behandelaren kunnen workflow volgen zonder uitleg
- Data wordt correct opgeslagen
- Geen kritieke bugs gevonden
Backup Plan:
- Lokale versie klaar bij hosting issues
- Screenshots voor elk scherm
- Pre-recorded video demo
7. Risico's & Mitigatie
| Risico | Kans | Impact | Mitigatie | Owner |
|---|---|---|---|---|
| FHIR complexity onderschat | Hoog | Hoog | Start simpel, itereer, gebruik FHIR profielen only where needed | Tech Lead |
| Database schema wijzigingen | Middel | Hoog | Gebruik Supabase migrations, version control alle schema changes | Developer |
| RLS policies te complex | Middel | Hoog | Start met brede policies voor MVP, verfijn later, test exhaustively | Developer |
| BSN encryptie performance | Laag | Middel | Index op encrypted field, benchmark queries, cache waar mogelijk | Developer |
| Type generation sync issues | Middel | Middel | Automate supabase gen types in CI/CD, git hooks |
DevOps |
| Scope creep (extra features) | Hoog | Middel | Strict MVP scope, feature freeze 2 weken voor launch | PM |
| Security vulnerability (RLS bypass) | Laag | Kritiek | Security audit, penetration testing, bug bounty | Security |
| Third-party dependencies vulnerabilities | Middel | Hoog | Dependabot alerts, regular updates, minimize dependencies | Developer |
| Supabase rate limits | Laag | Middel | Monitor usage, optimize queries, upgrade plan if needed | DevOps |
| GDPR compliance issues | Middel | Kritiek | Legal review, data privacy impact assessment, clear consent flows | Legal/PM |
| User adoption resistance | Middel | Hoog | Involve end-users early, training sessions, gradual rollout | PM |
Kritieke Risico's (Actie Vereist):
-
FHIR Complexity → Mitigatie:
- Gebruik alleen FHIR resources die echt nodig zijn
- Don't implement full FHIR API in MVP (alleen data model)
- Documentatie:
datamodel-documentatie.mdals referentie
-
GDPR Compliance → Mitigatie:
- BSN encryption (already in schema)
- Consent management (Epic 9)
- Data retention policy definiëren
- Privacy by design in alle features
-
Security (RLS bypass) → Mitigatie:
- Epic 12.S4: Dedicated security audit
- Test met multiple user accounts
- Verify policies in Supabase dashboard
- Logging van alle data access
8. Evaluatie & Lessons Learned
Te documenteren na MVP launch (na Epic 13):
Retrospective Vragen
Wat ging goed?
- Welke development practices werkten?
- Welke tooling was meest effectief?
- Welke FHIR resources waren eenvoudig te implementeren?
Wat kan beter?
- Waar liepen we vertraging op?
- Welke technische schuld hebben we opgebouwd?
- Welke features waren overcomplicated?
Technische Learnings:
- FHIR implementation patterns die werkten
- Supabase best practices
- Next.js App Router gotchas
- TypeScript tips voor FHIR types
Process Learnings:
- Sprint velocity (actual vs. estimated story points)
- Communication gaps
- Documentation gaps
- Testing coverage vs. bugs found
Next Iteration:
- Features voor Fase 2 (prioritering)
- Refactoring candidates
- Performance optimizations
- UX improvements
Metrics Tracking
Development Metrics:
- Actual story points per epic vs. estimated
- Bug count per epic
- Code churn (lines added/removed)
- Test coverage achieved
User Metrics (Post-Launch):
- Daily active users
- Feature adoption rate
- User feedback score
- Support tickets volume
9. Referenties
Mission Control Documents
Project Documentation:
- Datamodel Documentatie —
docs/datamodel-documentatie.md - Database Schema —
docs/archive/schemas/20241121_fhir_ggz_schema.sql(archived) - Bouwplan Template —
docs/templates/bouwplan_template.md
To Be Created:
- PRD — Product Requirements Document
- FO — Functioneel Ontwerp
- TO — Technisch Ontwerp
- UX/UI — Design specificatie
- API Documentation — Supabase API endpoints
External Resources
FHIR & Healthcare Standards:
- FHIR R4 Specification: https://hl7.org/fhir/R4/
- MedMIJ GGZ Basisgegevens: https://informatiestandaarden.nictiz.nl/wiki/MedMij:V2020.01/OntwerpGGZ
- Koppeltaal: https://www.koppeltaal.nl/
- ZIBs (ZorgInformatieBouwstenen): https://zibs.nl/
- DSM-5 Codes: American Psychiatric Association
- MedicatieProces 9.0: https://informatiestandaarden.nictiz.nl/wiki/mp:V9
Technical Stack Documentation:
- Next.js 15: https://nextjs.org/docs
- Supabase: https://supabase.com/docs
- TypeScript: https://www.typescriptlang.org/docs/
- Tailwind CSS: https://tailwindcss.com/docs
- shadcn/ui: https://ui.shadcn.com/
Development Tools:
- Repository:
https://github.com/[org]/mini-epd-prototype - Deployment:
https://mini-epd.vercel.app(to be configured) - Design: [Figma link] (to be created)
- Project Management: [Jira/Linear/GitHub Projects]
10. Glossary & Abbreviations
Project Terms
| 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, 21) |
| MVP | Minimum Viable Product - eerste werkende versie |
| RLS | Row Level Security - database-level access control |
| BSN | Burgerservicenummer - Nederlands persoonsnummer |
Development Principles
| Term | Betekenis |
|---|---|
| DRY | Don't Repeat Yourself - geen duplicate code |
| KISS | Keep It Simple, Stupid - eenvoud boven complexiteit |
| SOC | Separation of Concerns - logische scheiding van code |
| YAGNI | You Aren't Gonna Need It - alleen bouwen wat nodig is |
FHIR Healthcare Terms
| Term | Betekenis |
|---|---|
| FHIR | Fast Healthcare Interoperability Resources - internationale standaard |
| HL7 | Health Level 7 - internationale gezondheidsdata standaard organisatie |
| ZIB | ZorgInformatieBouwsteen - Nederlandse gezondheidsdata standaard |
| DSM-5 | Diagnostic and Statistical Manual of Mental Disorders (5e editie) |
| ICD-10 | International Classification of Diseases (10e revisie) |
| ATC | Anatomical Therapeutic Chemical - medicatie classificatie systeem |
| ROM | Routine Outcome Monitoring - vragenlijsten voor behandeleffect |
| MedMIJ | Nederlands afsprakenstelsel voor patiëntportalen (PGO) |
| PGO | Persoonlijke Gezondheidsomgeving - patiënt app voor eigen dossier |
| Koppeltaal | Standaard voor koppeling EPD met eHealth apps |
| LSP | Landelijk Schakelpunt - nationale medicatie-uitwisseling |
FHIR Resources
| Resource | Betekenis |
|---|---|
| Patient | Patiënt/cliënt |
| Practitioner | Behandelaar/zorgverlener |
| Organization | Zorginstelling |
| Encounter | Contactmoment (intake, sessie, etc.) |
| Condition | Diagnose of probleem |
| Observation | Meting of observatie (ROM, risico, etc.) |
| MedicationStatement | Medicatiegebruik |
| CarePlan | Behandelplan |
| Goal | Behandeldoel |
| Consent | Toestemming of wilsverklaring |
| Flag | Waarschuwing of alert |
| DocumentReference | Document (verslag, brief, etc.) |
Technical Abbreviations
| Term | Betekenis |
|---|---|
| API | Application Programming Interface |
| CRUD | Create, Read, Update, Delete |
| RSC | React Server Components |
| RLS | Row Level Security |
| UUID | Universally Unique Identifier |
| JWT | JSON Web Token |
| HTTPS | HTTP Secure |
| TLS | Transport Layer Security |
| CORS | Cross-Origin Resource Sharing |
| XSS | Cross-Site Scripting |
| SQL | Structured Query Language |
| REST | Representational State Transfer |
| JSON | JavaScript Object Notation |
Versiehistorie
| Versie | Datum | Auteur | Wijziging |
|---|---|---|---|
| v1.0 | 21 november 2024 | Colin Lit | Initiële versie - Complete bouwplan gebaseerd op FHIR schema |
Appendix A: Story Point Estimatie
Fibonacci Scale:
- 1 punt: Triviale taak (< 2 uur) - bijv. config change, minor text update
- 2 punten: Simpele taak (2-4 uur) - bijv. basic form, simple component
- 3 punten: Gemiddelde taak (4-8 uur) - bijv. CRUD page, database query
- 5 punten: Complexe taak (1-2 dagen) - bijv. multi-step form, complex logic
- 8 punten: Zeer complex (2-3 dagen) - bijv. integration, advanced feature
- 13 punten: Epic-sized (3-5 dagen) - overweeg opsplitsen in kleinere stories
- 21+ punten: Te groot - MOET worden opgesplitst
Velocity Estimatie:
- 1 developer, full-time: ~20-25 story points per 2-week sprint
- 2 developers, full-time: ~40-50 story points per 2-week sprint
- Accounting for: meetings, code review, bugfixes, unknowns
Project Totals:
- Total Story Points: ~200
- Estimated Duration: 8-10 weken @ 25 points/week
- Buffer: +20% voor onvoorzien = 10-12 weken totaal
Appendix B: Database Schema Overzicht
13 Core Tables (FHIR Resources):
practitioners- Behandelaren (BIG, AGB, kwalificaties)organizations- GGZ-instellingen (AGB, KVK)patients- Cliënten (BSN encrypted, demographics)encounters- Contactmomenten (intake, behandeling, etc.)conditions- Diagnoses (DSM-5, ICD-10, severity)observations- Metingen (ROM, risico's, vitals)medication_statements- Medicatie (ATC codes, dosering)care_plans- Behandelplannencare_plan_activities- Behandelactiviteitengoals- Behandeldoelen (SMART, meetbaar)consents- Toestemmingen (AVG, wilsverklaringen)flags- Waarschuwingen (suïcide, agressie, allergie)document_references- Documenten (verslagen, brieven)
Key Database Features:
- Row Level Security (RLS) op alle tabellen
- Automatic
updated_attriggers - UUID primary keys
- ENUM types voor type-safety
- Foreign key constraints
- Indexes op frequently queried fields
- BSN encryption via pgcrypto
Schema File: docs/archive/schemas/20241121_fhir_ggz_schema.sql (archived)
🎯 Dit bouwplan is gereed voor implementatie. Volgende stap: Start Epic 0 (Setup & Configuratie).