---
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
