Full-Site Generation

Reviewing and Hardening AI-Generated Theme Code

⏱ 15 min

The theme from the previous lesson renders. Rendering correctly and being safe to run are two different bars, and an AI coding agent clears the first one far more reliably than the second. This lesson is the checklist you run before a generated theme, or any generated plugin code, gets to leave your local Studio site.

What you'll learn in this lesson
The four review categories that matter most
Escaping, capability checks, nonces, and accessibility, in that priority order.
What a passing versus failing example looks like
Concrete before/after code, not abstract advice.
How to have the agent self-check first
Using the checklist itself as a prompt, then verifying the answer yourself.
When to reject a file outright
Patterns severe enough that patching in place isn't the right call.
Prerequisites

A generated theme or plugin from the previous lesson (or any AI-generated WordPress code) sitting in your local Studio site, ready for line-by-line review.

Step 1: escaping, checked at the point of output

Every dynamic value printed into a template needs to be escaped where it’s printed, not somewhere earlier in the code.

// Fails review: title printed with no escaping
<h1><?php echo $post_title; ?></h1>

// Passes review: escaped at the point of output
<h1><?php echo esc_html( $post_title ); ?></h1>
Escaping checklist
Text content uses esc_html()
Anywhere a string lands between HTML tags.
Attributes use esc_attr()
Any value inside a href, src, class, or data- attribute.
URLs use esc_url()
Especially anything built from user input or a settings field.
Limited HTML uses wp_kses_post() or wp_kses() with an explicit allow list
Never raw echo of anything that might contain HTML from an untrusted source.

Step 2: capability checks on anything that changes state

A generated form handler, AJAX callback, or REST route needs an explicit capability check, independent of whether a nonce is also present.

// Fails review: nonce checked, but no capability check
function my_theme_handle_settings_save() {
	check_admin_referer( 'my_theme_settings' );
	update_option( 'my_theme_settings', $_POST['settings'] );
}

// Passes review: both checks present
function my_theme_handle_settings_save() {
	check_admin_referer( 'my_theme_settings' );
	if ( ! current_user_can( 'manage_options' ) ) {
		wp_die( esc_html__( 'You do not have permission to do this.', 'my-theme' ) );
	}
	update_option( 'my_theme_settings', sanitize_text_field( wp_unslash( $_POST['settings'] ) ) );
}

A nonce proves the request came from your own form. It says nothing about whether the person submitting it should be allowed to. Generated code frequently gets this wrong in exactly this way, a nonce check that reads like a complete security measure and isn’t one.

Step 3: nonces on every state-changing form

Nonce checklist
wp_nonce_field() is present in every form that changes state
Settings forms, custom admin actions, anything beyond a simple GET request.
The handler verifies it before doing anything else
check_admin_referer() or wp_verify_nonce(), called first, not after other logic has already run.
The nonce action name is specific
Not a generic string reused across multiple unrelated forms in the same plugin.

Step 4: accessibility, the category generated themes fail most quietly

Escaping and capability failures usually show up as a security bug someone eventually finds. Accessibility failures in generated theme markup tend to just sit there, technically working, genuinely excluding real users.

<!-- Fails review: image with no alt text, button with no accessible label -->
<img src="/hero.jpg">
<button class="menu-toggle"></button>

<!-- Passes review: alt text present, accessible label on an icon-only button -->
<img src="/hero.jpg" alt="Fresh sourdough loaves cooling on the bakery counter">
<button class="menu-toggle" aria-label="<?php esc_attr_e( 'Open menu', 'my-theme' ); ?>"></button>
Accessibility checklist
Every meaningful image has real alt text
Not empty alt="", unless the image is genuinely decorative.
Icon-only buttons and links have an accessible name
aria-label or visually-hidden text, not just a class name.
Heading levels are sequential
Generated templates commonly jump from h1 straight to h4 because visual size, not document structure, drove the choice.
Color contrast in theme.json meets WCAG AA
Check text-on-background pairs from the palette, not just that they look fine to you.
Interactive elements are keyboard-reachable
Anything with a click handler needs to also work on Enter/Space if it isn't already a real button or link element.

Step 5: have the agent self-check first, then verify yourself

You can run this entire checklist as a prompt before you ever open the file yourself:

Review every template and PHP file in this theme against this checklist:
escaping at the point of output, capability checks on anything that changes
state, nonces on state-changing forms, and accessibility (alt text, heading
order, accessible names on icon-only controls). List every file where you
find a violation, with the specific line and what's wrong.

Treat the response as a starting point, not a verdict. Spot-check at least the files it flagged as clean, an agent grading its own generated output has the same blind spots reviewing that it had while writing.

Step 6: know when to reject a file outright

Some failures are worth patching in place. Others mean the file should be regenerated from scratch rather than fixed line by line.

Reject and regenerate, don't patch, when you see this

A database query built with string concatenation instead of $wpdb->prepare(), a form handler with no capability check at all (not just a weak one), or a file that hallucinated a core function and built significant logic around it. These indicate the generation missed a fundamental constraint, not a single line, and patching around a fundamentally wrong approach tends to leave subtler versions of the same mistake nearby.

Recap

Escaping at the point of output, capability checks independent of nonce checks, nonces on every state-changing form, and accessibility fundamentals, alt text, heading order, accessible names, keyboard reachability, are the four categories worth checking on every piece of AI-generated theme or plugin code before it’s trusted. Asking the agent to self-check against this list is a useful first pass, never a substitute for actually reading the files it flagged as clean, and a fundamentally wrong approach gets rejected and regenerated, not patched.

Resources & further reading

← Safe Full-Site Generation: From Plain-English Description to a Deployed Block Theme Course Recap: A Responsible AI Coding Workflow for WordPress →