* docs(naming): drop scrum4me- prefix from doc filenames Rename 10 docs/scrum4me-*.md files to unprefixed kebab-case names. Update every internal link in docs/, CLAUDE.md, AGENTS.md, README.md. * docs(naming): lowercase API.md and MD3 filenames Rename docs/API.md → docs/api.md and docs/MD3_Color_Scheme_Documentation.md → docs/md3-color-scheme.md. Update all internal links across 7 files. * docs(naming): rename plan file to kebab-case ASCII Rename "docs/plans/Tweede Claude Agent — Planning Agent.md" → docs/plans/tweede-claude-agent-planning.md. No external links needed updating. * docs(naming): rename middleware.md to proxy.md (next 16) docs/patterns/middleware.md → docs/patterns/proxy.md following the Next.js 16 proxy.ts rename. Update link in CLAUDE.md. * docs(naming): polish CLAUDE.md doc-index after renames Fix doubled scrum4me-scrum4me-mcp repo references (cascade from prior sed) in CLAUDE.md, docs/architecture.md, backlog.md, agent-instruction-audit.md, and plans/ST-1109. Update 'Middleware' label to 'Proxy middleware' in patterns table.
19 KiB
CLAUDE.md — Scrum4Me
Dit is het centrale instructiedocument voor Claude Code. Lees dit volledig voordat je iets bouwt.
Wat is Scrum4Me?
Een desktop-first fullstack webapplicatie voor solo developers en kleine Scrum Teams die meerdere softwareprojecten parallel beheren. De app organiseert werk hiërarchisch (product → PBI → story → taak), biedt gesplitste planningsschermen met drag-and-drop, en integreert met Claude Code via een REST API.
Specificatiedocumenten
Lees het relevante document voordat je aan een feature begint. Nooit gokken over requirements.
| Document | Gebruik voor |
|---|---|
docs/functional.md |
Acceptatiecriteria, randgevallen, user flows |
docs/architecture.md |
Stack, datamodel, Prisma schema, Zustand stores |
docs/backlog.md |
Welke task bouwen, volgorde, "done when"-criteria |
docs/personas.md |
Lars (primair), Dina, Remi — gebruik bij UI-beslissingen |
docs/product-backlog.md |
Historische domein-backlog (referentie); seed wordt sinds ST-004 gegenereerd uit backlog.md via prisma/seed-data/parse-backlog.ts |
docs/api.md |
REST-API contract voor Claude Code — endpoints, status-enums, foutcodes, voorbeeld-curls |
docs/styling.md |
Lees dit voor elk component — MD3-kleuren, shadcn patronen |
docs/agent-instruction-audit.md |
Waarom de agent-instructies zijn aangescherpt; checklist voor toekomstige wijzigingen |
docs/plans/<milestone-key>-*.md |
Implementatieplan per milestone — Bestanden, Stappen, Aandachtspunten, Verificatie. Lees vóór je aan een ST begint. Milestone-key matcht backlog-header (M9, M3.5, PBI-9, …). |
madhura68/scrum4me-mcp |
MCP-server repo: native tools voor Claude Code, schema-sync via git submodule |
Waar te beginnen
Volg de backlog strikt op volgorde. Start bij ST-001. Sla geen milestone over.
M0 (ST-001–008) → M1 (ST-101–110) → M2 (ST-201–210)
→ M3 (ST-301–312) → M4 (ST-401–410) → M5 (ST-501–506)
→ M6 (ST-601–612)
Werken aan een task kan via twee tracks. Track A heeft de voorkeur als je in Claude Code zit; Track B is voor Codex of omgevingen zonder MCP.
Track A — via Claude Code MCP (aanbevolen)
- Roep
mcp__scrum4me__implement_next_storyaan metproduct_id(gebruikmcp__scrum4me__list_productsals je het id niet weet) - De prompt orkestreert:
get_claude_context→log_implementation→ per taskupdate_task_status(in_progress)→ bouw →update_task_status(done)→log_test_result→log_commit - Bouw de tasks in volgorde van
sort_order; lees per task de relevante pattern-doc en styling - Verifieer:
npm run lint && npm test && npm run build - Commit per laag (zie Commit Strategy)
Track B — manueel (Codex of zonder MCP)
- Lees de task in
backlog.md - Zoek de bijbehorende feature-spec in
functional.md - Lees het relevante patroon in
docs/patterns/en styling indocs/styling.mdals dat van toepassing is - Bouw — test — verifieer de "Done when"-criteria
- Vraag of de code correct is
- Commit (zie Commit Strategy hieronder)
- Vraag of de volgende taak gedaan moet worden
Tech stack
Next.js 16 (App Router) + React 19
TypeScript strict
Tailwind CSS + shadcn/ui
MD3 kleurensysteem via app/styles/theme.css
Zustand (client state)
dnd-kit (drag-and-drop)
Prisma v7 + PostgreSQL (Neon)
iron-session (auth cookies)
bcryptjs + Zod + Sonner
Sharp (avatarverwerking)
Vercel Analytics (@vercel/analytics/next)
⚠️ Stylingregel: Gebruik nooit
bg-blue-500of willekeurige Tailwind-kleuren. Gebruik altijd semantische MD3-tokens:bg-primary,bg-status-done,bg-priority-critical. Ziestyling.mdvoor alle patronen.
⚠️ Next.js-versie: Lees
node_modules/next/dist/docs/bij twijfel — API's kunnen afwijken van trainingsdata.
UI Library Conventions
- Dit project gebruikt
@base-ui/react, niet Radix UI — ondanks dat shadcn-componenten visueel-identiek zijn - Composition gebeurt via de
render-prop, niet via Radix'sasChild:- ✅
<TooltipTrigger render={<button />}>...</TooltipTrigger> - ❌
<TooltipTrigger asChild><button>...</button></TooltipTrigger>— geeft TS-errors
- ✅
- Vóór je een nieuwe shadcn-/UI-primitive gebruikt: grep eerst de codebase voor bestaand gebruik en volg dat patroon (
grep -rn "PrimitiveTrigger" components/) - shadcn-componenten in
components/ui/zijn dunne wrappers rond@base-ui/react-primitives; lees die voor de exacte prop-API
Implementatiepatronen
Lees het relevante patroon vóór je begint. Nooit uit het hoofd schrijven.
| Patroon | Bestand |
|---|---|
| iron-session (auth cookies) | docs/patterns/iron-session.md |
| Prisma Client singleton | docs/patterns/prisma-client.md |
| Server Action (met auth + Zod) | docs/patterns/server-action.md |
| Route Handler (REST API) | docs/patterns/route-handler.md |
| Zustand optimistische update + rollback | docs/patterns/zustand-optimistic.md |
| Float sort_order drag-and-drop | docs/patterns/sort-order.md |
| Proxy middleware (route protection) | docs/patterns/proxy.md |
| QR-pairing (unauth-SSE + pre-auth cookie) | docs/patterns/qr-login.md |
| Bidirectionele async-comms MCP-agent ↔ user | docs/patterns/claude-question-channel.md |
| Entity Dialog (verplicht voor élke create/edit/detail-dialog) | docs/patterns/dialog.md — bron-of-truth; per entiteit één profile-doc (bv. docs/task-dialog.md) |
| Story met UI-component (verplicht 3-task-patroon: Helper / Component / Integration) | docs/patterns/story-with-ui-component.md — elke story met een *-component.tsx vereist een afsluitende Integration-task die de component in page.tsx wirt |
| Status-enum mapping (DB ↔ API) | lib/task-status.ts |
| Client/server module-boundary | *-server.ts bevat DB-calls of node-only deps; *.ts is pure (client-safe). Nooit import { ... } from '@/lib/foo-server' in een client-component, anders krijg je Module not found: 'dns'/'pg'-style runtime fouten |
Integration-task verificatie (smoke-test)
Voor stories met *-component.tsx: de Integration-task moet vóór
update_job_status(done) een smoke-test draaien op de daadwerkelijke
HTML-render:
# In de worktree — pas ROUTE en SECTIONS aan per story
ROUTE="/insights"
SECTIONS=("Sprint Health" "Plan-quality" "Agent throughput" "Velocity" "Backlog health")
npm run dev > /tmp/dev.log 2>&1 &
DEV_PID=$!
sleep 8 # wacht tot Next.js compiled
curl -s http://localhost:3000${ROUTE} > /tmp/page.html
SMOKE_FAIL=
for section in "${SECTIONS[@]}"; do
grep -q "$section" /tmp/page.html || { echo "MISSING: $section"; SMOKE_FAIL=1; }
done
kill $DEV_PID
[ -z "$SMOKE_FAIL" ] # exit-code 1 als iets miste
Als de smoke-test faalt: pas page.tsx aan zodat alle secties renderen, herhaal.
Markeer Integration-task DONE pas wanneer alle verwachte sections in de HTML zitten.
Env vars
DATABASE_URL="" # postgresql://... (verplicht)
DIRECT_URL="" # postgresql://... — pooler-bypass voor LISTEN/NOTIFY (Neon/cloud)
SESSION_SECRET="" # min 32 chars; openssl rand -base64 32
CRON_SECRET="" # M11 — Bearer-secret voor /api/cron/*; verplicht in productie, optioneel lokaal (genereer met openssl rand -base64 32)
Volledige Zod-schema in lib/env.ts. .env.example is de canonieke lijst voor nieuwe checkouts.
Conventies
- Branches:
feat/ST-001-scaffolding - Server Actions: altijd in
actions/[domein].ts, nooit inline in page.tsx - Validatie: altijd Zod, nooit handmatige checks
- Toegangsmodel: product-scoped resources gebruiken
productAccessFilter(userId)tenzij het expliciet een eigenaarsactie is - Bulk-ID's: reorder- en beslissingsacties valideren dat alle meegegeven IDs binnen dezelfde parent-scope vallen voordat er geschreven wordt
- Foreign keys: denormalized keys zoals
story.product_idworden afgeleid uit de database-parent (pbi.product_id), nooit uit client-input - Demo-check (drie lagen — ST-1110): write-acties zijn drielaags afgedekt: (1) middleware-guard in
proxy.tsblokkeert non-GET op/api/*voor demo; (2) elke Server Action / Route Handler controleertsession.isDemovóór schrijven; (3) write-knoppen in UI zijndisabledmet<DemoTooltip show={isDemo}>. Ziedocs/architecture.md#demo-user-policyendocs/plans/ST-1110-demo-readonly.md - Foutberichten: Nederlands voor eindgebruikers — comments in code: Engels
- Dependencies: elke geïmporteerde runtime package staat direct in
dependencies, niet alleen transitief inpackage-lock.json - Docs-sync: elke gedrags-, dependency-, API- of deploymentwijziging werkt README, relevante docs en patterns bij in dezelfde change
- Entity codes: gebruik product/PBI/story-codes in commit-titles wanneer aanwezig (
feat(ST-356.2): ...); branchnaam blijftfeat/ST-XXX-slug - Status-enums op API: lowercase (
todo|in_progress|review|done,open|in_sprint|done); DB houdt UPPER_SNAKE; conversie uitsluitend vialib/task-status.ts-mappers — nooit ad-hoc.toLowerCase()elders - Foutcodes API:
400alleen voor malformed JSON-body (parse-fout viarequest.json());422voor zod-validatie en well-formed-maar-niet-acceptabel;403voor demo-tokens. Documenteer per endpoint indocs/api.md - Tests volgen contract: bij een API-contract-wijziging (status, foutcode, response-shape) MOET in dezelfde commit ook
__tests__/api/mee — een test die rood gaat omdat de oude waarde wordt verwacht is een onvolledige wijziging, niet een "kapotte test" - Dev port:
npm run devdraait altijd op 3000. Eenpredev-hook killt vooraf elk proces op 3000 (stale Next.js dev-server, vorige sessie) zodat sessies, cookies en MCP-config consistent op één poort werken. Wijk hier niet van af — geen-p 3001o.i.d. tenzij je expliciet twee dev-servers naast elkaar wil draaien
Branch & PR Strategy (STRICT — kostenbeheersing)
Core rule: één branch per milestone, PR alleen na gebruikerstest
Elke git push naar een feature-branch triggert een Vercel preview-deployment. Op het huidige Hobby-account zijn die schaars en kosten geld; we minimaliseren preview-builds tot er werkelijk iets te reviewen valt.
Wel doen
- Eén branch voor de hele milestone —
feat/M{N}-{slug}(bv.feat/M10-qr-login); voor losse stories zonder milestone blijftfeat/ST-XXX-{slug}geldig - Commits accumuleren lokaal volgens de Commit Strategy hieronder — één commit per stap, ST-code in de titel
- Pushen + PR openen pas nadat de gebruiker de milestone handmatig heeft getest en goedgekeurd — vraag expliciet om bevestiging vóór
git push - Tussentijdse "klaar voor jouw test"-momenten markeren met een lokale tag of een berichtje in chat, niet met een push
Niet doen
- Pushen na elke story of commit
- Een PR per story openen tijdens de implementatie
- "Just-in-case" pushen om backup te hebben — gebruik
git stash, een lokale tag, of meerdere lokale branches --force-pushom eerdere preview-builds "weg te toveren" (kost dezelfde build opnieuw bij hercreatie)- Direct pushen naar
main— die branch heeft protection rules; gebruik altijd een PR
Wanneer wel commit-zonder-vragen, wanneer niet
- Tijdens een directed sprint-flow (Track A:
mcp__scrum4me__implement_next_storyof een expliciete "implementeer M{N}"-opdracht): commit-per-laag conform de Commit Strategy hieronder is impliciet geautoriseerd — niet per commit vragen - Bij ad-hoc / out-of-band werk (bug-fix tussendoor, refactor, kleine wijziging op verzoek): toon de diff + voorgestelde commit-message en wacht op
"commit it"voordat jegit commitdraait git pushis altijd expliciet — de scope van de policy gaat over preview-builds, dus push gebeurt alleen na gebruiker-test, ongeacht commit-context
Uitzonderingen op de push-regel
- Een planning-PR zonder code-wijzigingen (alleen docs in
docs/plans/ofdocs/) mag direct gepusht worden — die triggert geen functional regressie en is goedkoop te bouwen - Een bugfix-hotfix op
mainmet aantoonbare productie-impact mag direct gepusht worden (via een PR — zie boven)
Wanneer aanpassen
Zodra het Vercel-account naar Pro (of andere omgeving zonder per-build-kosten) gaat: vervang deze regel door "branch + PR per story" zoals oorspronkelijk in dit document stond. Werk deze sectie bij én documenteer de wijziging in docs/agent-instruction-audit.md.
Plan Mode
- Voor simpele, goed-afgebakende file-edits: niet in plan mode gaan — gewoon de wijziging maken
- Reserveer plan mode voor multi-step refactors, ambigue verzoeken, of milestone-planning waarbij design-keuzes vooraf bevestigd moeten worden
- Plannen die uit plan mode komen: opslaan als
docs/plans/M{N}-{slug}.md(zie memoryfeedback_plan_location), niet als ephemeral systeem-bestand
Commit Strategy (STRICT)
Core rule: één commit = één verantwoordelijkheid
Nooit doen
- Database + API + UI in één commit mengen
- Feature + documentatie combineren
- Grote "alles gewijzigd" commits
- Vage berichten zoals "update stuff"
Verplichte structuur
Splits werk op in logische lagen:
- Database / Prisma
- API / server actions
- UI / components
- Config / infra
- Documentatie
Commit-formaat
feat(ST-XXX): korte beschrijving
fix(ST-XXX): korte beschrijving
chore(ST-XXX): korte beschrijving
docs(ST-XXX): korte beschrijving
Voorbeeld (verplicht patroon)
In plaats van:
feat: add profile system
Splits altijd op in:
feat(ST-XXX): add user profile fields to Prisma schema
feat(ST-XXX): add avatar upload endpoint
feat(ST-XXX): add profile editor component
chore(ST-XXX): configure sharp for avatar processing
docs(ST-XXX): document profile feature
Scrum-terminologie
| Correct | Niet gebruiken |
|---|---|
| Product Backlog Item (PBI) | Feature, Epic, Issue |
| Story | User Story, Ticket |
| Sprint Goal | Sprint Objective |
| Scrum Team | Team |
MCP-integratie
Scrum4Me heeft een eigen MCP-server in repo madhura68/scrum4me-mcp die de REST-API als native tools voor Claude Code aanbiedt. Schema's worden gedeeld via een git submodule (vendor/scrum4me), niet gedupliceerd.
Tools beschikbaar in Claude Code (18)
Read / context:
mcp__scrum4me__health— service + DB pingmcp__scrum4me__list_products— producten waar de tokengebruiker toegang tot heeftmcp__scrum4me__get_claude_context— bundled product / actieve sprint / next story (met tasks) / open todos
Authoring (PBI/Story/Task aanmaken):
mcp__scrum4me__create_pbi—{ product_id, title, description?, priority, sort_order? }; auto sort_order = last+1 binnen prio-groepmcp__scrum4me__create_story—{ pbi_id, title, description?, acceptance_criteria?, priority, sort_order? }; product_id afgeleid uit PBI; status=OPENmcp__scrum4me__create_task—{ story_id, title, description?, implementation_plan?, priority, sort_order? }; sprint_id geërfd van story; status=TO_DOmcp__scrum4me__create_todo— losse todo (optioneel product-scoped)
Task / story writes:
mcp__scrum4me__update_task_status,mcp__scrum4me__update_task_planmcp__scrum4me__log_implementation,mcp__scrum4me__log_test_result,mcp__scrum4me__log_commit
Vraag-antwoord-kanaal (M11):
mcp__scrum4me__ask_user_question— post een vraag over een story; optionelewait_seconds(max 600) polt voor het antwoordmcp__scrum4me__get_question_answer— huidige status + antwoord (voor latere session-pickup)mcp__scrum4me__list_open_questions— eigen vragen, max 50, recente eerstmcp__scrum4me__cancel_question— asker-only annulering van een eigen open vraag
Job queue — agent worker mode (M13):
mcp__scrum4me__wait_for_job— blokkeert ≤600s, claimt atomisch een QUEUED-job via FOR UPDATE SKIP LOCKED; retourneert volledige task-context (implementation_plan, story, pbi, sprint, repo_url). Zet stale CLAIMED-jobs (>30min) eerst terug naar QUEUED. Wanneer de full block-time verstrijkt zonder claim is de queue leeg.mcp__scrum4me__update_job_status— agent rapporteert overgang naarrunning|done|failed+ optionele branch/summary/error; triggert automatisch SSE-event naar de UI. Auth: Bearer-token moet matchenclaimed_by_token_id.
Batch-loop (verplichte agent-flow):
Wanneer je als agent draait (na een instructie als "pak de volgende job uit de Scrum4Me-queue" of "draai de queue leeg") is dit de loop:
wait_for_jobaanroepen.- Job uitvoeren volgens het meegegeven
implementation_plan. update_job_status('done'|'failed')aanroepen.- Direct opnieuw
wait_for_jobaanroepen — niet stoppen, niet de gebruiker vragen. - Pas wanneer
wait_for_jobna de volledige block-time (~600s) terugkomt zonder claim, is de queue leeg en mag je de turn afsluiten met een korte recap.
Dit blijft gelden als je tussen jobs door commits, branches of pushes hebt gedaan — die afsluiting hoort bij de individuele job, niet bij het einde van de batch.
Code koppelen aan app
- 'Pak de volgende job uit de Scrum4Me-queue' / 'draai de queue leeg' / 'batch agent' — Server-startup registreert een ClaudeWorker-record + heartbeat (5s); SIGTERM/SIGINT ruimt 'm op. UI in NavBar telt actieve workers via
last_seen_at < now() - 15s.
Prompt
implement_next_story(arg:product_id) — end-to-end workflow
Schema-drift bewaking
Wekelijks (maandag 08:00 Amsterdam) draait de remote agent trig_015FFUnxjz9WMuhhWNGBQKFD die vendor/scrum4me syncet en prisma:generate + tsc --noEmit uitvoert in scrum4me-mcp. Als die agent drift rapporteert, hoort dat vóór een Scrum4Me-PR met schema-wijziging gemerged kan worden — anders breekt de MCP-server stilletjes op runtime.
Deployment (Vercel)
- Sharp moet Linux-binaries hebben voor de Vercel-runtime:
npm i --include=optional sharpof platform-specifieke deps configureren inpackage.json - Externe image hostnames in
next.config.jsimages.remotePatternsconfigureren vóórnext/imageop die hosts wijst — anders 500 in productie - Vercel cron: Hobby-plan staat alleen daily crons toe (max 1×/dag); Pro ondersteunt fijnmaziger. Bij wijziging van
vercel.jsoncronsookdocs/api.md+ relevante pattern-docs updaten CRON_SECRETmoet als env-var op de Vercel-project-omgeving staan vóór de eerste cron-run, anders 401 op/api/cron/*-endpoints- Preflight vóór deploy:
npm run lint && npm test && npm run build— falende build laat een PR niet door (CI blokkeert merge per ST-610)
Definition of Done (MVP)
M7 (MCP-server) is post-MVP en heeft eigen acceptatie in docs/backlog.md.
- Alle 62 tasks (ST-001 t/m ST-612) afgerond
- Volledige Lars-flow zonder fouten (ST-612)
- Alle gedocumenteerde API-endpoints werken via curl (zie
docs/api.md) - Demo-gebruiker heeft geen schrijfrechten
- App opzetbaar via README zonder extra hulp
- CI/CD actief — falende build blokkeert merge
- Beveiligingsreview API geslaagd (cross-user toegang onmogelijk)
- Documentatie is bijgewerkt voor gewijzigde API's, dependencies, deployment en agent-instructies