This website used to read its content out of WordPress. It now reads Markdown and JSON files that sit in the same repository as the code. We get asked about the move, so here is what both setups looked like, what changed in how content moves, and what the people editing the site gave up. We are not claiming one setup is better in general, and we are not going to give reasons beyond what the architecture itself shows.
How the site worked with WordPress
WordPress was the headless source. Editors worked in the WordPress admin, and the Next.js site never rendered a page through a WordPress theme. Before each build, a GraphQL export step read the content out of WordPress and wrote it into JSON files, and the Next.js build then read those files and generated the pages.
- 01WordPress admineditors write
- 02GraphQL exportruns before build
- 03JSON filesgenerated
- 04Next.js buildstatic pages
WordPress held the content; the export step turned it into files the build could read.
Two details matter here. The site visitors saw was already static Next.js output, so the public site did not depend on WordPress being up. And the JSON files were generated, which means the real source of truth was a WordPress database sitting outside the repository.
For the person editing, that setup meant the WordPress admin, with form fields, a media picker and validation. A post went in through a screen designed for writing posts, and nobody needed to know what a build was.
How the site works now
Content is kept as files in the repository. Blog posts are Markdown with frontmatter holding the title, the date, the categories and the excerpt. Projects, services and pages are JSON. Next.js reads them at build time and generates the static pages, same as before. The diagrams in our articles, including the ones on this page, are JSON blocks written inside the Markdown.
- 01Markdown and JSONedited as files
- 02Git commitreviewed like code
- 03Next.js buildstatic pages
The export step and the separate content system are gone.
Uploaded images are also files in the repository, in the public media folder, and a post references them by path. The visitor sees the same kind of static site as before. Everything that changed happened on the editing side.
What editing a post looks like now
Here is the top of a blog post file, in the format our content guide describes. The body follows underneath as plain Markdown.
title: Plain title for the article
date: '2025-08-18T19:45:40'
author: bizhues
categories:
- name: Web Development
slug: web-development
excerpt: One or two plain sentences, shown on cards and in search results.
projects: [profit-lever-models]
The first category is the primary one. The optional projects line adds a "From our work" card under the article, and it should only list a project the article actually draws on. Every ## heading in the body becomes an entry in the "In this article" list.
Fixing a typo now means opening that file, changing the line, running the check script, and committing. Adding an image means putting the file in the media folder and writing its path into the post. None of it is hard for someone used to a code editor. For someone used to pressing Update in WordPress, every one of those steps is new.
What we gained and what it costs
- Content and code in one history
- No export step to maintain
- Posts can be reviewed as diffs
- No separate content system to run
- No admin interface
- Editors need Markdown and Git
- No visual preview by default
- Scheduled publishing is manual
These follow from the architecture, not from a measured comparison.
The gains are real but modest. One history means a content change and a template change can ship in the same commit and get reviewed together. Removing the export step removed a piece of code whose only job was to keep up with WordPress field names.
The losses land on the editors. The admin gave them form fields, a media picker and validation. With files, a mistyped frontmatter key is caught by a check script instead of by a form, which is why the repository has a script that validates frontmatter, diagrams, image paths and project references before a change is committed. The script replaces some of what the admin form used to do. It does not replace the preview, and it does not let anyone schedule a post for Monday morning.
Where a move like this goes wrong
Treating the migration as a data copy. The content is the easy part. URLs, redirects, image paths and the field mapping between the old and new structures are where the mistakes hide, and a broken link gets found by a visitor before it gets found by you.
Not deciding who edits. File-based content works when the people editing are comfortable with Git, or when someone is willing to make the edits for them. If neither is true, you have taken away the tool they used and not replaced it.
Losing structure. WordPress enforced fields through its admin. Files enforce nothing until you add checks, so mixed date formats and missing excerpts creep in quietly.
Assuming it suits every site. A site with many editors, scheduled publishing or an approval chain needs a real editing interface, whether that is WordPress, a headless SaaS product or a custom admin. Our comparison of headless and traditional CMS setups goes through that choice.
When a file-based approach fits
- The people who edit content also work in the repository, or sit next to someone who does.
- The volume is modest. Dozens of posts and projects are comfortable as files; thousands with many editors are not.
- Content changes can wait for a build and a deploy.
- You can afford a small script that checks frontmatter and links.
If any of these fails, keep a CMS with an interface and let the repository be the place for code. Files in a repository also suit pre-built static sites, which is the subject of the piece on what pre-built JAMstack pages fix and where they get awkward.
WordPress as a headless source did its job of storing and editing content. Moving to files changed who could edit comfortably, not whether the site could be published. The real work in a move like this is the checks, the redirects, and getting agreement on who edits before anything is exported.
If you are planning a similar move, list every kind of content and every person who edits it. Then ask, person by person, whether each of them can still do their job afterwards, and write down what they will use to do it. If the answer for anyone is "they will message a developer", plan the CMS work that fixes that before you switch.

