How to Register a Custom Post Type in WordPress (Step-by-Step)
The complete register_post_type() walkthrough, including the rewrite-rules gotcha that causes a confusing 404 every time.
Advanced Custom Fields (ACF) is the plugin that turns WordPress from "a blogging platform with some custom fields bolted on" into a genuine flexible CMS. Here's how to go from installing it to displaying custom data on the frontend.
In the WordPress admin, go to Custom Fields → Add New. Add fields (text, image, repeater, relationship, etc.), then set the location rule — e.g., "Post Type is equal to Testimonial" — so this field group only appears where it's relevant.
<?php if (have_rows('features')) : ?>
<ul>
<?php while (have_rows('features')) : the_row(); ?>
<li><?php the_sub_field('feature_name'); ?></li>
<?php endwhile; ?>
</ul>
<?php endif; ?>
$image = get_field('hero_image');
if ($image) {
echo '<img src="' . esc_url($image['url']) . '" alt="' . esc_attr($image['alt']) . '">';
}
For any real project, define field groups in PHP or export as local JSON rather than only in the database UI — this makes fields version-controllable and lets them ship with your theme/plugin across environments:
acf_add_local_field_group([
'key' => 'group_hero',
'title' => 'Hero Section',
'fields' => [
['key' => 'field_hero_image', 'name' => 'hero_image', 'type' => 'image'],
],
'location' => [[['param' => 'post_type', 'operator' => '==', 'value' => 'page']]],
]);
By default, ACF field values don't appear in the REST API response automatically. Add show_in_rest when registering fields, or hook into rest_prepare_{post_type} to manually add them — essential if a headless frontend (Next.js, for example) is going to consume this content.
Once ACF clicks, most "can the client edit this themselves" requirements stop meaning custom admin pages and just mean one more field group.
The complete register_post_type() walkthrough, including the rewrite-rules gotcha that causes a confusing 404 every time.
Actions vs filters, safe functions.php structure, and the defensive habits that keep a single typo from taking down your site.
The mental model behind every WordPress plugin and theme — and how to create your own hooks so others can extend your code too.