Proof of Concept voor MijnOverheid Zakelijk https://proef.moza.rijksapp.dev/
  • JavaScript 58.9%
  • HTML 18.1%
  • CSS 14.1%
  • MDX 5.4%
  • Nunjucks 3.4%
  • Other 0.1%
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-06-04 18:00:26 +02:00
.agents/skills/caveman fix: recover caveman skill 2026-05-19 10:46:04 +02:00
.github/workflows 🦵 Tijdelijk opgehoogde time-out buildproces teruggebracht 2026-06-04 18:00:26 +02:00
.storybook E-mailvalidatie-flow 2026-04-09 19:50:38 +02:00
.vscode 🧼 CSS clean-up 2026-04-23 14:24:53 +02:00
_data Gemeentelijke subsidies 2026-06-04 16:51:13 +02:00
_includes Tabellen CSS geoptimaliseerd 2026-06-04 16:24:16 +02:00
agent-os/standards 📝 Overvloed aan Em dashes gewijzigd 2026-06-03 16:28:24 +02:00
assets 🧼 digitale-assistent.js: header-comment gelijkgetrokken met same-origin default 2026-06-04 09:17:48 +02:00
container ✏️ Reverse proxy via runtime BACKEND_ORIGIN + same-origin default (Kubernetes-DNS-resolver) 2026-06-03 10:55:04 +02:00
docs/superpowers Split Digitale-Assistent-backend naar eigen repo — frontend-only 2026-06-02 14:14:27 +02:00
inloggen Visuele afwijkingen Privé/Zakelijk/Gemachtigd 2026-06-03 18:32:50 +02:00
mailbox Visuele afwijkingen Privé/Zakelijk/Gemachtigd 2026-06-03 18:32:50 +02:00
mobu Tabellen CSS geoptimaliseerd 2026-06-04 16:24:16 +02:00
moza 🐛 List-indent berichtenbox 2026-06-04 16:56:05 +02:00
skills-internet@3e3184b4bf 🦵 Bump 2026-05-27 16:03:42 +02:00
stories Visuele afwijkingen Privé/Zakelijk/Gemachtigd 2026-06-03 18:32:50 +02:00
style Gemeentelijke subsidies 2026-06-04 16:51:13 +02:00
style-dictionary ️ Verbeterde focus-ring 2026-06-03 19:18:13 +02:00
tokens ️ Verbeterde focus-ring 2026-06-03 19:18:13 +02:00
.dockerignore ✏️ Storybook verwijderd ui .dockerignore 2026-03-24 14:29:26 +01:00
.eleventy.js ✏️ Mailbox includes 2026-05-27 18:43:55 +02:00
.eleventyignore ✏️ Mailbox includes 2026-05-27 18:43:55 +02:00
.gitignore Split Digitale-Assistent-backend naar eigen repo — frontend-only 2026-06-02 14:14:27 +02:00
.markuplintrc.json 🧼 CSS clean-up 2026-04-23 14:24:53 +02:00
.pre-commit-config.yaml Split Digitale-Assistent-backend naar eigen repo — frontend-only 2026-06-02 14:14:27 +02:00
.prettierignore ✏️ Berichtenbox wijzigingen 2026-04-15 15:05:12 +02:00
.prettierrc Externe link stijl 2026-03-02 17:04:25 +01:00
.stylelintrc.json 💄 Badge 2026-05-04 16:53:30 +02:00
CHANGELOG.md 🦵 Tijdelijk opgehoogde time-out buildproces teruggebracht 2026-06-04 18:00:26 +02:00
CLAUDE.md Merge branch 'main' into feat/move_DA 2026-06-04 08:22:31 +02:00
index-pages.html 🦵 POC freeze in time 2026-06-01 11:42:29 +02:00
index.html ↩️ Pre-flow gebruikersonderzoeken verwijderd 2026-03-11 14:55:38 +01:00
ontwerp-principes.md 📝 Overvloed aan Em dashes gewijzigd 2026-06-03 16:28:24 +02:00
package-lock.json 🧼 CSS optimalisatie 2026-04-23 14:50:38 +02:00
package.json ✏️ Reverse proxy via runtime BACKEND_ORIGIN + same-origin default (Kubernetes-DNS-resolver) 2026-06-03 10:55:04 +02:00
README.md Merge branch 'main' into feat/move_DA 2026-06-04 08:22:31 +02:00

MOZa proof of concept prototype

Zie Ontwerpprincipes voor de ontwerpprincipes, technische keuzes en relevante onderzoeken die ten grondslag liggen aan dit prototype.

Omgeving installeren

Clone deze repository lokaal.

Vereisten


Statische site-generator installeren

Eleventy wordt gebruikt om herhalende componenten zoals headers en footers als includes te beheren. Installeer Eleventy in de root van het project:

npm install @11ty/eleventy

Pagina's bouwen

Om de HTML pagina's te bouwen voer je dit commando uit vanuit de root van het project:

npx @11ty/eleventy

De gebouwde pagina's worden in de map _site geplaatst.

Lokaal bekijken

Start een lokale server met live reload:

npx @11ty/eleventy --serve

De site is vervolgens te bekijken op localhost:8080.

Includes

Herhalende componenten staan in de _includes map:

Bestand Beschrijving
base.njk Basis layout
header-rijksoverheid.njk Rijksoverheid header met logo en navigatie
header-overheid.njk Overheid header header met logo
footer-overheid.njk Overheid footer
side-nav-overheid.njk Overheid hoofdnavigatie
action-group.njk Actiegroep onder een topic (Bewaar, Deel, Niet relevant)

Elke pagina selecteert diens layout en opties bovenaan het bestand:

---
layout: base.njk
title: "Pagina titel"
headerType: overheid
footerType: overheid
---

Design tokens

Design tokens zijn ontwerp-waarden — zoals kleuren, typografie, maatvoering — opgeslagen in een platformonafhankelijk formaat (JSON). Ze vormen een gedeelde taal tussen ontwerp en ontwikkeling: in plaats van bijvoorbeeld losse hex-codes of pixelwaarden door te geven, verwijzen beide disciplines naar dezelfde bron. Hierdoor blijven ontwerp en code altijd synchroon en is een wijziging op één plek (bijvoorbeeld een merkkleur) direct overal doorgevoerd.

Het bestand tokens/tokens.json is de single source of truth voor alle ontwerp-waarden én toepassingen (kleur, typografie, spacing, etc.). Dit bestand is in twee richtingen te bewerken:

  • Figma; via de Tokens Studio plugin kunnen ontwerpers tokens ophalen, aanpassen en terugschrijven naar Git.
  • IDE; ontwikkelaars kunnen het JSON-bestand ophalen, aanpassen en terugschrijven naar Git in een code-editor.

Style Dictionary

Om de design tokens te vertalen naar CSS variabelen wordt Style Dictionary gebruikt.

  1. Installeer Style Dictionary in /style-dictionary, deze vertaald design tokens naar CSS variabelen
  2. Instaleer SD-Transforms in /style-dictionary, dit is een pakketje met extra transformatie-opties die nodig zijn om design tokens uit Figma Tokens Studio te vertalen

De pipeline ziet er zo uit:

Figma met Tokens Studio óf IDE → tokens/tokens.json → Style Dictionary + SD-Transforms → CSS variabelen → Stylesheet (style.css)

Style Dictionary leest tokens.json en transformeert de tokens naar CSS custom properties. Omdat Tokens Studio een eigen tokenformaat hanteert dat afwijkt van het standaard Design Token Community Group (DTCG) formaat, wordt SD-Transforms als aanvulling gebruikt. Dit zorgt onder andere voor het correct oplossen van tokenreferenties, het omrekenen van px naar rem waarden en het omzetten van namen naar kebab-case.

Het resultaat wordt opgesplitst in twee automatisch gegenereerde CSS-bestanden:

  • _rijkshuisstijl.css; bevat de waarden uit de Rijkshuisstijl: het kleurenpalet, typografie-instellingen, maatvoering, etc. Dit zijn de beschikbare opties.
  • _toepassing.css; bevat semantische variabelen die verwijzen naar de Rijkshuisstijl-waarden en daar een concrete betekenis aan geven, bijvoorbeeld --color-text-default of --button-primary-background-color. Dit zijn de toepassingen van de opties.

Gebruik in stylesheets en componenten altijd variabelen uit _toepassing.css en nooit rechtstreeks uit _rijkshuisstijl.css. De Rijkshuisstijl-variabelen zijn de bouwstenen; de toepassingsvariabelen bepalen hoe die bouwstenen worden ingezet. Door deze scheiding kan een Rijkshuisstijl-waarde wijzigen zonder dat stylesheets aangepast hoeven te worden, de toepassingslaag vangt de verandering op.

Beide bestanden worden automatisch gegenereerd en mogen niet handmatig bewerkt worden. Alle wijzigingen aan ontwerp-waarden horen thuis in tokens/tokens.json.

Design tokens vertalen naar CSS variabelen

Gebruik dit commando om design tokens handmatig naar CSS variabelen om te zetten:

npm run tokens

Dit resulteert in wijzigingen in de CSS variabelen bestanden. Deze worden automatisch geïmporteerd in de globale style.css style sheet.

Bij het gebruik van npm run dev worden design tokens automatisch opnieuw gebouwd wanneer tokens/tokens.json wijzigt.


Digitale Assistent

De chat-UI van de Digitale Assistent zit in dit prototype (moza/digitale-assistent.html + assets/javascript/digitale-assistent.js). De backend — een FastAPI-host die twee LLM-backends (VLAM en Claude) combineert met overheidsbronnen via MCP of CLI — leeft in een eigen repo en draait standalone:

backend: moza-poc-digitale-assistent

https://github.com/MinBZK/moza-poc-digitale-assistent

Verbinden met de backend

In productie draait alles achter één origin: de nginx van de frontend proxyt de chat-endpoints (/chat, /chat/stream, /health, /tools) intern naar de backend. De browser praat dus alleen met de frontend-origin — geen CORS nodig, en de backend hoeft niet publiek te zijn. Twee instellingen:

Variabele Waar Betekenis
MOZA_CHAT_API build-time (_data/chatApi.jsbase.njkwindow.MOZA_CHAT_API) Waar de browser naartoe fetcht. Default leeg ("") = same-origin via de proxy. Productie laat dit leeg.
BACKEND_ORIGIN runtime env op de nginx-container Waar de proxy naartoe stuurt. Default http://dabackend:8000. Zet dit op het ZAD-component proef via de ZAD-UI (zad-actions/deploy kan geen runtime-env zetten).

Lokaal end-to-end (zonder proxy; backend draait los, dus daar wél CORS):

  1. npm run dev — Eleventy --serve op localhost:8080; zet automatisch window.MOZA_CHAT_API=http://localhost:8000 zodat de browser de lokale backend direct aanroept.
  2. Start de backend (FastAPI, poort 8000) volgens de backend-repo.
  3. Zet aan de backend ALLOWED_ORIGINS=http://localhost:8080.

⚠️ Preview-deploys (pr<nr>): het backend-component dabackend draait alleen in de gedeelde deployments (poc, gebruikersonderzoek), niet in per-PR previews. In een PR-preview is er dus geen backend en werkt de chat niet, tenzij dabackend aan die deployment wordt toegevoegd.

Voor losse demo's van de CLI-tools (kvk-cli, koop-cli, …) gebruik je de backend-repo; die bevat de standalone bash-tools.

API-sleutels

Gebruikers kunnen hun eigen VLAM- en Claude-sleutel invullen via het feature-flags-paneel rechtsonder in de site. Deze worden per request als X-VLAM-API-Key / X-Claude-API-Key header naar de backend meegestuurd (de proxy laat die headers door). Dit werkt zolang de backend ALLOW_API_KEY_OVERRIDE=true heeft (PoC-default); lege velden vallen terug op de server-side keys.

Let op: een Claude-sleutel uit de UI werkt zelfstandig. Voor VLAM vraagt de UI alleen de sleutel, maar VLAM heeft ook VLAM_BASE_URL + VLAM_MODEL_ID nodig — die moeten server-side op de backend staan. Het eenvoudigst is om de server-side keys op de backend-deployment te zetten, dan werkt de chat voor iedereen zonder iets in te vullen.

Containerisatie

De container/Containerfile bouwt de statische site (frontend-only): een Node-builder genereert de Eleventy-site en Storybook, en een nginx-image serveert die op poort 8080 én doet de same-origin reverse proxy naar de backend (zie Verbinden met de backend). De proxy-config (container/default.conf.template) wordt bij container-start gerenderd met envsubst; BACKEND_ORIGIN (runtime env, default http://dabackend:8000) bepaalt de upstream, met runtime-DNS-resolutie zodat nginx ook start als de backend nog niet up is. Dezelfde image (non-root, poort 8080) wordt gebruikt voor preview- en productiedeploys (ZAD).

docker build -f container/Containerfile -t moza .
# wijs de proxy naar een lokaal draaiende backend (Docker Desktop):
docker run --rm -p 8080:8080 -e BACKEND_ORIGIN=http://host.docker.internal:8000 moza

Storybook

Storybook is de omgeving om afzonderlijke componenten te bekijken, testen en documenteren.

Lokaal opstarten

npm run storybook

Storybook is vervolgens te bekijken op localhost:6006.

Automatisch bouwen

Bij het gebruik van npm run dev wordt Storybook automatisch opnieuw gebouwd naar _site/storybook wanneer bestanden in stories/ of style/style.css wijzigen. Dit gebeurt via chokidar die het build-storybook script triggert bij elke wijziging.

Stories

De stories staan in de stories/ map. Elk bestand beschrijft één component en toont varianten, bijvoorbeeld:

Bestand Beschrijving
Knop.stories.js Knopvarianten (primair, secundair, negatief)
Link.stories.js Linkvarianten
Tekstinvoer.stories.js Tekstinvoervelden
Selectie.stories.js Selectievakjes en keuzerondjes
Feedback.stories.js Notificaties en foutmeldingen
Navigatie.stories.js Navigatiecomponenten
Typografie.stories.js Koppen en tekststijlen
Tabel.stories.js Tabelopmaak

NPM scripts

Installeer dependencies in de root van het project:

npm install
Script Commando Beschrijving
npm run dev Eleventy serve + token watcher Beide parallel via concurrently. Eleventy --serve met live reload op localhost:8080; de chat-backend draai je apart (zie Digitale Assistent).
npm run build Tokens + Eleventy Volledige productie-build
npm run tokens Alleen Style Dictionary Handmatig tokens bouwen
npm run storybook Storybook dev server Componentenbibliotheek lokaal bekijken
npm run build-storybook Storybook productie-build Statische Storybook-site bouwen

Structuur

📂 _data                    Eleventy-data: persona's, subsidies, regelgeving, berichtenbox
📂 _includes                herhalende consistente elementen die in meerdere pagina's toegegepast worden
📂 _site                    statische site gegenereerd door Eleventy.js
📂 assets
    📁 favicon              favicons voor diverse platformen
    📁 fonts                Rijkslettertype webfonts
    📁 icons                iconen
    📁 images               afbeeldingen
    📁 javascript           interactielogica per pagina-type (personas, content-interactions, berichtenbox, etc.)
📂 container                Containerfile + nginx-config voor de statische site-deployment
📂 mobu                     prototype voor MijnOverheid Burger
📂 moza                     prototype voor MijnOverheid Zakelijk, gebaseerd op deze omgeving
📂 stories                  'stories' om componenten weer te geven in Storybook
📂 style
    📄 _reset.css           cross-browser stijl normalisatie
    📄 _rijkshuisstijl.css  opties uit de Rijkshuisstijl
    📄 _toepassing.css      semantische toepassing van de opties uit de Rijkshuisstijl
    📄 style.css            algemene CSS styling
📁 style-dictionary
    📄 config.json          configuratiebestand voor Style Dictionary
📁 tokens
    📄 tokens.json          design tokens JSON bestand
📄 .stylelintrc.json        Stylelint-config (logical properties, alfabetische volgorde, spacing-regels)
📄 index.html               homepagina van het MijnOverheid Zakelijk prototype
📄 package.json             build dependencies
📄 package-lock.json        locked dependency versions
📄 README.md                dit bestand

CSS conventies

CSS patronen

Deze omgeving maakt gebruik van moderne CSS-features:

  • CSS nesting voor o.a. component-staten en varianten
  • CSS custom properties (variabelen) voor alle ontwerp-waarden
  • :focus-visible (niet :focus) voor toetsenbordfocus-indicatoren
  • aria-disabled en aria-invalid ARIA attributen voor staten (niet :disabled)

Variabele naamgeving

Gegenereerde variabelen volgen kebab-case met een semantische hiërarchie:

--prefix-categorie-optionelesubcategorie-attribuut--optionelestaat

Voorbeelden:

  • --rijkhuisstijl-color-lintblauw-50
  • --toepassing-button-primary-background-color

Logical properties

In de stylesheets worden CSS logical properties gebruikt in plaats van physical properties. Logical properties passen zich automatisch aan op basis van de schrijfrichting (direction) en schrijfmodus (writing-mode), wat de CSS toekomstbestendig en beter geschikt maakt voor meertalige ondersteuning.

Voorbeelden van physical properties en hun logical equivalenten:

Physical Logical
width inline-size
height block-size
max-width max-inline-size
min-height min-block-size
margin-top / margin-bottom margin-block-start / margin-block-end
margin-left / margin-right margin-inline-start / margin-inline-end
padding-top / padding-bottom padding-block-start / padding-block-end
padding-left / padding-right padding-inline-start / padding-inline-end
border-top / border-bottom border-block-start / border-block-end

Git commit berichten

Initial commit Initiële commit, een eerste versie die in de bestandsgeschiedenis geplaatst wordt.

Added Toevoeging(en) aan een bestand.

Voorbeeld: Link component

✏️ Modified Wijziging(en) aan een bestand.

Voorbeeld: ✏️ Kleur van :hover staat primaire knop

❌ Deleted Verwijdering van (iets in) een bestand.

Voorbeeld: ❌ contactpagina.html verwijderd

🧼 Hygiene Kleine aanpassing, fix.

Voorbeeld: 🧼 padding-inline-start → padding-inline

🐛 Bugfix Herstel van een bug.

Voorbeeld: 🐛 footer include werd niet getoond

💾 Backup Back-up van een bestand voordat grote wijzigingen plaatsvinden.

Voorbeeld: 💾 backup 2026-03-18 voorafgaand aan wijzigingen voor gebruikersonderzoeken

🔁 Renamed Hernoeming van (iets in) een bestand.

Voorbeeld: 🔁 contact-pagina.html hernoemd naar comntact.html

↩️ Revert commit Wijziging(en) in een vorige commit die ongedaan gemaakt worden.

Voorbeeld: ↩️ wijzigingen van vorige commit ongedaan gemaakt omdat deze performance issues veroorzaakte

🔀 IDE ↔︎ Figma Twee-wegverkeer tussen IDE en Figma, met name om design tokens in beide omgevingen te kunnen aanpassen en testen (Style Dictionary → CSS variabelen en Figma Tokens Studio)

Voorbeeld: 🔀 tokens voor knoppen aangepast in Figma