Amit Kvint ES

Vibe Coding a Live WordPress Site With No Fancy Tools

Want to talk about this essay? Email me: · or message me on LinkedIn

There are a lot of tools being promoted for "vibe coding" in WordPress, so I thought I'd take Claude Code for a ride and see if I'm missing anything.

First rule - don't buy anything for it. No page builder, no premium theme, no staging service, no deploy plugin, no sync plugin. The theme is Twenty Twenty-Five, the free default. The only thing I pay for is the Claude subscription (which I have anyway :) ).

That's really the point of this post. You don't need the fancy tools. You need three things:

  1. to understand how WordPress actually works - check!
  2. to know Claude Code well enough to set it up properly - check!
  3. some creativity - check!

Claude Code wrote 90% of the CSS, and I'm not going to pretend otherwise. The three things above are what made that safe, and they're what the rest of this post is about.

Where the site was

The site is yuvalk.com, the portfolio of my son, a film director and writer studying at ESCAC (one of the best film schools out there). Content in Spanish, a normal small WordPress install: a custom post type for projects (a short, a vlog), a taxonomy for the three sections.

And, like most sites that grow for a few years, its custom code lived in the wrong places.

I pasted the PHP (a block for the section cards, custom ordering, two shortcodes, the analytics snippet) into the parent theme's functions.php. The styling was all over the place, including ten snippets in a CSS plugin.

Both worked. Both were one theme update away from disappearing, and the snippets lived in a database table where neither git nor an agent could see them.

Point an AI agent at a site like that and say "make the home page look like a cinema", and it will happily edit functions.php in the parent theme, because that's where the code is. It doesn't know that folder is a landmine.

You do, if you know how WordPress works. That's the first ingredient.

Ingredient one: knowing WordPress

Almost everything people buy a tool for here, WordPress already does, or a few lines of script can do.

A local copy instead of a staging service

A full backup of live, restored into MAMP on my Mac - that's just because I am used to working like that, but you can use whatever you are used to.

The rule from the first minute: the copy goes one way. Live comes down to local. Nothing goes back up that way, ever, because the moment you overwrite live with a full copy you lose everything anyone edited there since you pulled it.

A child theme instead of a premium theme or a builder

A child theme is built into WordPress and costs nothing, and if you wanna understand how basic and old this concept is, here I am at WordCamp Seville 2012 talking about it :)

I called this one yuvalk and everything moved into it: the PHP into one include file, the ten snippets into one stylesheet (207 lines), and the templates that had been edited in the Site Editor into real files. The snippets went to Draft, and the CSS plugin now has nothing to do.

One wrinkle worth showing. The live parent theme still had the old code in it, and defining the same PHP function twice is a fatal error. So the child theme skips its own copy while the old one exists:

add_action( 'after_setup_theme', function () {
	if ( function_exists( 'show_genre_type_statement' ) ) {
		return; // the old copy in the parent theme is still there
	}
	require get_theme_file_path( 'inc/site-features.php' );
}, 20 );

Upload the child theme, activate it, update the parent (which deletes the old code), and the child takes over by itself. No downtime, no editing files on the server by hand. Claude proposed the guard. I read it twice before I trusted it, and I could only do that because I know the load order.

WP-CLI scripts instead of a sync plugin

Half of what "restyle the home page" means is not styling. It's content: put the new reel next to the bio, drop "(Inacabado)" from a film's title now that it's finished, add two names to a credit. That lives in the database. You could redo each change by hand on live. You'd get one of them slightly wrong.

WP-CLI is free, and it's installed on plenty of shared hosts, DreamHost included. So every change became a small script in a db-changes folder, all with the same shape. Read the current state. If the change is already there, say so and stop. If the state isn't what the script expects, stop and change nothing. Otherwise apply it and say what you did.

$title = get_post_field( 'post_title', 210, 'raw' );

if ( 'El Murmullo del Agua' === $title ) {
	WP_CLI::success( 'Already done. Nothing to do.' );
	return;
}
if ( 'El Murmullo del Agua (Inacabado)' !== $title ) {
	WP_CLI::error( 'Unexpected title: "' . $title . '". Nothing changed.' );
}

Run it locally, look at the page, then run the same file on live over SSH. Six scripts in two days, each safe to run twice, each in git next to the CSS it belongs with. This is the part I hadn't done before, and the one I'd keep even without an agent.

Ingredient two: knowing Claude Code

The agent is only as safe as the setup around it. None of this setup is a product. It's git, rsync and a text file.

A repo that tracks your code, not WordPress

The .gitignore ignores everything and then lets back in only what's ours:

/*
!/.gitignore
!/CLAUDE.md
!/bin/
!/db-changes/
!/docs/
!/wp-content/
/wp-content/*
!/wp-content/themes/
/wp-content/themes/*
!/wp-content/themes/yuvalk/

Core, plugins, uploads and wp-config.php aren't yours, they hold secrets, and they don't belong in git. What's left is small enough to read in one sitting, which matters when your collaborator can rewrite a file faster than you can read it.

A deploy script instead of a deploy service

A short bash script, bin/deploy. With no arguments it does an rsync dry run against live and lists what would change. With --go it uploads the child theme folder, and only that folder, then clears the page cache. It refuses to run while the theme has uncommitted changes, so live always matches a commit you can point at:

if [[ -n "$(git status --porcelain -- wp-content/themes/yuvalk)" ]]; then
	echo "Uncommitted changes in the theme. Commit first."
	exit 1
fi

That refusal turns "the agent pushed something" into "the agent pushed commit 4bd70ec, and here's the diff". And the rule that it only deploys when I ask, preview first, is written down where Claude reads it every session.

A CLAUDE.md that learns

A CLAUDE.md in the site root: where things live, the data model, the rules (never edit core, plugins or the parent theme; relative URLs only; commit after each working change).

The useful part is what piled up in it. Plain wp couldn't reach MAMP's database, so a small wrapper that uses MAMP's PHP went into bin and the rule went into the file. Templates edited in the Site Editor sit in the database and silently override the files, so that went in too, with the command to check. Every time the agent tripped over something, the fix landed in CLAUDE.md, and the second session was noticeably faster than the first.

Ingredient three: a bit of creativity

This is the fun part, and it's where no tool helps you anyway.

Section cards styled as cinema screens. Too heavy. Slim modern TV screens instead. The reel gets the same frame. A bit of side margin. The small testimonial block that held the bio, twelve-pixel text next to a round photo, replaced with a proper name, a role line and the paragraph, so it holds its own next to the video.

Five commits in the second session, each previewed against live before upload.

Some ideas we didn't build yet (looping clips instead of stills, a preloader, inspired by a site I liked but built our own way) went into a docs file with what blocks them: short silent clips per project, which don't exist yet. Parked, not lost.

Creativity also counts in the plumbing. A guard that lets two copies of the same code coexist for ten minutes. A content change that checks before it writes. Those aren't features anyone sells you. They come from knowing how the pieces fit and asking "what's the simplest thing that can't go wrong here?"

To wrap up

I spent twelve years at a company that sells a paid WordPress plugin, so I'm not against paying for software :) But - pay for the thing that does something you can't.

Before you buy a tool, check whether WordPress already does it. The agent doesn't need the builder. It needs someone who knows which folder is a landmine, how to set it up so a wrong guess costs a git revert and not a Saturday, and what the site should actually look like.

Understand WordPress. Learn your agent. Be creative and then let it rip.

building-with-aiwordpress

← Back