For years, registering a Custom Post Type (CPT) in WordPress meant either writing PHP in your theme's functions.php file or relying on a dedicated third-party plugin like Custom Post Type UI. Since version 6.1, Advanced Custom Fields (ACF) has completely streamlined this process. You can now build, configure, and manage Custom Post Types directly from the ACF dashboard. It keeps your plugin stack lean and your data architecture centralised.
Here is a comprehensive guide to building a custom post type—let's use a “Portfolio Project” as our example—entirely within the ACF interface.
Step 1: Accessing the CPT Builder
First, ensure you are running ACF version 6.1 or higher. The free version on the WordPress repository works perfectly for this; you do not need an ACF Pro license to register post types.
- Log into your WordPress admin dashboard.
- Navigate to ACF > Post Types in the left-hand menu.
- Click the Add New button at the top of the screen.
Step 2: The Basic Configuration
You will be presented with a clean, straightforward interface. The basic settings are exactly what WordPress needs to identify and label your new content type in the dashboard.
Fill out the following fields:
- Plural Label: Projects (This is what appears in the main left-hand WordPress menu).
- Singular Label: Project (This is used for buttons like “Add New Project”).
- Post Type Key: project (This is the internal name. It must be lowercase, with no spaces. Use hyphens or underscores if you have multiple words, e.g., portfolio_project).
- Hierarchical: Leave this disabled for most CPTs (like projects, staff members, or products). This makes them behave like standard blog posts. Enable this only if you want them to behave like Pages, where one project can be the “parent” of another.
Once these three fields are populated, you could just hit “Save Changes” and be done. However, for a professional build, you need to configure how this post type actually behaves.
Step 3: Advanced Settings Configuration
Toggle the Advanced Configuration switch at the bottom of the basic settings to reveal the granular controls. These dictate how the CPT interacts with the rest of WordPress.
Here are the critical tabs you need to review:
1. General
This tab controls which native WordPress meta boxes appear on the editing screen. By default, only “Title” and “Editor” are checked.
- Title: Essential. Leave checked.
- Editor: Essential for the main content area.
- Featured Image: Highly recommended for portfolios, directories, or products.
- Excerpt: Useful if you want to write custom short descriptions for the archive grid.
2. URLs
- Permalink Rewrite: This dictates the URL structure. By default, it uses the Post Type Key. For our example, a single project will live at [yourdomain.com/project/project-name]. If you want the URL to say [yourdomain.com/portfolio/project-name], you would change the “Custom Rewrite Slug” to portfolio.
- Archive: Toggle this On. This allows WordPress to generate a main directory page (e.g., [yourdomain.com/projects/]) that lists all your published CPTs.
3. REST API
- Show in REST API: Ensure this is toggled On. If you turn this off, WordPress will force you to use the outdated, pre-2018 Classic Editor for this Custom Post Type. Leaving it on enables the modern Gutenberg Block Editor.
Once you have configured these settings, click Save Changes in the top right corner. You will see a new “Projects” icon appear in your WordPress sidebar.
Step 4: Displaying the Custom Post Type
Now that your Custom Post Type exists, you can start adding content. However, your site's visitors won't be able to see it properly until you tell your WordPress theme how to display it. WordPress uses the Template Hierarchy to figure out which file should render your custom content. For a CPT with the key project, WordPress will automatically look for two specific files in your active theme:
- archive-project.php: This controls the main directory page that lists all projects.
- single-project.php: This controls the individual, dedicated page for a single project.
If you don't create these files, WordPress will fall back to using archive.php and single.php (or index.php), which rarely look correct for custom data.
Here is a basic skeleton for these files, which you should place in your theme folder (or create a simple plugin):
single-project.php
<?php /** * The template for displaying all single Projects. */ get_header(); // Start the WordPress Loop if ( have_posts() ) : while ( have_posts() ) : the_post(); ?> <article id="post-<?php the_ID(); ?>" <?php post_class( 'custom-project-layout' ); ?>> <header class="project-header"> <h1 class="project-title"><?php the_title(); ?></h1> </header> <?php if ( has_post_thumbnail() ) : ?> <div class="project-featured-image"> <?php the_post_thumbnail( 'large' ); ?> </div> <?php endif; ?> <div class="project-content"> <?php the_content(); ?> </div> </article> <?php endwhile; endif; get_footer(); ?>
archive-project.php
<?php /** * The template for displaying the Project archive. */ get_header(); ?> <main class="project-archive-container"> <header class="archive-header"> <h1>Our Portfolio</h1> </header> <div class="project-grid"> <?php // Start the standard WordPress loop for the archive if ( have_posts() ) : while ( have_posts() ) : the_post(); ?> <article class="project-card"> <?php if ( has_post_thumbnail() ) : ?> <a href="<?php the_permalink(); ?>" class="project-thumbnail-link"> <?php the_post_thumbnail( 'medium' ); ?> </a> <?php endif; ?> <h2 class="project-card-title"> <a href="<?php the_permalink(); ?>"><?php the_title(); ?></a> </h2> <div class="project-excerpt"> <?php the_excerpt(); ?> </div> </article> <?php endwhile; // Standard pagination for large portfolios the_posts_pagination( array( 'mid_size' => 2, 'prev_text' => 'Previous', 'next_text' => 'Next', ) ); else : ?> <div class="no-results"> <p>No projects have been published yet.</p> </div> <?php endif; ?> </div> </main> <?php get_footer(); ?>
Step 5: Add Some Projects
Now we need to add some projects to our new post type. Simply click on Projects from the sidebar and begin adding your new projects by filling in the relevant data fields.
You can now view your projects at [yourdomain.com/projects/]
Step 6: The Pro Move – Exporting Your Architecture to Code
Building your Custom Post Types and fields in the ACF user interface is incredibly fast, but stopping there leaves your site's core architecture sitting in the WordPress database. Every time a page loads, WordPress has to query the database to figure out if your “Projects” post type exists. Furthermore, if an administrator accidentally deletes the CPT from the ACF dashboard, your front-end will immediately break.
The professional standard is to export this configuration into your codebase. This reduces database queries, makes your architecture version-controllable (via Git), and client-proofs your site. Here is how you export everything we just built:
The Generate PHP Method (Maximum Lockdown)
This method takes your ACF configuration, converts it into raw PHP, and allows you to lock it away inside a custom plugin or your child theme's functions.php file.
- Navigate to ACF > Tools in your WordPress dashboard.
- Select the Generate PHP tab.
- Check the box next to your Projects Custom Post Type (and any field groups you created for it).
- Click the Generate PHP button.
ACF will output a block of perfectly formatted PHP code. You can now add this to your themes functions.php or even better would be to create a custom plugin for it.
Create a file named wpac-projects.php in your wp-content/plugins folder, paste the generated code inside, and wrap it in a basic plugin header:
Once you activate this plugin in your WordPress dashboard, you can safely delete the Post Type from the ACF user interface. Your custom plugin is now handling the heavy lifting, running straight from the server rather than the database.
The Local JSON Method (The Hybrid Approach)
If you prefer to keep using the ACF visual builder but still want the benefits of version control and performance optimization, use ACF Local JSON.
- Open your active theme (or child theme) folder via FTP or your code editor.
- Create a new, empty folder named acf-json.
- Ensure the folder has the correct write permissions.
- Re-save your Post Type via the acf interface to generate the necessary JSON
From now on, whenever you save a Post Type or Field Group in the ACF dashboard, a lightweight .json file is automatically saved into that folder. ACF will load your configurations directly from these files instead of querying the database. It is incredibly efficient, keeps your setup portable, and gives you the absolute best of both worlds. More info on using JSON with ACF (aff).
Wrapping Up
By leveraging Advanced Custom Fields for your post types, you eliminate the need for bloated third-party CPT plugins. You gain a cleaner admin area, faster database performance, and a completely streamlined workflow. Build it visually, export it to code / JSON, and enjoy a faster, more robust WordPress site.




