Files
crewli/resources/design/dev-guide.md

760 lines
29 KiB
Markdown

# Crewli Development Guide
Cursor & Claude Code — Van Leeg Project naar Productie
**Versie:** 1.0 | **Datum:** Maart 2026 | **Stack:** Laravel 12 + Vue 3 | **AI Tools:** Cursor + Claude Code
## 1. Strategie & Mindset
Cursor vs Claude Code — wanneer gebruik je wat?
Voordat je begint met ontwikkelen is het belangrijk te begrijpen hoe Cursor en Claude Code zich tot elkaar verhouden. Ze zijn complementair — niet concurrerend.
| **Tool** | **Wanneer inzetten** |
|----|----|
| Cursor (IDE) | Dagelijks coderen. Inline autocomplete, context-aware suggesties, kleine refactors, code reviews, directe file-edits. Beste voor: een specifiek component bouwen, een bug fixen, een test schrijven. |
| Claude Code (Terminal) | Grote, multi-file taken. Scaffolding van een volledig module (migrations + model + controller + tests + Vue-pagina). Autonome agent die zelfstandig werkt, tests uitvoert en fouten corrigeert. Beste voor: 'Bouw het volledige shift-module end-to-end.' |
| Samen | Aanbevolen workflow: Claude Code genereert het skelet en alle bestanden. Cursor verfijnt, debugt en voegt details toe. Claude Code draait de test-suite. Cursor doet code review en stijlcorrecties. |
> **KERNPRINCIPE**
>
> Claude Code is je senior developer die grote blokken werk autonoom uitvoert.
>
> Cursor is je pair programmer die naast je zit terwijl jij zelf ook werkt.
>
> Jij bent de architect en product owner: jij beslist, zij bouwen.
## 2. De Eerste Stappen
Wat je vandaag doet voordat je één regel code schrijft
### 2.1 Repository structuur definitief maken
Controleer en bevestig de folderstructuur
Jouw huidige setup heeft al een goede basis. Bevestig of maak de volgende structuur:
```
crewli/ # Monorepo root
├── api/ # Laravel 12 backend
│ ├── app/
│ │ ├── Http/
│ │ │ ├── Controllers/Api/V1/
│ │ │ ├── Middleware/
│ │ │ └── Requests/ # Form Requests per endpoint
│ │ ├── Models/
│ │ ├── Policies/ # Laravel Policies per model
│ │ ├── Services/ # Business logic buiten controllers
│ │ ├── Events/ + Listeners/
│ │ └── Jobs/ # Queue jobs (briefings, PDF, notifs)
│ ├── database/
│ │ ├── migrations/
│ │ ├── factories/
│ │ └── seeders/
│ └── tests/Feature/Api/V1/ # PHPUnit feature tests per controller
├── apps/
│ ├── admin/ # Super Admin SPA (Vuexy)
│ ├── app/ # Organizer SPA (Vuexy) -- HOOFDAPP
│ └── portal/ # Externe portals (vrijwilliger, artiest, leverancier)
├── docs/ # Design document, API docs, ERD
│ ├── design-document.md
│ └── dev-guide.md
└── .cursorrules # Cursor workspace rules
```
### 2.2 Dependencies installeren
Backend en frontend klaarstomen
**Backend (api/)**
```bash
cd api
# Spatie permissions (rollen/permissies)
composer require spatie/laravel-permission
# Audit log
composer require spatie/laravel-activitylog
# Media library (bestandsbeheer)
composer require spatie/laravel-medialibrary
# PDF generatie
composer require barryvdh/laravel-dompdf
# QR codes
composer require endroid/qr-code
# Publiceer Spatie configs
php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider"
php artisan vendor:publish --provider="Spatie\LaravelActivitylog\ActivitylogServiceProvider"
```
**Frontend — alle apps (apps/app/, apps/admin/, apps/portal/)**
```bash
# TanStack Query voor API state management
npm install @tanstack/vue-query
# Formuliervalidatie
npm install vee-validate zod @vee-validate/zod
# Drag-and-drop (form builder, timetable, prioriteitsranking)
npm install vuedraggable@next
# In apps/app/ en apps/admin/ ook:
npm install @fullcalendar/vue3 @fullcalendar/timeline @fullcalendar/resource-timeline
```
### 2.3 CLAUDE.md aanmaken
Het belangrijkste bestand in je hele repo
CLAUDE.md is de instructieset voor Claude Code. Het wordt automatisch geladen bij elke sessie. Dit bestand is de meest impactvolle investering die je doet — een uur hieraan besteden bespaart honderden uren aan correcties.
Maak aan: /crewli/CLAUDE.md (root niveau, zodat het voor alle sub-projecten geldt)
## 3. Helper Files — Volledige Inhoud
De exacte bestanden die je aanmaakt voor de eerste prompt
### 3.1 CLAUDE.md — Root niveau
Dit is de volledige, aanbevolen inhoud voor je CLAUDE.md. Kopieer dit letterlijk en pas aan waar nodig.
```
# Crewli — Claude Code Instructies
## Project Context
Crewli is een multi-tenant SaaS platform voor event- en festivalbeheer.
Gebouwd voor een professionele vrijwilligersorganisatie, met SaaS-uitbreidingspotentieel.
Design Document: /resources/design/design-document.md
## Tech Stack
- Backend: PHP 8.2+, Laravel 12, Sanctum, Spatie Permission, MySQL 8, Redis
- Frontend: TypeScript, Vue 3 (Composition API), Vuexy/Vuetify, Pinia, TanStack Query
- Testing: PHPUnit (backend), Vitest (frontend)
## Repository Structuur
- api/ Laravel backend
- apps/app/ Organizer SPA (hoofdapp)
- apps/admin/ Super Admin SPA
- apps/portal/ Externe portals (vrijwilliger, artiest, leverancier)
## Backend Regels (STRIKT VOLGEN)
### Multi-tenancy
- ELKE query op event-data MOET scoperen op organisation_id
- Gebruik OrganisationScope als Eloquent Global Scope op alle event-gerelateerde modellen
- Nooit directe id-checks in controllers — gebruik altijd Policies
### Controllers
- Gebruik Resource Controllers (index/show/store/update/destroy)
- Namespace: App\Http\Controllers\Api\V1\
- Alle responses via API Resources (nooit model-attributen direct teruggeven)
- Validatie via Form Requests (nooit inline validate())
### Modellen
- Gebruik HasUlids trait op alle business-modellen (GEEN UUID v4)
- Soft deletes op: Organisation, Event, FestivalSection, Shift, ShiftAssignment, Person, Artist
- GEEN soft deletes op: CheckIn, BriefingSend, MessageReply, ShiftWaitlist (audit-records)
- JSON kolommen ALLEEN voor opaque configuratie — nooit voor queryable data
### Database
- Primaire sleutels: ULID via HasUlids (niet UUID v4, niet auto-increment voor business tables)
- Elke migratie in volgorde aanmaken: eerst foundation, dan afhankelijke tabellen
- ALTIJD composite indexes toevoegen zoals gedocumenteerd in het design document sectie 3.5
### Rollen & Permissies
- Gebruik Spatie laravel-permission
- Check rollen via $user->hasRole() en Policies — nooit hardcoded role strings in controllers
- Drie niveaus: app (super_admin), organisatie (org_admin/org_member), event (event_manager etc.)
### Testing
- Schrijf PHPUnit Feature Tests per controller
- Minimaal per endpoint: happy path + unauthenticated (401) + wrong organisation (403)
- Gebruik factories voor alle test-data
- Draai tests NA elke module: php artisan test --filter=ModuleNaam
## Frontend Regels (STRIKT VOLGEN)
### Vue Componenten
- Altijd <script setup lang='ts'> — nooit Options API
- Props altijd getypeerd met defineProps<{...}>()
- Emits altijd gedeclareerd met defineEmits<{...}>()
### API Calls
- Gebruik TanStack Query (useQuery / useMutation) voor ALLE API calls
- Nooit direct axios in een component — altijd via een composable in composables/api/
- Pinia stores voor cross-component state — nooit prop drilling
### Naamgeving
- DB kolommen: snake_case
- TypeScript/JS variabelen: camelCase
- Vue componenten: PascalCase (bijv. ShiftAssignPanel.vue)
- Composables: use-prefix (bijv. useShifts.ts)
- Pinia stores: use-suffix store (bijv. useEventStore.ts)
### UI
- Gebruik ALTIJD Vuexy/Vuetify componenten voor layout, forms, tabellen, dialogen
- Nooit custom CSS schrijven als een Vuetify klasse bestaat
- Responsief: mobile-first, minimaal werkend op 375px breedte
## Verboden Patronen
- NOOIT: $user->role === 'admin' (gebruik policies)
- NOOIT: Model::all() zonder where-clausule (altijd scopen)
- NOOIT: dd() of var_dump() achterlaten in code
- NOOIT: .env waarden hardcoden in code
- NOOIT: JSON kolommen gebruiken voor data waarop gefilterd wordt
- NOOIT: UUID v4 als primaire sleutel (gebruik HasUlids)
## Volgorde bij elke nieuwe module
1. Migratie(s) aanmaken en draaien
2. Eloquent Model met relaties, scopes en HasUlids
3. Factory voor test-data
4. Policy voor autorisatie
5. Form Request(s) voor validatie
6. API Resource voor response transformatie
7. Resource Controller
8. Routes registreren in api.php
9. PHPUnit Feature Test schrijven en draaien
10. Vue composable voor API calls (useModuleNaam.ts)
11. Pinia store indien cross-component state nodig
12. Vue pagina component
13. Route toevoegen in Vue Router
```
### 3.2 .cursorrules — Root niveau
Dit is het equivalent van CLAUDE.md maar voor Cursor's autocomplete en inline AI. Korter en meer gefocust op directe code-stijl.
```
# Crewli Cursor Rules
## Stack
PHP 8.2 + Laravel 12 | TypeScript + Vue 3 + Vuexy/Vuetify | Pinia + TanStack Query
## Laravel
- Resource Controllers, Form Requests, API Resources — altijd
- HasUlids op business modellen, HasFactory, SoftDeletes waar gedocumenteerd
- Global Scope OrganisationScope op event-gerelateerde modellen
- Policies voor autorisatie, nooit inline role checks
## Vue 3
- <script setup lang='ts'> altijd
- TanStack Query voor API state, Pinia voor UI state
- Vuetify componenten eerst, custom CSS als laatste redmiddel
## Naamgeving
- snake_case DB | camelCase JS | PascalCase Vue | use* composables | use*Store Pinia
## Tests
- PHPUnit Feature Test per controller, minimaal: 200 + 401 + 403
```
### 3.3 docs/SCHEMA.md — Levend schema-document
Maak een Markdown bestand aan in /docs/ dat de tabel-definitie bevat als platte tekst. Claude Code gebruikt dit als primaire referentie bij het genereren van migraties.
```
# Crewli Database Schema
# Versie: 1.3 | Gegenereerd vanuit Design Document
## Regels
- Primaire sleutels: ULID via HasUlids (nooit UUID v4)
- Soft delete: zie lijst per tabel hieronder
- JSON kolommen: alleen voor opaque config
## Tabellen
### users
- id (ulid, PK)
- name (string)
- email (string, unique)
- password (string)
- timezone (string, default: Europe/Amsterdam)
- locale (string, default: nl)
- avatar (string, nullable)
- email_verified_at (timestamp, nullable)
- deleted_at (timestamp, nullable) -- soft delete
### organisations
- id (ulid, PK)
- name (string)
- slug (string, unique)
- billing_status (enum: trial|active|suspended|cancelled, default: trial)
- settings (json, nullable) -- UI display prefs only
- deleted_at (timestamp, nullable)
# ... (volledig schema uit Design Document sectie 3.5)
```
### 3.4 docs/API.md — API contract
Een simpele route-lijst die Claude Code gebruikt als referentie bij het genereren van controllers en Vue composables.
```
# Crewli API Contract
# Base: /api/v1/
# Auth: Bearer token (Sanctum)
## Auth
POST /auth/login
POST /auth/logout
GET /auth/me
## Organisations
GET /organisations -- lijst (super admin)
POST /organisations -- aanmaken
GET /organisations/{org} -- detail
PUT /organisations/{org} -- bijwerken
GET /organisations/{org}/members -- leden
POST /organisations/{org}/invite -- uitnodigen
## Events
GET /organisations/{org}/events
POST /organisations/{org}/events
GET /organisations/{org}/events/{event}
PUT /organisations/{org}/events/{event}
## Festival Sections
GET /events/{event}/sections
POST /events/{event}/sections
GET /events/{event}/sections/{section}
## Time Slots
GET /events/{event}/time-slots
POST /events/{event}/time-slots
## Shifts
GET /events/{event}/sections/{section}/shifts
POST /events/{event}/sections/{section}/shifts
PUT /events/{event}/sections/{section}/shifts/{shift}
POST /events/{event}/sections/{section}/shifts/{shift}/assign
POST /events/{event}/sections/{section}/shifts/{shift}/claim
## Persons
GET /events/{event}/persons
POST /events/{event}/persons
GET /events/{event}/persons/{person}
PUT /events/{event}/persons/{person}
POST /events/{event}/persons/{person}/approve
# ... (volledig API contract uitbreiden per module)
```
## 4. Development Workflow
Hoe je van leeg project naar werkende feature gaat
Elke feature volgt dezelfde drielaagse workflow. Commit altijd per voltooide laag — nooit halfafgebouwde code in main.
| **Laag** | **Wat je doet en met welk tool** |
|----|----|
| Laag 1 — Backend (API) | Claude Code genereert: migratie + model + factory + policy + form request + resource + controller + test. Jij reviewt en draait tests. |
| Laag 2 — Frontend (Vue) | Claude Code genereert: composable + Pinia store + Vue pagina + router entry. Cursor verfijnt de UI met Vuexy componenten. |
| Laag 3 — Integration | Cursor: verbind frontend met backend. Test end-to-end. Fix type-errors. Review mobile weergave. |
### 4.1 De Module-generatie volgorde
Altijd in deze volgorde. Nooit stappen overslaan — later toevoegen kost meer tijd dan nu correct doen.
| **Stap** | **Commando / Actie** |
|----|----|
| 1. Migratie | php artisan make:migration create_shifts_table |
| 2. Model | php artisan make:model Shift -mfp (migration + factory + policy) |
| 3. Form Request | php artisan make:request StoreShiftRequest + UpdateShiftRequest |
| 4. API Resource | php artisan make:resource ShiftResource + ShiftCollection |
| 5. Controller | php artisan make:controller Api/V1/ShiftController --api |
| 6. Registreer routes | In api/routes/api.php toevoegen |
| 7. Test | php artisan make:test ShiftControllerTest + draaien |
| 8. Composable | apps/app/src/composables/api/useShifts.ts aanmaken |
| 9. Store (indien nodig) | apps/app/src/stores/useShiftStore.ts |
| 10. Vue pagina | apps/app/src/pages/sections/[id]/shifts.vue |
| 11. Route | apps/app/src/router/index.ts |
### 4.2 Fase-planning: wat bouw je wanneer
| **Fase** | **Inhoud** |
|----|----|
| Fase 1 — Foundation (nu) | Auth (login/logout/me), Organisations CRUD, Events CRUD, User invitations, Multi-tenant scope, Roles & permissions setup, Basis dashboard shell |
| Fase 2 — Core Operations | Persons & Crowd Types, Festival Sections + Time Slots + Shifts, Shift claiming + goedkeuring, Vrijwilligers registratie + portaal, Accreditatie engine, Basis briefings |
| Fase 3 — Advancing & Show Day | Artist advancing + portaal, Timetable, Mission Control, Formulierbouwer, Post-festival evaluatie, PDF allocatiesheet, Campagnes (email + WhatsApp via Zender) |
| Fase 4 — Differentiators | Real-time WebSockets, Show Day Mode, Vrijwilligersprofiel + festival-paspoort, Shift swap & wachtlijst, Retrospectief rapport, Leveranciersportaal uitgebreid |
## 5. Prompt Bibliotheek
Kant-en-klare prompts voor elke ontwikkelstap
Gebruik deze prompts letterlijk of als basis. De meest effectieve prompts zijn: specifiek, contextueel en taak-gebaseerd. Verwijs altijd naar de docs/ bestanden die je hebt aangemaakt.
### 5.1 Kickstart prompts
> **Fase 1 kickstart — Alles genereren in een sweep**
>
> Lees /resources/design/design-document.md sectie 3.5 (schema) en /CLAUDE.md.
>
> Genereer alle Fase 1 componenten in de juiste volgorde:
>
> 1. Migrations voor: users (update), organisations, organisation_user, user_invitations, events, event_user_roles
> 2. Eloquent modellen met HasUlids, relaties, OrganisationScope global scope waar van toepassing
> 3. Factories met realistic test data
> 4. Spatie Permission seeder: maak rollen aan (super_admin, org_admin, org_member, event_manager, staff_coordinator, volunteer_coordinator)
> 5. Auth controller (login/logout/me) met Sanctum
> 6. Organisations controller (CRUD) met Policy en Feature Test
> 7. Events controller (CRUD) met Policy en Feature Test
>
> Draai na elke stap: php artisan test. Los fouten op voor je verder gaat.
> **Module genereren — Shifts als voorbeeld**
>
> Lees /CLAUDE.md en /docs/SCHEMA.md voor de shifts tabel definitie.
>
> Bouw het volledige Shifts module in de volgorde uit CLAUDE.md sectie 'Volgorde bij elke nieuwe module'.
>
> Specifieke eisen voor Shifts:
>
> - time_slot_id MOET gedenormaliseerd worden in shift_assignments voor de UNIQUE(person_id, time_slot_id) constraint
> - ShiftAssignment heeft een status machine: pending_approval > approved/rejected/cancelled/completed
> - Auto-approve is configureerbaar per shift (auto_approved bool op shift niveau)
> - Bij approve: stuur notificatie naar vrijwilliger (queued job, gebruik ZenderService voor WhatsApp)
> - ShiftResource moet slots_filled (count van approved assignments) en fill_rate (percentage) berekend teruggeven
>
> Eindig met: php artisan test --filter=Shift
### 5.2 Backend prompts
> **Migration genereren**
>
> Genereer een Laravel migratie voor de tabel [TABELNAAM] op basis van /docs/SCHEMA.md.
>
> Gebruik $table->ulid('id')->primary() als PK.
>
> Voeg alle indexes toe zoals gedocumenteerd (composite indexes, unique constraints).
>
> Voeg timestamps() en softDeletes() toe indien van toepassing per CLAUDE.md.
>
> Gebruik constrained() op alle foreign keys voor cascade-gedrag.
> **Model met alle features**
>
> Genereer het Eloquent model voor [MODELNAAM].
>
> Gebruik: HasUlids, HasFactory, SoftDeletes (indien van toepassing).
>
> Voeg toe: OrganisationScope global scope, alle relaties (hasMany, belongsTo, belongsToMany),
> computed accessors (fill_rate, available_slots), status-gerelateerde scopes (scopePending, scopeApproved),
> en $fillable of $guarded array.
>
> Schrijf ook de factory met realistic Nederlandse testdata.
> **API Resource met computed velden**
>
> Genereer een Laravel API Resource voor [MODELNAAM].
>
> Voeg toe: alle relevante velden, computed velden (fill_rate, status_label),
> conditioneel geladen relaties (whenLoaded), en wanneer van toepassing: when() voor permissie-afhankelijke velden.
>
> De Resource mag NOOIT model-attributen direct weggeven zonder transformatie.
> **Feature test schrijven**
>
> Schrijf een PHPUnit Feature Test voor [CONTROLLERNAAM].
>
> Dek minimaal af: index (200), show (200), store (201), update (200), destroy (204),
> unauthenticated (401 op alle routes), wrong organisation (403), validatiefouten (422).
>
> Gebruik RefreshDatabase, ActingAs met correcte rol via Spatie Permission.
>
> Maak test data via factories — nooit hardcoded IDs.
> **ZenderService aanmaken (WhatsApp/SMS)**
>
> Maak app/Services/ZenderService.php aan.
>
> Zender is een self-hosted SMS/WhatsApp gateway (CodeCanyon product).
>
> Config: ZENDER_API_URL en ZENDER_API_KEY uit .env.
>
> Methoden: sendSms(string $to, string $message): bool
> sendWhatsApp(string $to, string $message): bool
> sendByUrgency(string $to, string $message, string $urgency): bool
>
> urgency: normal=email only, urgent=whatsapp, emergency=sms+whatsapp parallel
>
> Gebruik Laravel HTTP Client (Http::). Log alle sends via activitylog.
>
> Schrijf ook een ZenderServiceTest met HTTP fake.
### 5.3 Frontend prompts
> **Vue pagina voor een lijst-overzicht**
>
> Maak apps/app/src/pages/[module]/index.vue.
>
> Gebruik \<script setup lang='ts'\>.
>
> API calls via useQuery() uit TanStack Query — niet direct axios.
>
> Tabel via VDataTable van Vuetify — niet custom HTML.
>
> Bovenaan: status KPI-tiles (totaal, goedgekeurd, pending) als klikbare VCard componenten.
>
> Rij klik: opent een side panel (niet navigeert naar nieuwe pagina) met detail-informatie.
>
> Loading state: VSkeleton loader. Error state: VAlert met retry knop.
>
> Mobiel: tabel collapst naar een VList op viewport < 768px.
> **Composable voor API calls**
>
> Maak apps/app/src/composables/api/use[Module].ts.
>
> Exporteer: use[Module]List (useQuery), use[Module]Detail (useQuery met id param),
> useCreate[Module] (useMutation), useUpdate[Module] (useMutation), useDelete[Module] (useMutation).
>
> Gebruik axios via de centrale api.ts instance (met Sanctum CSRF en auth header).
>
> Mutations invalideren automatisch de relevante query keys na succes.
>
> Alle response types volledig getypeerd via TypeScript interfaces in types/[module].ts.
> **Pinia store aanmaken**
>
> Maak apps/app/src/stores/use[Module]Store.ts.
>
> Gebruik defineStore met Setup syntax (niet Options syntax).
>
> Sla op: geselecteerde IDs, UI state (open sidepanel, actief tab), filters.
>
> NIET in Pinia: server data (dat zit in TanStack Query). Pinia is alleen voor UI state.
>
> Exporteer: alle state als readonly via storeToRefs.
> **Shift claim workflow — volledig end-to-end**
>
> Bouw de volledige shift claim workflow:
>
> Backend: POST /shifts/{shift}/claim endpoint in ShiftController.
>
> - Valideer: shift heeft slots_open_for_claiming beschikbaar
> - Valideer: geen bestaande approved assignment voor zelfde time_slot_id voor deze person
> - Maak ShiftAssignment aan met status=pending_approval
> - Dispatch NotifyCoordinatorOfClaimJob (queued)
> - Return ShiftAssignmentResource
>
> Frontend: 'Claim' knop in portal/shifts/index.vue.
>
> - Disable knop als conflict of geen slots beschikbaar
> - Na claim: toon 'Wachten op goedkeuring' badge
> - Optioneel: 'Op wachtlijst' knop als shift vol is
### 5.4 Agent-aanstuurprompts
> **Grote module — een prompt voor alles**
>
> Je bent een senior fullstack developer die werkt aan Crewli. Lees /CLAUDE.md volledig.
>
> Bouw het volledige [MODULE] module:
>
> Backend (in volgorde):
>
> 1. Migrations voor alle tabellen uit /docs/SCHEMA.md sectie [X.X]
> 2. Models met alle relaties, scopes en accessors
> 3. Factories
> 4. Policies
> 5. Form Requests
> 6. API Resources
> 7. Controllers
> 8. Routes
> 9. Feature tests — draai ze, los fouten op
>
> Frontend:
>
> 10. TypeScript types in apps/app/src/types/[module].ts
> 11. Composables in apps/app/src/composables/api/
> 12. Vue pagina's (lijst + detail side panel)
> 13. Router entries
>
> Stop na elke laag en vraag bevestiging voor je doorgaat.
>
> Als een test faalt: los het op voor je verdergaat — nooit overslaan.
> **Bug fix prompt**
>
> Er is een probleem met [BESCHRIJVING VAN HET PROBLEEM].
>
> Relevante bestanden: [BESTANDSPADEN].
>
> Foutmelding: [PLAK EXACTE ERROR].
>
> Verwacht gedrag: [WAT ZOU ER MOETEN GEBEUREN].
>
> Analyseer de oorzaak, schrijf een failing test die het probleem reproduceert,
> fix het probleem, en bevestig dat de test slaagt.
> **Code review prompt**
>
> Review de code in [BESTANDSPAD] als senior Laravel/Vue developer.
>
> Check specifiek op:
>
> - Multi-tenancy: wordt organisation_id correct gescopeerd?
> - Security: worden Policies gebruikt? Geen directe role-checks?
> - Performance: ontbrekende eager loading (N+1), ontbrekende indexes?
> - Conventies: volgt het CLAUDE.md regels?
> - Types: zijn alle TypeScript types volledig (geen any)?
>
> Geef concrete verbeterpunten met codevoorbeelden.
## 6. Agents — Autonome Ontwikkeling
Hoe je Claude Code en Cursor agents effectief inzet
### 6.1 Claude Code als Agent
Claude Code kan volledig autonoom werken: bestanden lezen, aanmaken, aanpassen, tests draaien en fouten corrigeren — zonder dat jij elke stap bevestigt. Dit is het krachtigste en snelste werkmode.
| **Mode** | **Wanneer gebruiken** |
|----|----|
| Interactief (standaard) | Als je wil meekijken en goedkeuren. Claude Code stelt elke actie voor en wacht. Gebruik voor: eerste keer een module bouwen, complexe refactors. |
| Autonoom (--dangerously-skip-permissions) | Als je een grote taak wil delegeren en wegloopt. Claude Code werkt door tot klaar. Gebruik voor: routine-modules die je eerder hebt gebouwd, test-driven fixes. |
| Aanbevolen aanpak | Start autonoom voor scaffolding. Schakel naar interactief bij UI-componenten of business-logica die project-specifieke kennis vereist. |
**Claude Code opstarten**
```bash
# Installeer Claude Code (eenmalig)
npm install -g @anthropic-ai/claude-code
# Start in je project root
cd /pad/naar/crewli
claude
# Of: direct met een taak
claude --print 'Genereer de Shift migration op basis van CLAUDE.md'
# Autonoom mode (voorzichtig gebruiken)
claude --dangerously-skip-permissions
```
### 6.2 Cursor Agent Mode
Cursor heeft een ingebouwde Agent mode die vergelijkbaar is met Claude Code maar geintegreerd in de IDE. Activeer via Cmd+Shift+P > 'Cursor: Open Agent'.
| **Feature** | **Gebruik** |
|----|----|
| @workspace | Geeft de agent toegang tot je hele codebase als context. Altijd meegeven bij module-niveau taken. |
| @file | Verwijs naar een specifiek bestand. Bijv: @CLAUDE.md @api/app/Models/Shift.php |
| @docs | Verwijs naar externe documentatie (Laravel docs, Vuetify docs). Cursor indexeert deze. |
| Composer mode | Meerdere bestanden tegelijk bewerken. Ideaal voor: tegelijk model + controller + test aanpassen. |
### 6.3 De optimale agent-workflow per dag
> **DAGELIJKSE ROUTINE**
>
> Ochtend: Open Claude Code. Geef de taak voor die dag: 'Bouw het volledig Persons module op basis van CLAUDE.md en SCHEMA.md.' Laat autonoom draaien.
>
> Middag: Review de gegenereerde code in Cursor. Check: volgt het de conventies? Zijn de tests groen? Zijn de TypeScript types compleet?
>
> Namiddag: Cursor voor UI fijnafstelling, Vuexy componenten integratie, visuele correcties.
>
> Einde dag: php artisan test (alle tests groen). Commit alles met duidelijke commit messages.
### 6.4 Context window management
Claude Code heeft een beperkt context window. Bij grote taken verliest het de context van eerdere bestanden. Beheer dit proactief:
- Begin elke nieuwe sessie met: 'Lees /CLAUDE.md voor je begint.'
- Verwijs expliciet naar relevante bestanden: 'Zie /docs/SCHEMA.md voor de tabel definitie.'
- Splits grote modules: 'Bouw eerst alleen de backend (stappen 1-9). Stop dan.'
- Na een context-verlies: geef een samenvatting: 'We bouwen Crewli. Tot nu toe klaar: auth, organisations, events. Nu: Shifts module backend.'
- Gebruik /docs/API.md als levend document — houd bij wat er al gebouwd is.
## 7. Tips, Valkuilen & Best Practices
Geleerd van ervaring — lees dit voordat je begint
### 7.1 De grootste tijdverspillers
| **Valkuil** | **Oplossing** |
|----|----|
| Te brede prompts: 'Bouw de hele app' | Altijd per module. Per module maximaal 1 laag tegelijk. Breed = vaag = slechte output. |
| CLAUDE.md niet up-to-date houden | Na elke architectuurbeslissing: update CLAUDE.md. Dit is je bron van waarheid. Verouderde regels leiden tot inconsistente code. |
| Tests overslaan 'want het werkt toch' | Schrijf tests altijd. AI-gegenereerde code heeft subtiele bugs die pas later opduiken. Tests vangen dit vroeg. |
| Alle gegenereerde code blindelings accepteren | Review altijd: check multi-tenancy scoping, check indexes, check error handling. AI mist soms subtiele business logica. |
| Frontend en backend tegelijk bouwen | Backend eerst, compleet en getest. Dan frontend. Nooit parallel — je verliest overzicht. |
| Geen versiecontrole per module | Commit na elke voltooide module (backend + frontend + tests). Kleine commits = makkelijk terugdraaien. |
### 7.2 Prompts die altijd goed werken
- **Geef altijd context: 'Crewli is een multi-tenant SaaS voor festival-organisatie...'**
- **Verwijs naar bestanden: 'Op basis van CLAUDE.md en SCHEMA.md...'**
- **Specificeer de output: 'Genereer X, Y en Z. Niets anders.'**
- **Vraag om uitleg: 'Leg uit waarom je deze aanpak kiest voor de shift conflict-check.'**
- **Gebruik iteratief: 'Dit klopt niet omdat... Pas aan en draai tests opnieuw.'**
### 7.3 Kwaliteitscontrole checklist
Gebruik dit als checklist voor elke voltooide module voordat je verder gaat:
| **Check** | **Wat je controleert** |
|----|----|
| Tests | php artisan test draait groen. Minimaal: 200, 401, 403 per endpoint. |
| Multi-tenancy | Elke query heeft organisation_id scope. Controleer via tinker. |
| N+1 queries | Gebruik Laravel Debugbar of query logging. Geen N+1 in lijst-endpoints. |
| TypeScript | Geen 'any' types in Vue composables en components. npx tsc --noEmit groen. |
| Mobile | Pagina is bruikbaar op 375px. Open Chrome DevTools en check. |
| Error states | Wat ziet een gebruiker bij: lege lijst, API fout, netwerk timeout? |
| CLAUDE.md | Geen verboden patronen (Model::all, hardcoded roles, UUID v4). |
### 7.4 Handige Laravel commando's
```bash
# Alles in een keer voor een nieuwe model
php artisan make:model Shift -a # model + migration + factory + seeder + policy + controller + resource
# Tests draaien
php artisan test # alle tests
php artisan test --filter=ShiftTest # specifieke test class
php artisan test --coverage # met coverage rapport
# Database
php artisan migrate:fresh --seed # reset + migreer + seed
php artisan tinker # REPL voor quick checks
# Routes inspecteren
php artisan route:list --path=api/v1 # alle API routes
# Queue (voor briefings, notificaties)
php artisan queue:work --queue=notifications,briefings,default
```
### 7.5 Eerste dag: exacte volgorde
| **#** | **Actie** |
|----|----|
| 1 | Repository structuur controleren (sectie 2, stap 01) |
| 2 | Dependencies installeren (sectie 2, stap 02) |
| 3 | CLAUDE.md aanmaken en invullen (sectie 3.1) |
| 4 | .cursorrules aanmaken (sectie 3.2) |
| 5 | docs/SCHEMA.md aanmaken met volledig schema uit design document |
| 6 | docs/API.md aanmaken met initiiele routes |
| 7 | Claude Code starten: 'Lees CLAUDE.md. Daarna: genereer Fase 1 — auth, organisations, events.' |
| 8 | Tests draaien: php artisan test — los fouten op |
| 9 | Commit: 'feat: fase 1 foundation — auth, organisations, events' |
| 10 | Morgen: Fase 2 starten met Persons & Crowd Types |
---
Crewli Development Guide v1.0 — Maart 2026