Work Pricing FAQ Blog Jobs Trending Book the AI Audit

HomeBlogHow to Build WordPress Custom Post Types with Claude Code

How to Build WordPress Custom Post Types with Claude Code

I've built WordPress custom post types with Claude Code for a dozen clients in the past six months, and the process is faster, cleaner, and more maintainable than using a plugin like ACF or Pods. If you know what data structure you need — a portfolio, team members, locations, case studies, events — you can have it live in under an hour with no recurring plugin fees and full control over how it works.

Here's exactly how I do it, why I choose this approach over plugins, and what a working custom post type setup looks like in practice.

Why Build Custom Post Types Programmatically

Most WordPress developers reach for Advanced Custom Fields or Custom Post Type UI when a client needs structured content beyond blog posts. Those plugins work, but they come with trade-offs I don't love:

  • Performance overhead — every plugin adds queries and admin scripts, even if you're only using 10% of the features
  • Vendor lock-in — your data structure becomes dependent on that plugin's update cycle and pricing decisions
  • Migration headaches — moving a site or changing hosts gets messier when custom fields are tied to plugin-specific database tables
  • Ongoing cost — ACF Pro is $49/year per site, which adds up when you manage multiple client sites

Building custom post types in code means you own the logic. It lives in your theme or a must-use plugin, travels with the site, and costs nothing after the initial build. For most use cases — anything short of a full e-commerce catalog with hundreds of SKU variations — the native WordPress post type and meta field system is more than enough.

The Core Workflow with Claude Code

I start every custom post type build the same way: with a clear spec of what content the client needs to manage. Let's say a Vancouver real estate agent wants a "Properties" post type with fields for price, bedrooms, bathrooms, square footage, and listing status.

I give Claude Code a prompt that looks like this:

Create a WordPress custom post type called "Properties" with the slug "property".

Include these custom fields:
- Price (number, required)
- Bedrooms (number)
- Bathrooms (number)
- Square Footage (number)
- Listing Status (select: active, pending, sold)

Register the post type with public visibility, archive page, single template support, and featured image.

Add a custom taxonomy called "Neighbourhood" that supports hierarchical terms.

Generate the complete PHP for functions.php including:
1. register_post_type() function
2. register_taxonomy() function
3. Custom meta box for property details
4. Save function for meta fields with nonce verification
5. Helper function to retrieve property meta

Claude Code outputs a working PHP file in about 90 seconds. I review it, test it locally, and if the logic is sound, I deploy it. The whole process — from brief to live custom post type — takes 30–45 minutes.

What the Generated Code Actually Does

The code Claude Code produces follows WordPress best practices and handles the full lifecycle of a custom post type:

  • Registration — the register_post_type() call defines the post type slug, labels, capabilities, and which features it supports (title, editor, thumbnail, revisions)
  • Custom taxonomy — if you need categorization (like "Neighbourhood" for properties), it registers a taxonomy and associates it with the post type
  • Meta box UI — a custom admin panel where editors input structured data, with proper HTML5 input types and validation
  • Save handler — sanitizes and saves meta field values with nonce security checks, so only authorized users can edit
  • Retrieval helpers — simple functions like get_property_price($post_id) that fetch meta values without repetitive get_post_meta() calls

The real win here is maintainability. Six months from now, when the client asks for a new field, I open the file, add the field to the meta box array, update the save function, and redeploy. No plugin settings to export, no database migrations, no compatibility checks.

Example Code Structure

Here's what a simplified version of the generated code looks like for the Properties post type:

function register_property_post_type() {
  $labels = array(
    'name' => 'Properties',
    'singular_name' => 'Property',
    'add_new_item' => 'Add New Property',
    'edit_item' => 'Edit Property',
    'view_item' => 'View Property',
  );

  $args = array(
    'labels' => $labels,
    'public' => true,
    'has_archive' => true,
    'supports' => array('title', 'editor', 'thumbnail'),
    'rewrite' => array('slug' => 'properties'),
    'show_in_rest' => true,
  );

  register_post_type('property', $args);
}
add_action('init', 'register_property_post_type');

That's the post type registration. The meta box and save functions are another 50–70 lines, all of which Claude Code generates based on the field list you provide.

Custom Taxonomies and Archive Pages

One feature clients often need is filtering — browsing properties by neighbourhood, sorting team members by department, or filtering case studies by industry. WordPress taxonomies handle this natively, and Claude Code sets them up automatically when you specify them in the prompt.

For the Properties example, the taxonomy code looks like this:

function register_property_taxonomy() {
  register_taxonomy('neighbourhood', 'property', array(
    'labels' => array('name' => 'Neighbourhoods', 'singular_name' => 'Neighbourhood'),
    'hierarchical' => true,
    'show_in_rest' => true,
    'rewrite' => array('slug' => 'neighbourhood'),
  ));
}
add_action('init', 'register_property_taxonomy');

Once that's live, editors can create terms like "Kitsilano," "Yaletown," "Mount Pleasant" and assign them to properties. The archive page at /neighbourhood/kitsilano/ works out of the box — no extra routing required.

Displaying Custom Fields in Templates

The last piece is rendering the custom fields on the front end. I usually build a custom single template (single-property.php) or use a block theme pattern to pull in the meta values.

Claude Code can generate the template logic too. A basic property detail block might look like:

<div class="property-details">
  <p><strong>Price:</strong> $<?php echo number_format(get_post_meta(get_the_ID(), 'property_price', true)); ?></p>
  <p><strong>Bedrooms:</strong> <?php echo get_post_meta(get_the_ID(), 'property_bedrooms', true); ?></p>
  <p><strong>Bathrooms:</strong> <?php echo get_post_meta(get_the_ID(), 'property_bathrooms', true); ?></p>
  <p><strong>Status:</strong> <?php echo ucfirst(get_post_meta(get_the_ID(), 'property_status', true)); ?></p>
</div>

If you want it cleaner, use the helper functions Claude Code generates. Instead of get_post_meta() calls, you'd write get_property_price() and keep the template readable.

When This Approach Makes Sense

This workflow works best when:

  • You have a defined content model and won't need editors to add new field types on the fly
  • The site has fewer than 10 custom post types (beyond that, a framework like ACF starts to make sense for speed)
  • You want full version control — the entire data structure lives in your Git repo
  • You're building for a client who won't be hiring another developer unfamiliar with custom code

If the client needs a visual field builder or wants non-technical staff to modify the data structure themselves, a plugin is probably the better choice. But for most small business WordPress sites — local services, consultants, small e-commerce stores — programmatic custom post types are faster, cheaper, and more reliable long-term.

Real-World Example: Legal Practice Areas

I recently built a custom post type for a Vancouver law firm that wanted to manage "Practice Areas" with structured content for each service line. Each practice area needed:

  • A description (WordPress editor)
  • A list of typical case outcomes (repeater-style, but implemented as serialized array)
  • Attorney assignment (relationship to another custom post type, "Attorneys")
  • Related case studies (manual selection from another post type)

Claude Code generated the full setup in one session. The firm's marketing coordinator can now add new practice areas without touching code, and the site displays them with a clean archive and detail template. Total build time: 90 minutes. Cost to the client: part of a $2,800 site build, versus paying $200/year for ACF Pro across three sites.

How to Get Started

If you want to try this for your own site or a client project, here's the fastest path:

  1. Write a one-paragraph spec of the content type and the fields you need
  2. Open a Claude Code session and paste the prompt template I showed above, customized to your needs
  3. Review the generated PHP — check that the field types match your intent and the save function sanitizes inputs properly
  4. Add the code to a custom plugin file or your theme's functions.php
  5. Test locally, then deploy

The first time takes an hour because you're learning the pattern. After that, each new post type takes 20–30 minutes.

If you want help setting this up for a specific use case — or if you're managing multiple WordPress sites and want to standardize on a programmatic approach — I walk through it in detail on client calls. You can see more about how I use Claude Code for WordPress automation or book a session to build your first custom post type together.

The tools are here. The question is just whether you want to keep renting your data structure or own it outright.

Work with me

Want this kind of result for your business?

Start with the AI Audit — $1,500. One focused engagement. The 3 highest-ROI opportunities in your business, ranked. A working proof-of-concept of the #1. Credited toward your build if we go forward.

Book the AI Audit → Read the FAQ
← All posts Book the AI Audit →