- Add DocsChatWidget to epd-layout-client.tsx - Widget now visible for all authenticated EPD users - Update bouwplan status: all epics complete Completes AI Documentatie Assistent feature (E0-E4, 12 stories) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
322 lines
10 KiB
Markdown
322 lines
10 KiB
Markdown
# Mission Control — Bouwplan AI Documentatie Assistent
|
||
|
||
**Projectnaam:** Mini-ECD – AI Documentatie Assistent
|
||
**Versie:** v1.0
|
||
**Datum:** 01-12-2025
|
||
**Auteur:** Colin van der Heijden
|
||
|
||
---
|
||
|
||
## 1. Doel en context
|
||
|
||
**Doel:** Een floating chat widget bouwen die eindgebruikers van het EPD helpt door vragen te beantwoorden op basis van de systeemdocumentatie.
|
||
|
||
**Context:** Dit is de eerste AI-integratie in het Mini-ECD prototype. Het dient als fundament voor toekomstige AI features (zoals AI Pre-fill Behandelplan). De widget maakt documentatie direct toegankelijk via een conversatie-interface.
|
||
|
||
**Relatie met andere documenten:**
|
||
- PRD: `prd-ai-docs-assistent-v1.md` — Wat en waarom
|
||
- FO: `fo-ai-docs-assistent-v1.md` — Hoe het werkt voor gebruikers
|
||
|
||
---
|
||
|
||
## 2. Uitgangspunten
|
||
|
||
### 2.1 Technische Stack
|
||
|
||
| Laag | Technologie |
|
||
|------|-------------|
|
||
| **Frontend** | Next.js 14.2 + React + Tailwind CSS |
|
||
| **Backend** | Next.js API Routes (App Router) |
|
||
| **Database** | Supabase PostgreSQL (alleen voor auth check) |
|
||
| **AI** | Claude API (claude-sonnet-4-20250514) met streaming |
|
||
| **Hosting** | Vercel |
|
||
| **Icons** | Lucide React (Sparkles, X, Send) |
|
||
|
||
### 2.2 Projectkaders
|
||
|
||
| Aspect | Waarde |
|
||
|--------|--------|
|
||
| **Bouwtijd** | 1-2 dagen |
|
||
| **Team** | 1 developer |
|
||
| **Data** | Alleen bestaande MDX documentatie |
|
||
| **Scope** | MVP — chat widget met streaming responses |
|
||
| **Persistentie** | Sessie-only (geen database opslag) |
|
||
|
||
### 2.3 Programmeer Uitgangspunten
|
||
|
||
**Code Quality Principles:**
|
||
|
||
- **DRY** — Herbruikbare hook voor chat state, centrale prompt configuratie
|
||
- **KISS** — Eenvoudige fetch naar Claude API, geen SDK overhead
|
||
- **SOC** — UI componenten gescheiden van API logic en knowledge base
|
||
- **YAGNI** — Geen RAG, geen database opslag, geen multi-provider support
|
||
|
||
**Security:**
|
||
- API key alleen server-side (Next.js API route)
|
||
- Widget alleen voor ingelogde gebruikers
|
||
- Geen logging van conversaties
|
||
|
||
---
|
||
|
||
## 3. Epics & Stories Overzicht
|
||
|
||
| Epic ID | Titel | Doel | Status | Stories |
|
||
|---------|-------|------|--------|---------|
|
||
| E0 | Knowledge Base Content | FAQ's en guidelines in markdown | ✅ Done | 2 |
|
||
| E1 | Knowledge Services | CategoryDetector, KnowledgeLoader, PromptBuilder | ✅ Done | 3 |
|
||
| E2 | API Endpoint | Streaming Claude integratie | ✅ Done | 1 |
|
||
| E3 | Chat UI Components | Widget, messages, input | ✅ Done | 4 |
|
||
| E4 | Integratie & Testing | Widget in EPD, testen | ✅ Done | 2 |
|
||
|
||
**Totaal:** 12 stories, ~18 story points
|
||
|
||
---
|
||
|
||
## 4. Epics & Stories (Uitwerking)
|
||
|
||
### Epic 0 — Knowledge Base Content
|
||
|
||
**Epic Doel:** Gestructureerde FAQ's en guidelines in markdown bestanden.
|
||
|
||
| Story ID | Beschrijving | Acceptatiecriteria | Status | SP |
|
||
|----------|--------------|---------------------|--------|-----|
|
||
| E0.S1 | FAQ markdown bestanden | 6 FAQ bestanden met Q&A per categorie | ✅ | 2 |
|
||
| E0.S2 | Guidelines bestanden | 2 guideline bestanden (interface, technisch) | ✅ | 1 |
|
||
|
||
**Deliverables:**
|
||
```
|
||
lib/docs/knowledge/
|
||
├── faq_clientbeheer.md # Cliënt aanmaken, zoeken, verwijderen
|
||
├── faq_intake.md # Intake starten, notities, spraak
|
||
├── faq_screening.md # Screening resultaten, vragenlijsten
|
||
├── faq_behandelplan.md # Plan maken, doelen, interventies
|
||
├── faq_spraak.md # Microfoon, dicteren, transcriptie
|
||
├── faq_inloggen.md # Login, wachtwoord, rechten
|
||
├── guidelines_interface.md # UI uitleg, navigatie, menu's
|
||
└── guidelines_technisch.md # FHIR API, data model (devs)
|
||
```
|
||
|
||
---
|
||
|
||
### Epic 1 — Knowledge Services
|
||
|
||
**Epic Doel:** Intelligente services voor dynamische knowledge loading.
|
||
|
||
| Story ID | Beschrijving | Acceptatiecriteria | Status | SP |
|
||
|----------|--------------|---------------------|--------|-----|
|
||
| E1.S1 | CategoryDetector | Keyword matching om relevante categorieën te bepalen | ✅ | 2 |
|
||
| E1.S2 | KnowledgeLoader | Laadt alleen relevante markdown bestanden | ✅ | 2 |
|
||
| E1.S3 | PromptBuilder | Combineert base prompt + relevante knowledge | ✅ | 2 |
|
||
|
||
**Deliverables:**
|
||
```
|
||
lib/docs/
|
||
├── category-detector.ts # Analyseert vraag → categorieën
|
||
├── knowledge-loader.ts # Laadt relevante knowledge
|
||
└── prompt-builder.ts # Bouwt geoptimaliseerde prompt
|
||
```
|
||
|
||
**Category Mapping:**
|
||
```typescript
|
||
const CATEGORY_KEYWORDS: Record<Category, string[]> = {
|
||
clientbeheer: ['cliënt', 'patient', 'aanmaken', 'zoeken', 'dossier'],
|
||
intake: ['intake', 'gesprek', 'notitie', 'verslag'],
|
||
screening: ['screening', 'vragenlijst', 'score', 'resultaat'],
|
||
behandelplan: ['behandelplan', 'doel', 'interventie', 'plan'],
|
||
spraak: ['spraak', 'microfoon', 'dicteren', 'stem', 'transcriptie'],
|
||
inloggen: ['inloggen', 'wachtwoord', 'login', 'account'],
|
||
interface: ['menu', 'knop', 'scherm', 'navigatie', 'waar vind'],
|
||
technisch: ['api', 'fhir', 'endpoint', 'database', 'developer']
|
||
};
|
||
```
|
||
|
||
**Flow:**
|
||
```
|
||
Vraag: "Hoe maak ik een intake aan?"
|
||
↓
|
||
CategoryDetector → ['intake']
|
||
↓
|
||
KnowledgeLoader → laadt faq_intake.md
|
||
↓
|
||
PromptBuilder → base prompt + intake FAQ
|
||
↓
|
||
Claude API → streaming response
|
||
```
|
||
|
||
---
|
||
|
||
### Epic 2 — API Endpoint
|
||
|
||
**Epic Doel:** Streaming API endpoint met dynamische knowledge.
|
||
|
||
| Story ID | Beschrijving | Acceptatiecriteria | Status | SP |
|
||
|----------|--------------|---------------------|--------|-----|
|
||
| E2.S1 | Streaming endpoint | `POST /api/docs/chat` met dynamic knowledge, SSE stream | ✅ | 3 |
|
||
|
||
**Deliverables:**
|
||
```
|
||
app/api/docs/chat/
|
||
route.ts # Streaming API endpoint
|
||
```
|
||
|
||
**API Contract:**
|
||
```typescript
|
||
// Request
|
||
POST /api/docs/chat
|
||
{
|
||
messages: Array<{ role: 'user' | 'assistant', content: string }>,
|
||
userMessage: string
|
||
}
|
||
|
||
// Response: Server-Sent Events stream
|
||
event: content_block_delta
|
||
data: {"delta":{"text":"..."}}
|
||
```
|
||
|
||
---
|
||
|
||
### Epic 3 — Chat UI Components
|
||
|
||
**Epic Doel:** Complete chat widget UI volgens FO specificaties.
|
||
|
||
| Story ID | Beschrijving | Acceptatiecriteria | Status | SP |
|
||
|----------|--------------|---------------------|--------|-----|
|
||
| E3.S1 | Chat state hook | `use-docs-chat.ts` met messages, loading, sendMessage, streaming | ✅ | 2 |
|
||
| E3.S2 | Message list component | `chat-messages.tsx` met styling, auto-scroll, streaming cursor | ✅ | 1 |
|
||
| E3.S3 | Input component | `chat-input.tsx` met textarea, send, Enter/Shift+Enter | ✅ | 1 |
|
||
| E3.S4 | Widget container | `docs-chat-widget.tsx` met trigger, panel, header, animaties | ✅ | 2 |
|
||
|
||
**Deliverables:**
|
||
```
|
||
components/docs-chat/
|
||
use-docs-chat.ts # Custom hook
|
||
chat-messages.tsx # Message list
|
||
chat-input.tsx # Input area
|
||
docs-chat-widget.tsx # Main container
|
||
```
|
||
|
||
**UI Specs (uit FO):**
|
||
|
||
| Element | Specificatie |
|
||
|---------|--------------|
|
||
| Trigger button | 56x56px, amber gradient, Sparkles icon, `fixed bottom-6 right-6` |
|
||
| Panel | 384px breed, max 80vh, slide-in animatie |
|
||
| User messages | Rechts, `bg-amber-100`, rounded |
|
||
| Assistant messages | Links, `bg-slate-100`, rounded |
|
||
| Streaming | Pulserende cursor `▊` |
|
||
|
||
---
|
||
|
||
### Epic 4 — Integratie & Testing
|
||
|
||
**Epic Doel:** Widget geïntegreerd in EPD en getest.
|
||
|
||
| Story ID | Beschrijving | Acceptatiecriteria | Status | SP |
|
||
|----------|--------------|---------------------|--------|-----|
|
||
| E4.S1 | Widget integratie | `DocsChatWidget` in EPD layout, alleen ingelogde users | ✅ | 1 |
|
||
| E4.S2 | Smoke tests | Happy flow, error states, category detection werkt | ✅ | 1 |
|
||
|
||
**Te wijzigen bestand:**
|
||
```
|
||
app/epd/components/epd-layout-client.tsx
|
||
```
|
||
|
||
---
|
||
|
||
## 5. Kwaliteit & Testplan
|
||
|
||
### Test Types
|
||
|
||
| Test Type | Scope | Methode |
|
||
|-----------|-------|---------|
|
||
| Unit | Knowledge base loader | Console test |
|
||
| Integration | API endpoint | curl/Postman |
|
||
| Smoke | Volledige flow | Manual in browser |
|
||
|
||
### Manual Test Checklist
|
||
|
||
- [ ] Widget trigger button zichtbaar in EPD
|
||
- [ ] Klik opent chat panel met animatie
|
||
- [ ] Welkomstbericht wordt getoond
|
||
- [ ] Vraag versturen werkt (Enter + button)
|
||
- [ ] Streaming response verschijnt woord-voor-woord
|
||
- [ ] Vervolgvraag behoudt context
|
||
- [ ] X-knop sluit panel
|
||
- [ ] Conversatie blijft behouden na sluiten/openen
|
||
- [ ] Error state toont bij API failure
|
||
- [ ] Widget verdwijnt bij uitloggen
|
||
|
||
### Acceptatiecriteria (uit PRD)
|
||
|
||
| Criterium | Target |
|
||
|-----------|--------|
|
||
| First token | < 2 seconden |
|
||
| Volledige response | < 30 seconden |
|
||
| Error rate | < 5% |
|
||
|
||
---
|
||
|
||
## 6. Demo & Presentatieplan
|
||
|
||
**Duur:** 3 minuten
|
||
**Scenario:**
|
||
|
||
1. **Intro** (30s): "Dit is de documentatie assistent"
|
||
2. **Vraag 1** (45s): "Hoe maak ik een intake aan?" → streaming antwoord
|
||
3. **Vraag 2** (45s): "En hoe gebruik ik spraakherkenning?" → context behouden
|
||
4. **Edge case** (30s): "Wat is de beste behandeling?" → "weet ik niet" response
|
||
5. **Afsluiting** (30s): Widget sluiten, conversatie behouden
|
||
|
||
---
|
||
|
||
## 7. Risico's & Mitigatie
|
||
|
||
| Risico | Kans | Impact | Mitigatie |
|
||
|--------|------|--------|-----------|
|
||
| AI hallucineert | Middel | Hoog | Strikte system prompt, FAQ's eerst, "alleen uit docs" regel |
|
||
| Trage response | Laag | Middel | Streaming UX, timeout na 30s |
|
||
| Context te groot | Laag | Middel | ~119KB past in context window, monitoring |
|
||
| API rate limits | Laag | Middel | Sessie-based (geen caching nodig) |
|
||
|
||
---
|
||
|
||
## 8. Referenties
|
||
|
||
### Mission Control Documents
|
||
|
||
- **PRD:** `prd-ai-docs-assistent-v1.md`
|
||
- **FO:** `fo-ai-docs-assistent-v1.md`
|
||
- **Gerelateerd:** `prd-ai-prefill-behandelplan-v1.md`
|
||
|
||
### Bestaande Code Patterns
|
||
|
||
| Bestand | Pattern |
|
||
|---------|---------|
|
||
| `app/api/reports/classify/route.ts` | Claude API fetch pattern |
|
||
| `lib/mdx/documentatie.ts` | MDX loading met gray-matter |
|
||
| `components/ui/ai-button.tsx` | Amber AI styling |
|
||
|
||
### Externe Referenties
|
||
|
||
- [Claude API Docs](https://docs.anthropic.com)
|
||
- [Anthropic Streaming](https://docs.anthropic.com/en/api/streaming)
|
||
|
||
---
|
||
|
||
## 9. Glossary
|
||
|
||
| Term | Betekenis |
|
||
|------|-----------|
|
||
| SSE | Server-Sent Events (streaming protocol) |
|
||
| Knowledge Base | Verzameling documentatie voor AI context |
|
||
| FAQ | Frequently Asked Questions |
|
||
| Streaming | Real-time response, woord-voor-woord |
|
||
|
||
---
|
||
|
||
**Versiehistorie:**
|
||
|
||
| Versie | Datum | Auteur | Wijziging |
|
||
|--------|-------|--------|-----------|
|
||
| v1.0 | 01-12-2025 | Colin van der Heijden | Initiële versie |
|