# Website Workspace Contract Dit document is voor wie de publieke website bouwt die naast de SlpModularCms-admin draait. Je hoeft de rest van deze repository niet te lezen om een werkende site te kunnen opleveren — dit contract is compleet genoeg om zelfstandig te volgen. ## Doelpad De website hoort in **`wwwroot/web/`**, in de root van de gepubliceerde applicatie. Dit pad **moet** minimaal een `index.html` bevatten. Alles onder `wwwroot/web/` is van jou — de applicatie zelf raakt deze map nooit aan buiten het plaatsen van de bestanden die je aanlevert, en een CMS-deploy verwijdert of overschrijft de inhoud nooit (zie "Waarom dit veilig is" hieronder). ``` wwwroot/ web/ ← jouw site komt hier (dit contract) index.html ← verplicht assets/... ... admin/ ← VERBODEN — dit is de CMS admin-UI, hoort niet bij deze repo ``` ## Verboden en gereserveerde paden **Verboden** — plaats hier nooit bestanden: - `wwwroot/admin/` — dit is de CMS admin-single-page-app, wordt door deze repository zelf beheerd en bij elke build overschreven - De applicatie-root zelf (waar de `.dll`-bestanden van de API staan) **Gereserveerd** — deze paden bestaan al en je site mag er niet mee botsen: - `/admin` — de CMS admin-UI - `/api/v1` — de backend-API - `/health` — infrastructuur-liveness-check (zie hieronder — dit is geen CMS-functionaliteit) Als jouw site een eigen route of bestand op een van deze paden zou plaatsen, wint de gereserveerde route altijd. ## Routing (SPA-fallback) Voor paden die **geen bestandsextensie** hebben (bijv. `/over-ons`, `/producten/123`) valt de applicatie terug op **`wwwroot/web/index.html`** — zo werkt client-side routing (React Router, Vue Router, of vergelijkbaar) zoals verwacht. Voor paden die er wél uitzien als een bestand (bijv. `/assets/logo.png`) geldt geen fallback: ontbreekt het bestand, dan krijg je gewoon een `404`, niet per ongeluk de `index.html`. Dit betekent: bouw je een Single Page Application, dan hoeft je routing-configuratie niets speciaals te doen voor deze server — de fallback wordt door de applicatie zelf verzorgd. ## De API aanroepen Roep `/api/v1/...` aan met **relatieve URL's** (bijv. `fetch('/api/v1/System/capabilities')`). Omdat je site en de API door hetzelfde proces op dezelfde origin worden geserveerd, is dit een **same-origin request** — er is geen CORS-configuratie nodig, en er hoeft niets ingesteld te worden om dit te laten werken. ## Content-Security-Policy Jouw site valt onder het **`Relaxed`**-beleid (de standaardpolicy voor alle paden die niet expliciet `Strict` zijn — `/admin`, `/api/v1` en `/health` krijgen `Strict`, `/` (jouw site) niet). Dit beleid is bewust minder streng, zodat je niet gebonden bent aan restricties die voor de CMS-admin gelden maar die je als website-bouwer nooit zou hoeven kennen. De exacte permissieve/strikte policy-definities staan in code (`SlpModularCms.Core`), niet in configuratie — je hoeft ze niet zelf te lezen om te weten dat je site onder het permissieve beleid valt. ## Umami-analytics insluiten Als de instantie analytics gebruikt, wordt het Umami-trackingscript geladen via een build-time omgevingsvariabele op de **admin**-kant (`VITE_UMAMI_SCRIPT_URL` / `VITE_UMAMI_WEBSITE_ID`) — dat script wordt dus niet door jouw site zelf ingesloten. Wil je dat jouw website ook gemeten wordt via dezelfde Umami-instantie, vraag dan de scriptregel en het bijbehorende website-ID op bij wie de CMS beheert, en neem die regel zelf op in je `index.html` (Umami's standaard `