Korte versie
We bouwden deze site zonder CMS. Alle content leeft als MDX- en JSON-bestanden in Git en Astro Content Collections valideren elk veld bij de build. Dat scheurt een hele laag weg: geen API-calls, geen database, geen editor-accounten, geen plugin-onderhoud. De publicatie is een gewone commit en deploy. Voor AI-agenten is zo'n repo een natuurlijke werkplek: lezen, schrijven en reviewen gebeurt met bestandsoperaties die een agent al beheerst. Hier lees je hoe de architectuur eruitziet, wat het opleverde en wanneer je tóch beter een CMS kiest.
Deze website heeft geen CMS. Geen Storyblok, geen WordPress, geen database met berichten. Alles wat je leest staat als MDX- en JSON-bestanden in een Git-repository, en Astro Content Collections valideren bij elke build elk veld tegen een schema. Dit artikel is zelf zo’n bestand: frontmatter bovenaan, daaronder secties in getypeerde blokken.
Waarom zou je een website zonder CMS willen? Omdat een CMS voor een statische site met een klein team vaak meer kost dan het oplevert. Niet alleen in euro’s, maar in onderhoud, veiligheidsoppervlakte en de extra laag tussen “tekst klaar” en “pagina live”. Toen we de afweging maakten, bleek dat we 90 procent van het CMS niet gebruikten en de resterende 10 procent met Git-conventies konden vervangen. Boven verwachting bleek ook dat de architectuur de beste werkplek is die je een AI-agent kunt geven.
In dit artikel leg ik uit hoe wij het aanpakten: welke rol Content Collections spelen, hoe de content in Git is georganiseerd, wat het opleverde en wanneer je tóch beter voor een CMS kiest.
Waarom wij het CMS afstootten
Vóór de zomer van 2026 draaide deze site nog op Astro mét Storyblok. Een prima combinatie, technisch netjes, en voor klanten bouwen we die stack vandaag nog steeds. Maar voor onszelf groeide de frictie.
Een CMS meenemen betekent in de praktijk een hele reeks dingen regelen die niets met content maken te maken hebben. Een space met componenten en contentmodellen synchroniseren met de code. API-calls in de build die faalden als het CMS een stootje kreeg. Accounts en rechten voor iedereen die iets wilde aanpassen. Webhooks of rebuilds om publicaties vlot te trekken. En een tweede plek waar “de waarheid” leefde: de repository bevatte de code, het CMS bevatte de inhoud, en elke wijziging moest je in beide werelden begrijpen.
De vraag die het deed kantelen was simpel: wie werkt er eigenlijk met deze content? Het antwoord: Seppe en het team, plus de AI-agenten die het voorbereidende werk doen. Niemand van ons heeft een grafische editor nodig. Iedereen in die groep leest en schrijft al dagelijks in Git. Het CMS was een vertaallaag tussen twee groepen die dezelfde taal spraken.
Daar komt bij dat de agenten toegang tot het CMS nodig hadden om inhoud te kunnen aanpassen. API-sleutels, een MCP-server als brug, rate limits en draft-workflows: allemaal oplossbare dingen, maar allemaal extra bewegende onderdelen om te beheren en te beveiligen. In Git waren die problemen gewoon weg. De agent leest een bestand, past het aan en maakt een diff, exact wat een agent van nature doet.
De kern van de wissel
Een CMS lost het probleem “hoe krijgen niet-technische mensen content in een website” op. Wij hebben dat probleem niet. Wij hebben het probleem “hoe houden we een groeiende site snel, veilig en door AI-agenten beheerbaar”. Voor dat tweede probleem is een Git-repository met getypeerde content een directer antwoord.
Wat Astro Content Collections zijn (en wat niet)
Astro Content Collections zijn de ingebouwde contentlaag van het framework. Je definieert per collectie een map met bronbestanden en een schema, en Astro laadt bij de build alle bestanden als getypeerde entries. Wij hebben er zeven: pagina’s en artikelen als MDX, en datasets, case-metrics, mensen en instellingen als JSON.
Zo ziet de configuratie er in ons project uit, ingekort tot het principe:
import { defineCollection } from 'astro:content';
import { glob } from 'astro/loaders';
const articles = defineCollection({
loader: glob({ pattern: '**/*.mdx', base: './src/content/articles' }),
schema: articleFrontmatterSchema,
});
export const collections = { articles /*, pages, datasets, … */ };Het schema is een Zod-definitie die precies vastlegt welke velden een artikel mag en moet hebben: titel, route, publicatiedatum, auteur, categorie, tags, samenvatting, FAQ-items. Is de frontmatter van één bestand onvolledig of zit er een typo in een veldnaam, dan faalt de build met een foutmelding die het bestand en het veld benoemt. Voor je bezoekers verandert er niets: de output is gewone, snelle HTML.
Wat het dus wél is: een contract tussen je content en je templates. Elk artikel dat de template inleest, heeft gegarandeerd de velden waar de layout op rekent. Dat geldt ook voor de JSON-datasets die we aan cards en onderdelen meegeven: het zijn dezelfde schema’s, dezelfde garanties.
En wat het níét is: een CMS. Er is geen grafische editor, geen database, geen preview-omgeving met inlogscherm, geen API-token die kan verlopen. Content Collections vervangen niet de editor-ervaring van Storyblok of WordPress; die bestaat hier gewoonweg niet. Wie dagelijks content wil slepen en schuiven in een vertrouwd dashboard, voelt dat gemis meteen. Daarover meer in de sectie over wanneer je tóch een CMS kiest.
Wil je eerst de bredere context: wat een CMS is en hoe een headless CMS werkt, leggen we apart uit in de kennisbank.
Hoe onze architectuur eruitziet: MDX en JSON in Git
De hele inhoudelijke structuur van de site leeft in één repository. Dit is de organisatie in het kort:
src/content/
├── pages/ # landingspagina's en hubpagina's (MDX)
│ ├── nl/ # 28 Nederlandstalige pagina's
│ └── en/ # 24 Engelse pagina's
└── articles/
├── nl/
│ ├── blog/ # 22 blogs, dit artikel incluis
│ ├── case/ # 12 cases
│ └── begrippen/ # 33 begrippen
└── en/
├── blog/ # 16 blogs
├── case/ # 11 cases
└── glossary/ # 33 begrippen(Datasets, case-metrics, mensen en instellingen leven als JSON ernaast; de boom hierboven toont de MDX-zijde.)
Elk bestand begint met frontmatter die aan het schema moet voldoen. De frontmatter van dit artikel bevat onder meer de route, de auteur, de samenvatting voor de “korte versie”, de FAQ voor onderaan de pagina en de referentie naar het beeld hierboven. Onder die frontmatter staat de body: gewone Markdown-headers binnen getypeerde sectiecomponenten. Interne links schrijven we als gewone links; de URL-conventie zonder trailing slash bewaakt de build zelf.
Daar zit de kern van wat Git hier sterker maakt dan een CMS. Elke inhoudelijke wijziging is een diff: je ziet welke regel in welk bestand veranderde, wanneer, door wie, en waarom in de commitmessage. Een nieuwe blog publiceren is een commit op de hoofdbranch; Vercel bouwt en deployt automatisch. Terugdraaien kan met een revert. Er is geen tweede systeem om te synchroniseren en geen versie in het CMS die kan afwijken van de code die hem rendert.
Diezelfde structuur zetten we onszelf ook bewust strak. De site is tweetalig, en de Engelse tegenhangers zijn via een vast paarregister gekoppeld aan de Nederlandse pagina’s. Omdat de koppeling in de repository leeft, kan de buildcontrole controleren dat elke koppeling naar een echte route wijst en dat beide kanten elkaars bestaan bevestigen.
| Criterium | Klassiek CMS | Headless CMS | Content in Git |
|---|---|---|---|
| Waar leeft content | Database van het CMS | Database achter een API | Bestanden in de repository |
| Wie past content aan | Editors in het dashboard | Editors in het dashboard | Iedereen met schrijfrechten op Git |
| Validatie | Veldcontrole in het CMS | Veldcontrole in het CMS | Schema bij de build, faalt hard |
| Publicatie | Opslaan in het CMS | Opslaan en rebuild | Commit en push, deploy volgt |
| Versiegeschiedenis | Revisions in het CMS | Revisions in het CMS | Volledige diff per wijziging |
| Extra onderhoud | Core, plugins, database | API, accounts, webhooks | Alleen de repository zelf |
| Runtime-afhankelijkheden | Server en database | CMS-hosting en API | Geen, de site is statisch |
| AI-agent-toegang | Plugin of API-rechten | MCP-server of API-sleutel | Gewone bestandsoperaties |
De laatste rij is voor ons de belangrijkste geworden, en verdient een eigen sectie.
Waarom AI-agenten hier van profiteren: Git als werkplek
In 2026 is de manier waarop AI-agenten werken snel volwassen geworden. Ze lezen instructiebestanden, verkennen een projectstructuur, voeren commando’s uit en passen bestanden aan. Publicaties over deze evolutie, zoals het GitHub-blog over AGENTS.md en artikelen over waarom Markdown in het AI-tijdperk blijft winnen, beschrijven hetzelfde patroon: agenten presteren het best in repositories vol platte, gestructureerde tekst.
Onze eigen AI-agent Hermes werkt zo ook. Voor elke contenttaak leest hij instructies en schema’s, zoekt de relevante bestanden op, past ze aan en laat de build de validatie doen. In een CMS-wereld heeft zo’n agent een brug nodig naar het CMS: API-sleutels, een MCP-server met de juiste rechten, rate limits, draft-statussen. In de Git-aanpak leest en schrijft hij gewoon bestanden. CloudCannon, een CMS-leverancier die beide werelden aanbiedt, formuleerde het in 2026 zo: hoe meer content je hebt, hoe meer een agent moet ophalen en parsen via een API, terwijl een lokaal bestand lezen gratis is. Hun conclusie voor AI-gedreven teams was ronduit dat git-based content wint.
Vier concrete voordelen, zoals wij ze elke dag ervaren:
- Lezen kost geen API-verkeer. De agent opent het MDX-bestand en ziet in één oogopslag frontmatter, structuur en inhoud. Geen endpoint-calls, geen rate limits, geen vertaalwerk van API-respons naar tekst.
- Schrijven is een gewone bestandsoperatie. Een sectie herschrijven, een FAQ-item toevoegen, interne links bijwerken: het gebeurt met dezelfde tools als codebewerking. Er is geen CMS-specifieke API om te leren of te beveiligen.
- Elke wijziging is een diff. Voor een mens is dat de natuurlijke reviewvorm: je leest de diff, keurt hem goed en commit. Je hoeft niet te vertrouwen op de logging van een CMS om te reconstrueren wat een agent deed.
- De build is de kwaliteitspoort. Doordat het schema hard faalt, kan een agent geen inhoud publiceren die niet aan het contract voldoet. Verkeerde datumnotatie, ontbrekend veld, te lange samenvatting: de build stopt en wijst naar het bestand. Hoe AI de dagelijkse kwaliteitscontroles doet, lees je in hoe we onze blog met AI optimaliseren.
Belangrijk is waar de grens ligt. De agent bereidt voor en voert controles uit; wat er gepubliceerd wordt, beslissen mensen. Dat is bij ons een bewuste afspraak, geen technische noodzaak. Zonder die discipline is een AI-agent met schrijfrechten op een repository precies zo riskant als een agent met publicatierechten in een CMS.
Wat het opleverde: meten, niet beweren
Cijfers over een eigen migratie zijn pas iets waard als je ze ook echt meten. Deze site behandelen we daarom als een lopende case: maandelijkse PageSpeed-metingen en maandelijkse Search Console-data, publiek inzichtelijk op de casepagina van Straffe Sites.
Op 1 september 2026 ziet die meetreeks er zo uit: de eigen site scoort 100/100 op mobiele Performance, met een LCP van 1,4 seconden. Over de twaalf actuele casesites, waarvan de meeste op hetzelfde stackpatroon van statisch bouwen en meten zijn gezet, ligt de mediaan op 99/100 mobiele Performance. De snelste gemeten LCP in die reeks is 941 milliseconden. Dat zijn metingen van echte productiesites, geen laboratoriumdemo’s.
Die cijfers komen niet uit de lucht gevallen en zijn ook geen automatisch gevolg van “geen CMS”. Ze zijn het resultaat van de lichte technische basis die deze aanpak afdwingt: statisch renderen, bijna geen JavaScript, en een build die onmogelijk maakt wat niet door de schema’s heen komt. Zonder database en API-laag zijn er wel degelijk minder bewegende onderdelen die je snelheid en stabiliteit kunnen breken.
Die winst zit niet alleen in de cijfers, maar vooral in het werk zelf: een site zonder CMS-onderhoud is een site met één zorgpunt minder. Sinds de wissel is er geen CMS-update meer gepland, geen plugin-audit meer gedaan, geen API-key meer geroteerd en geen CMS-account meer beheerd. Het enige dat nog telt, is de repository: één plek, één geschiedenis, één set regels.
Wanneer kies je tóch een CMS?
Deze aanpak is geen wet. Ze past bij een specifieke situatie, en het is eerlijk om die grens te benoemen.
Kies een CMS als je team niet in Git werkt. Een grafische editor, conceptstatussen, rechtenbeheer en publicatieflows: dat zijn precies de problemen waarvoor CMS’en gebouwd zijn, en ze lossen die goed op. Voor veel bedrijven met een marketingteam dat wekelijks content plaatst, is een dashboard onmisbaar. In die situaties bouwen we ook oplossingen mét CMS, zoals headless met Storyblok, of een git-based CMS met een grafische editor die onder de motorkap naar Git schrijft: de editor-ervaring blijft, de voordelen van bestanden blijven.
Kies ook een CMS als je contentstructuur vaak en snel verandert door mensen buiten het ontwikkelteam. Nieuwe contenttypes bedenken hoort bij een dashboard met veldbeheer; in onze aanpak is een nieuw contenttype een schema- en templatewijziging, ontwikkelwerk dus.
En kies een CMS als je van het CMS afhankelijke functies nodig hebt: ingebouwde mediabibliotheken met gebruikersrechten, planning van publicaties, meertaligheid met vertaalworkflows per veld, of koppelingen met andere systemen die via het CMS lopen. Al die dingen kun je in Git nabouwen, maar dan ben je zelf een mini-CMS aan het bouwen, en dat is precies wat we wilden vermijden.
De vraag is dus niet “is een CMS slecht?”, maar “wie werkt er dagelijks met je content?”. Is dat een technisch team dat toch al in Git leeft en AI-agenten inzet, dan is content in Git de directere weg. Is dat een redactie met niet-technische mensen, dan is een CMS de juiste tool en is er niets mis met die keuze. Hoe je headless en klassiek naast elkaar zet, lees je in headless CMS of klassiek CMS, en voor een concrete systeemvergelijking bestaat er Storyblok vs WordPress.
Twijfel je welke route past bij jouw team en plannen? Dan helpt een kort gesprek meer dan nog een artikel lezen. Bespreek je project.

