The short version

We built this site without a CMS. All content lives as MDX and JSON files in a Git repository, and Astro Content Collections validate every field at build time. That removes an entire layer: no API calls, no database, no editor accounts, no plugin maintenance. Publishing is a regular commit and deploy. For AI agents, such a repository is a natural workplace: reading, writing and reviewing happen with file operations an agent already masters. Here is how the architecture works, what it got us and when you should still choose a CMS.

This website has no CMS. No Storyblok, no WordPress, no database with posts. Everything you read lives as MDX and JSON files in a Git repository, and Astro Content Collections validate every field against a schema on each build. This article is such a file itself: frontmatter at the top, typed block components below.

Why would you want a website without a CMS? Because for a static site with a small team, a CMS often costs more than it returns. Not just in money, but in maintenance, security surface and the extra layer between “text ready” and “page live”. When we made the trade-off, it turned out we used 10 percent of the CMS and could replace the rest with Git conventions. Beyond expectations, the architecture also proved to be the best workplace you can give an AI agent.

In this article I explain how we approached it: the role Content Collections play, how the content in Git is organized, what it got us and when you are still better off choosing a CMS.

Why we dropped the CMS

Before the summer of 2026, this site ran on Astro with Storyblok. A solid combination, technically clean, and we still build that stack for clients today. But for ourselves, the friction kept growing.

In practice, bringing a CMS means arranging a whole series of things that have nothing to do with content. A space with components and content models to keep in sync with the code. API calls in the build that failed whenever the CMS hiccuped. Accounts and permissions for everyone who wanted to change something. Webhooks or rebuilds to speed up publications. And a second place where “the truth” lived: the repository held the code, the CMS held the content, and every change had to be understood in both worlds.

The question that tipped the scale was simple: who actually works with this content? The answer: Seppe and the team, plus the AI agents that do the preparatory work. Nobody in that group needs a visual editor. Everyone already reads and writes in Git daily. The CMS was a translation layer between two groups that spoke the same language.

On top of that, the agents needed access to the CMS to change content. API keys, an MCP server as a bridge, rate limits and draft workflows: all solvable things, but all extra moving parts to manage and secure. In Git, those problems simply did not exist. The agent reads a file, changes it and produces a diff — exactly what an agent does naturally.

The core of the switch

A CMS solves the problem “how do non-technical people get content into a website”. We do not have that problem. Our problem is “how do we keep a growing site fast, secure and manageable by AI agents”. For that second problem, a Git repository with typed content is the more direct answer.

What Astro Content Collections are (and are not)

Astro Content Collections are the framework’s built-in content layer. You define a folder with source files and a schema per collection, and Astro loads all files as typed entries at build time. We have seven: pages and articles as MDX, and datasets, case metrics, people and settings as JSON.

This is what the configuration looks like in our project, trimmed down to the principle:

ts
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, … */ };

The schema is a Zod definition that pins down exactly which fields an article may and must have: title, route, publication date, author, category, tags, summary, FAQ items. If the frontmatter of a single file is incomplete or a field name has a typo, the build fails with an error that names the file and the field. For your visitors nothing changes: the output is plain, fast HTML.

So what it is: a contract between your content and your templates. Every article the template reads is guaranteed to have the fields the layout relies on. The same holds for the JSON datasets we hand to cards and components: same schemas, same guarantees.

And what it is not: a CMS. There is no visual editor, no database, no preview environment behind a login screen, no API token that can expire. Content Collections do not replace the editor experience of Storyblok or WordPress; that experience simply does not exist here. Anyone who wants to drag and shuffle content in a familiar dashboard every day will miss it immediately. More on that in the section about when to choose a CMS anyway.

For the broader context first: what a CMS is and how a headless CMS works are explained separately in our knowledge base.

How our architecture looks: MDX and JSON in Git

The entire content structure of the site lives in one repository. This is the organization in short:

sh
src/content/
├── pages/            # landing pages and hub pages (MDX)
   ├── nl/           # 29 Dutch-language pages
   └── en/           # 29 English pages
└── articles/
    ├── nl/
   ├── blog/      # 24 blogs
   ├── case/      # 13 case studies
   └── begrippen/ # 34 glossary terms
    └── en/
        ├── blog/      # 18 blogs, this article included
        ├── case/      # 12 case studies
        └── glossary/  # 34 glossary terms

(Datasets, case metrics, people and settings live as JSON alongside this tree; the structure above shows the MDX side.)

Every file starts with frontmatter that must satisfy the schema. The frontmatter of this article contains, among other things, the route, the author, the summary for “the short version”, the FAQ at the bottom of the page and the reference to the image above. Below that frontmatter sits the body: regular Markdown headings inside typed section components. We write internal links as regular links; the URL convention without trailing slashes is enforced by the build itself.

That is the core of what makes Git stronger than a CMS here. Every content change is a diff: you see which line in which file changed, when, by whom and why in the commit message. Publishing a new blog post is a commit to the main branch; Vercel builds and deploys automatically. Rolling back is a revert. There is no second system to keep in sync and no version in a CMS that can drift from the code that renders it.

We also keep that structure deliberately tight for ourselves. The site is bilingual, and the English counterparts are linked to the Dutch pages through a fixed pair registry. Because those pairs live in the repository, the build checks can verify that every link points to a real route and that both sides confirm each other’s existence.

CriterionClassic CMSHeadless CMSContent in Git
Where content livesCMS databaseDatabase behind an APIFiles in the repository
Who edits contentEditors in the dashboardEditors in the dashboardAnyone with write access to Git
ValidationField checks in the CMSField checks in the CMSSchema at build time, fails hard
PublishingSave in the CMSSave and rebuildCommit and push, deploy follows
Version historyRevisions in the CMSRevisions in the CMSFull diff per change
Extra maintenanceCore, plugins, databaseAPI, accounts, webhooksOnly the repository itself
Runtime dependenciesServer and databaseCMS hosting and APINone, the site is static
AI agent accessPlugin or API rightsMCP server or API keyOrdinary file operations

The last row has become the most important one for us, and deserves its own section.

Why AI agents benefit: Git as a workplace

In 2026, the way AI agents work has matured quickly. They read instruction files, explore a project structure, run commands and edit files. Publications about this evolution, such as the GitHub blog on AGENTS.md and articles on why Markdown keeps winning in the AI era, describe the same pattern: agents perform best in repositories full of flat, structured text.

Our own AI agent Hermes works exactly like that. For every content task he reads instructions and schemas, locates the relevant files, changes them and lets the build do the validation. In a CMS world, such an agent needs a bridge to the CMS: API keys, an MCP server with the right permissions, rate limits, draft statuses. In the Git approach he simply reads and writes files. CloudCannon, a CMS vendor that offers both worlds, put it this way in 2026: the more content you have, the more an agent has to fetch and parse through an API, while reading a local file is free. Their conclusion for AI-driven teams was blunt: git-based content wins.

Four concrete benefits, as we experience them every day:

  1. Reading costs no API traffic. The agent opens the MDX file and sees frontmatter, structure and content at a glance. No endpoint calls, no rate limits, no translating API responses into text.
  2. Writing is an ordinary file operation. Rewriting a section, adding an FAQ item, updating internal links: it happens with the same tools as code editing. There is no CMS-specific API to learn or secure.
  3. Every change is a diff. For a human, that is the natural review form: you read the diff, approve it and commit. You do not have to trust a CMS log to reconstruct what an agent did.
  4. The build is the quality gate. Because the schema fails hard, an agent cannot publish content that violates the contract. Wrong date format, missing field, summary too long: the build stops and points at the file. For how AI handles our day-to-day quality checks, read how we optimize our blog with AI.

What matters is where the boundary lies. The agent prepares and runs checks; what gets published is decided by people. For us that is a deliberate agreement, not a technical necessity. Without that discipline, an AI agent with write access to a repository is exactly as risky as an agent with publish rights in a CMS.

What it got us: measuring, not claiming

Numbers about your own migration only mean something if you actually measure them. We therefore treat this site as an ongoing case study: monthly PageSpeed measurements and monthly Search Console data, publicly visible on the Straffe Sites case page.

As of September 3, 2026, that measurement series looks like this: our own site scores 100/100 on mobile Performance, with an LCP of 1.4 seconds. Across the twelve other case sites in the series — most of them built on the same stack pattern of static building and measuring — the median best monthly score is 99/100 mobile Performance. The fastest measured LCP in that series is 937 milliseconds. These are measurements of real production sites, not laboratory demos.

Those numbers did not fall from the sky and are not an automatic consequence of “no CMS” either. They are the result of the lightweight technical foundation this approach enforces: static rendering, almost no JavaScript and a build that makes impossible whatever does not pass the schemas. Without a database and API layer there are genuinely fewer moving parts that can break your speed and stability.

The gain is not only in the numbers, but especially in the work itself: a site without CMS maintenance is a site with one less thing to worry about. Since the switch, no CMS update has been scheduled, no plugin audit done, no API key rotated and no CMS account managed. The only thing that still counts is the repository: one place, one history, one set of rules.

When should you choose a CMS anyway?

This approach is not a law. It fits a specific situation, and it is honest to name that boundary.

Choose a CMS if your team does not work in Git. A visual editor, draft statuses, permissions and publishing flows: those are exactly the problems CMS platforms are built for, and they solve them well. For many companies with a marketing team publishing weekly, a dashboard is indispensable. In those situations we also build solutions with a CMS, such as headless with Storyblok, or a git-based CMS with a visual editor that writes to Git under the hood: the editor experience stays, the benefits of files stay. If you hesitate between both routes, we describe the commercial side of such an architecture on the page about having a headless website built.

Also choose a CMS if your content structure changes often and quickly because of people outside the development team. Inventing new content types belongs in a dashboard with field management; in our approach a new content type is a schema and template change — development work.

And choose a CMS if you need CMS-dependent features: built-in media libraries with user rights, publication scheduling, multilingual setups with per-field translation workflows, or integrations with other systems that run through the CMS. You can rebuild all of that in Git, but then you are building a mini-CMS yourself, which is precisely what we wanted to avoid.

So the question is not “is a CMS bad?” but “who works with your content daily?”. If that is a technical team that already lives in Git and uses AI agents, content in Git is the more direct route. If that is an editorial team of non-technical people, a CMS is the right tool and there is nothing wrong with that choice. To compare architectures side by side, read what a headless CMS is.

Not sure which route fits your team and plans? A short conversation helps more than reading another article. Discuss your project.