Back to the blog

Moving WordPress pages and settings out of the database so AI agents can maintain them

For the last ten years, the direction in WordPress was clear: move as much as possible into the database. Page builders, the Customizer, Full Site Editing, and Gutenberg block attributes all exist for the same reason. Writing PHP and CSS by hand was slow, and store owners did not want to wait three days on a developer just to change a hero section or flip a checkout setting.

Coding with AI agents flipped that math.

When an agent can edit a PHP block pattern, update a SCSS file, and open a pull request in thirty seconds, clicking through six nested sidebar panels in the block editor stops being a shortcut. It becomes the slowest and least reliable part of the job.

Lately I have been moving in the opposite direction: keeping page content, layout structure, design tokens, and critical store settings directly in the repository, and using wp-admin for less.

Why the block editor is a blind spot for agents

Coding agents are good at text files. Give an agent a repository and it can grep for a class name, read the surrounding context, make a change across four files, and leave a clean git diff you can review in two minutes.

Now try asking that same agent to update a landing page that was built by hand in the block editor.

In a standard WordPress setup, that page lives in wp_posts as a wall of serialized block comments and inline JSON attributes. Padding, font sizes, hex colors, and visibility rules are scattered across individual blocks in the database. To change it, either a human has to log into wp-admin and click around, or the agent has to run WP-CLI commands against raw post content in the database.

Neither option leaves a trail you can trust:

  • There is no real diff. WordPress post revisions show that a 400-line blob of block markup changed, without telling you why or whether a style file changed alongside it.
  • Staging and production drift apart. Someone tweaks a block on production on Tuesday, and the next deployment from staging overwrites it, or vice versa.
  • Settings disappear into wp_options. On a WooCommerce store, half the bugs I get called in to fix start the same way: someone unchecked a box in a payment gateway or tax setting in wp-admin, nobody wrote it down, and orders stopped flowing.

If an agent is going to help maintain a store, the parts it touches need to live where git can see them.

How to set this up

I recently redesigned my personal website using this workflow. An agent is able to change any section, style, or dependency respecting the harness of rules, without touching the WordPress admin screen. Everything inside wp-content is tracked in a single repository with three rules:

  1. Design tokens and copy rules live in .design/design-system.yml and theme.json. The color palette, font scale, breakpoints, contrast rules, and even a list of banned phrases sit in the repo. In theme.json, custom color pickers are turned off ("custom": false). Neither a human nor an agent can invent a new shade of blue on a single block.
  2. Pages are built from PHP block patterns in the theme. Instead of assembling the Home and Projects pages in the editor, each section is a PHP file in themes/afpair/patterns/. All spacing and responsive rules live in SCSS partials under src/scss/ using .afp-* classes instead of block attributes.
  3. Top-level pages just compose the patterns. The entire Home page pattern (patterns/page-home.php) looks like this:
<!-- wp:pattern {"slug":"theme/home-hero"} /-->
<!-- wp:pattern {"slug":"theme/home-wave"} /-->
<!-- wp:pattern {"slug":"theme/home-services"} /-->
<!-- wp:pattern {"slug":"theme/home-steps"} /-->
<!-- wp:pattern {"slug":"theme/connect"} /-->

The agent is able to walk through the sections with me, update the PHP pattern files, regenerate the pages from those patterns via WP-CLI, and run a Playwright check to verify the responsiveness.

Where WordPress pushes back

I would love to say WordPress makes this workflow easy, but the truth is that WordPress is wired to treat the database as the source of truth. If you go down this road, you will hit two traps almost immediately.

First, pages store expanded markup. When you insert a block pattern into a WordPress page and save it, WordPress copies the rendered HTML into wp_posts. If you edit patterns/home-hero.php in your repo tomorrow and deploy the theme, the live page will still show yesterday’s HTML from the database.

Second, the Site Editor silently overrides theme files. In a block theme, your header and footer live in parts/header.html and parts/footer.html. The moment someone opens the Site Editor in wp-admin, tweaks the header, and clicks Save, WordPress creates a wp_template_part post in the database. From that point on, WordPress ignores parts/header.html in your repo forever until you delete that database row.

If you want your repo to be the source of truth, you have to treat the Site Editor as read-only on production, or clean out database template overrides on deploy.

Where to draw the line on a real store

Putting the whole website in git sounds tidy until someone wants to fix a typo in a product description at 4 PM and has to wait on a CI pipeline. Not everything belongs in the repository.

On a WooCommerce store, the split that actually holds up looks like this:

  • In the repository (maintained by agents and git): Theme templates, header and footer parts, theme.json tokens, SCSS, landing pages, Home and About pages, composer.json plugin versions, and core store settings.
  • In the database (maintained in wp-admin or your ERP): Orders, customers, stock levels, products, coupons, and blog posts like this one.

A good rule of thumb is simple: if a broken change could break the layout, slow down the checkout, or stop orders from coming through, put it in the repo so an agent can edit it cleanly and a human can audit the diff. If it is daily catalog data or an article, leave it in the database where WordPress has always kept it.

Writing PHP patterns and locking options in files used to feel like extra work compared to dragging blocks around on a screen. With an agent in the terminal, writing the file takes the same two minutes. The difference is that six months later, when an update lands and nothing breaks, you still know why.