Root causes fixed:
1. branchAngle routing only matched 0° — now uses isExtendAngle()
for all extend angles (0/180/45/315), vertical (90/270) = fork
2. handleForkBranch did nothing at dim 1 — now opens thema form
3. After form submit, Inertia reloaded entire page losing canvas
dimension state — now uses axios + refreshMapData() via API
4. Custom metro node form used dead Inertia useForm refs
Changes:
- All creation flows now use axios POST + refreshMapData() which
fetches /api/map/strategy or /api/map/project/{id} without page
reload, preserving the canvas dimension and zoom state
- New thema creation modal (for ↑↓ fork at dim 1)
- Track creation modal updated to use axios (for ↑↓ fork in dim 2)
- Metro node creation modal updated to use axios
- CommitmentForm @close now triggers refreshMapData()
- CommitmentForm eigenaar_id now has required validation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Usage: git clone <repo> && cd innovatieplatform && bash setup.sh
The script:
- Checks for docker and docker compose v2
- Creates .env from .env.example with auto-generated APP_KEY
- Builds all 7 Docker containers
- Waits for PostgreSQL and Redis health checks
- Runs migrations and seeds with 2026 planning + student data
- Builds frontend (if npm available locally)
- Prints access URLs and credentials
Prerequisites: docker, docker compose. That's it.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
FIXES (from comprehensive audit):
- NodePreview: complete rewrite — 380px left panel with document
summaries, commitment list, phase track visualization, scrollable.
Fixed children count bug (was showing [object Object]).
Slides in from left (not right) to not overlap branch handles.
- CommitmentForm: added required validation on eigenaar_id field
- MetroMap: wired custom metro node creation with form + POST /metro-nodes
- MetroMap: removed dead handleCliCommand console.log
- MetroMap: added metro node creation modal (naam + beschrijving)
NEW — AI Service integration:
- ai-service/main.py: real Anthropic API integration via httpx
- Reads ANTHROPIC_API_KEY from env, uses claude-haiku-4-5-20251001
- /api/chat fetches project context from PostgreSQL (docs, commitments)
- /api/summarize sends content to Claude for summarization
- /api/search does basic text search on documents + kennis_artikelen
- AiController.php: Laravel proxy for /api/ai/chat → ai-service
- CliBar.vue: complete rewrite with async API calls, processing state,
error handling, conversation history, auto-scroll
- Receives projectId prop for context-scoped AI queries
- Shows "denken..." animation while waiting for response
- docker-compose.yml: passes ANTHROPIC_API_KEY to ai-service container
- config/services.php: ai service URL configuration
To activate AI: set ANTHROPIC_API_KEY in .env and rebuild ai-service.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
→ ← = extend same line (horizontal tracks)
↑ ↓ = new track (parallel line above/below)
↘ ↗ = new track (diagonal fork)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Visual distinction:
- Populated dimension: dashed cyan ring + [+] indicator
- Empty dimension: subtle gray dashed ring + [○] indicator
- No dimension: plain station (no ring)
Context menu changes:
- "Open dimension" on nodes that have children (zooms in directly)
- "Add dimension" on nodes without children (creates empty zoomable space)
- Removed old "Add child node" option
Add dimension creates an empty children structure on the node with
proper parent metadata. The node immediately shows the [○] indicator
and becomes zoomable. User enters and builds tracks with FAB + branch
handles. Truly recursive metro — any station can contain a world.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Zoom fix: The zoom handler was being completely removed during the
fit-to-view animation (svg.on('.zoom', null)), which meant D3's
transition dispatched zoom events that nobody handled — so `g` never
got its transform updated during the animation. The view stayed stuck
at the old scale until the user scrolled again.
Fix: Keep handleZoom active during commit animation. When isCommitting
is true, it only applies the visual transform (g.attr('transform'))
and skips threshold logic. This lets D3's transition smoothly animate
`g` to the fit-to-view position.
Branch handles: Removed the occupied-position check. In a real metro,
stations can be shared between lines (interchanges). Now all 3 branch
handles always appear. Ghost preview shows "interchange" label when
targeting an occupied position.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Phase 1 — Fit-to-view zoom:
- computeFitTransform() calculates bounding box and scales to fit all nodes
- Replaces hardcoded scale=1 reset in animateZoomReset() and initCanvas()
- Dim 1 no longer appears tiny after zooming out from dim 2
Phase 2 — Grid system:
- Shared gridConstants.js (GRID=50, GRID_STEP_X=200, GRID_STEP_Y=150)
- MapDataService snapToGrid() aligns all node positions server-side
- Canvas renders subtle grid lines (shown on interaction only, with fade)
- Line highlighting support via setHighlightedLine() for FAB hover
Phase 3 — Branch handles:
- Hover any station node → 3 "+" handles appear (0°/45°/315°)
- 0° extends the current line, 45°/315° fork to create new branch
- Ghost preview (dashed line + circle) on handle hover
- Handles only show at unoccupied grid positions
- Grid fades in during handle interaction, fades out after
Phase 4 — Custom tracks database:
- metro_lines table (project_id, naam, color, type, order)
- metro_nodes table (metro_line_id, naam, status, x, y, order)
- MetroLine + MetroNode models, controllers, routes
- Project.metroLines() relationship added
Phase 5+6 — FAB redesign + MetroMap wiring:
- FAB shows "Nieuw thema (lijn)" at root, "Nieuwe lijn" in project dim
- Track creation modal with retro-styled form
- MetroMap handles create-node events from branch handles
- Extend (0°) opens commitment/document form, fork opens track form
- Canvas context menu replaced with "hover to branch" hint
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- ai-service/convert.py: converts Office/PDF files to markdown with frontmatter
- database/seeders/data/: folder structure for themas, projects, documents, etc.
- database/seeders/data/raw/: drop zone for Office/PDF files to convert
- wiki/: project architecture, concepts, and knowledge graph documentation
- Remove unused Laravel example tests
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
MetroCanvas rewrite:
- Dimension stack: every node can contain children forming a sub-metro-map
- Zoom-triggered transitions: scroll-zoom near a node gradually cross-fades
parent dimension out and child dimension in (threshold 2.5x, range 1.5x)
- Zoom out past 0.5x transitions back to parent dimension
- Right-click context menu: "New node here" on canvas, "Edit/Add child/Delete" on stations
- Depth indicator HUD with back button
- Transition progress bar during cross-fade
- Nodes with children get dashed ring + glow indicator
Backend:
- MapDataService now includes children data inline per project node
- Each project's children contain lifecycle phases, commitments, documents as sub-map
- New API endpoint: GET /api/map/node/{type}/{id}/children for lazy loading
- Consistent data structure: every node has children field (null = leaf)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Frontend:
- Connect MetroMap to live Inertia props (replace hardcoded demo data)
- Drill-down navigation via router.visit for project-level maps
- Reactive breadcrumb based on map level
- Empty state when no projects exist
- Reusable Modal component with retro styling
- ProjectForm and CommitmentForm with Inertia useForm
- FormInput reusable component (text, date, textarea, select)
- FloatingActions FAB button for creating projects/themes
Backend:
- CommitmentService + CommitmentController (CRUD, mark complete, overdue)
- DocumentService + DocumentController (upload, download, delete)
- MapController now passes users and speerpunten to frontend
- 7 new routes (4 commitment, 3 document)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add top bar with breadcrumb (left) and user name + logout button (right)
- Move station labels below dots (centered) to prevent line overlap
- Move line labels further above stations
- Increase vertical spacing between metro lines (160px) for label clearance
- Align station x-coordinates for cleaner map layout
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Enable PHP OPcache in Docker (256MB, dev-friendly settings)
- Enable gzip compression in nginx + immutable caching for /build/ assets
- Reduce fonts to latin-only subsets (from 28 files to ~6)
- Lazy-load Vue pages via dynamic imports (D3 no longer loaded on login)
- MetroMap chunk split out separately (62KB only when needed)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add explicit $table property to all Eloquent models with Dutch names
- Fix pivot table names in belongsToMany relationships
- Fix seeder: use valid enum values for afhankelijkheden status
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Design interview completed. Core decisions:
- Zoomable metro map as primary navigation (strategy > project > detail)
- C64-style CLI bar for AI assistant at bottom
- Independent R&D color palette (dark theme, electric blues, neon accents)
- Full retro-futurism: monospace fonts, pixel accents, glow effects
- Bilingual NL/EN, informal tone
- Custom components (no off-the-shelf UI library)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>