--- title: System Architecture created: 2026-04-08 updated: 2026-04-08 status: evolving tags: [architecture, stack, docker, layers] sources: [docker-compose.yml, composer.json, package.json, ai-service/app/main.py] --- # System Architecture ## Stack | Layer | Technology | Version | |---|---|---| | Backend | Laravel (PHP) | 13.0 / PHP 8.3+ | | Frontend | Vue 3 + Inertia.js | Vue 3.5, Inertia 3 | | Build | Vite | 8.0 | | Styling | Tailwind CSS | 4.2 | | Visualization | D3.js | 7.9 | | Database | PostgreSQL + pgvector | 16 | | Cache / Queue | Redis | alpine | | AI Service | Python FastAPI | 0.1.0 | | Auth | Laravel Fortify + Sanctum | Fortify 1.36, Sanctum 4.0 | | Fonts | VT323, Press Start 2P, IBM Plex Mono | — | ## Architecture Principles 1. **Service-oriented** — domain logic lives in service classes (`app/Services/`), not controllers 2. **Event-driven** — status transitions go through transactional methods with audit logging 3. **API-first** — all functionality reachable via REST endpoints 4. **Audit trail** — all mutations logged to `audit_logs` table (append-only) 5. **AI content labeled** — AI-generated content marked and requires human confirmation 6. **Inertia SPA** — server-side routing (Laravel) with client-side rendering (Vue 3), no separate API layer needed for pages ## Docker Topology ``` ┌─────────────────────────────────────────────────────────┐ │ nginx:alpine ─────────────────────────────→ :80 │ │ │ │ │ ▼ │ │ laravel-app (PHP 8.4-FPM) │ │ │ │ │ ├── laravel-worker (queue:work) │ │ ├── laravel-scheduler (cron) │ │ │ │ │ ┌───▼────────────┐ ┌─────────────────┐ │ │ │ postgresql:16 │ │ redis:alpine │ │ │ │ + pgvector │ │ cache/queue │ │ │ │ :5432 │ │ :6379 │ │ │ └─────────────────┘ └─────────────────┘ │ │ │ │ ai-service (Python FastAPI) ──────────────→ :8000 │ │ └── connects to postgresql for embeddings │ └─────────────────────────────────────────────────────────┘ ``` 7 services total. All on `innovatieplatform` bridge network. ## Data Flow ### Page Rendering (Inertia) ``` Browser → nginx → PHP-FPM → Laravel Router → Controller → Service (business logic) → Inertia::render('Page', $data) → Vue component receives props → D3.js renders metro map canvas ``` ### API Calls (Map data) ``` Vue component → axios GET /api/map/strategy → MapController::apiStrategy() → MapDataService::getStrategyMap() → Eloquent queries (Thema → Speerpunten → Projects) → JSON response {lines, nodes, connections, level} → D3 re-renders canvas ``` ### AI Integration (planned) ``` CliBar.vue → POST /api/chat → Laravel proxy → ai-service:8000/api/chat → LangGraph agent → Anthropic Claude → RAG: pgvector similarity search on documents → Response with source attribution → CliBar displays with [AI] prefix ``` ## Key Service Classes | Service | LOC | Responsibility | |---|---|---| | `ProjectService` | 186 | Project CRUD, lifecycle transitions, park/stop, audit logging | | `MapDataService` | 165 | Build metro map data structures (Level 1: strategy, Level 2: project) | | `ThemaService` | 60 | Theme CRUD operations | ## Configuration - **Session/Cache/Queue**: All Redis-backed (`config/session.php`, `config/cache.php`, `config/queue.php`) - **Database**: PostgreSQL with pgvector extension for embedding vectors - **Auth**: Fortify handles registration/login/password flows, Sanctum for API tokens - **OPcache**: Production-optimized (`docker/php/opcache.ini`) - **Gzip**: Enabled in nginx config