Get a Free Quote

How to Create a WordPress Custom Post Type

A WordPress custom post type lets you add your own kind of content to the dashboard, separate from ordinary posts and pages, so things like portfolios, testimonials, team members, or events each get their own tidy home. Instead of forcing every piece of content into a blog post, you create a content type that fits its shape, with its own admin menu, its own fields, and its own URLs.

This tutorial shows both ways to create one: the no code plugin method and the code method with register_post_type(). We also cover custom taxonomies, custom fields, how to display the content with templates, and the permalink trap that leaves so many people staring at a 404. If you would rather have it built for you, you can get a free quote.

What Is a Custom Post Type

A WordPress custom post type is a content type you define yourself, separate from the built in posts and pages, so you can manage a specific kind of content on its own terms. Out of the box WordPress ships with a handful of content types you already use without thinking about them: posts for your blog, pages for static content like About and Contact, plus a few behind the scenes types for attachments, navigation menus, and revisions. A custom post type adds a brand new kind of content to that list, with its own admin menu, its own editing screen, and its own place in your database.

The reason this matters is organisation and control. Imagine you run a design studio and you want a portfolio. You could publish each project as a normal blog post, but then your projects and your articles get mixed together in the same list, share the same categories, and use the same template. That gets messy fast. A Portfolio custom post type gives projects their own menu item in the dashboard, their own set of categories, their own URL structure like /portfolio/riverside-cafe/, and their own template so a project page can look completely different from a blog post. The content is cleanly separated, easier to manage, and easier for visitors to browse.

Think of the WordPress dashboard as a filing cabinet. Posts are one drawer, pages are another. A custom post type is you adding a new labelled drawer for a specific kind of paperwork, so it does not end up jammed into a drawer that was never meant to hold it. This guide walks through what custom post types are for, both ways to create one, how to show them on your site, and the traps that catch people. If you would rather have a developer set this up properly, you can get a free quote and we will build it for you.

Posts Blog articles Pages About, Contact + Portfolio Testimonials Events Anything else you define
Built in types (posts, pages) on the left, custom post types you add on the right. The examples are illustrative of common uses.
Thinking about a new WordPress website?Get a free consultation and a fixed-scope quote. A senior engineer replies within 24 hours. No obligation.
Get a Free Quote

When to Use a Custom Post Type

Not every piece of content needs its own post type. The test is simple: if the content is meaningfully different from a blog post or a page, has its own set of fields, and you want to manage or display it as a group, a custom post type earns its keep. If it is just another article, a normal post is fine. Reaching for a custom post type when a category would do only adds complexity.

Here are the situations where a custom post type is usually the right call.

  • Portfolio or projects. A studio, agency, photographer, or freelancer showing work. Each project has an image gallery, a client name, a year, and a description, and you want a dedicated portfolio archive.
  • Testimonials or reviews. Short pieces of content with a person's name, company, and quote, displayed in sliders or grids across the site rather than as blog posts.
  • Team members or staff. Each person has a photo, a role, a bio, and social links. A Team post type keeps them tidy and lets you output a staff page automatically.
  • Products or a catalogue. If you are not running a full store but want to list products, services, or menu items with their own fields and archive.
  • Events. Each event has a date, a location, and a ticket link, and you want an events calendar or upcoming events list.
  • Properties, listings, or vehicles. Real estate, rentals, or dealerships where each item has structured details like price band, bedrooms, or mileage.
  • Case studies, recipes, courses, FAQs, or knowledge base articles. Any repeating, structured content that deserves its own home.

The common thread is repeating content with its own shape. When you find yourself thinking "these all have the same three or four fields and I want them listed together, but they are not blog posts", that is a custom post type asking to exist. If your project is large or the content type sits at the centre of the site, it is worth planning this properly, which is where a custom WordPress development approach pays off.

Need a content type built around your business?Get a free, no-obligation quote and we will design and build custom post types that fit exactly how your team works.
Get a free quote

Plugin or Code: Which Method

There are two ways to create a custom post type: with a plugin that gives you a form to fill in, or with a few lines of code. Both end up in the same place, a registered post type that behaves the same way. The difference is who does the work and where the definition lives. Neither is wrong, and the right choice depends on who is building the site and how much control you want.

The plugin route is faster to start with and needs no code, which suits site owners and non technical users. You click through a screen, type in some labels, tick a few boxes, and your post type appears. The trade off is that the definition lives inside the plugin's settings, so the post type depends on that plugin staying installed and active.

The code route puts the definition in your theme or a small plugin of your own, which is how most developers do it on client sites. It is more portable, has no ongoing dependency on a third party plugin, and gives you full control over every option. The trade off is that you need to be comfortable editing a PHP file and you should never edit the parent theme directly.

ConsiderationPlugin methodCode method
Skill neededNone, point and clickComfortable editing PHP
Speed to set upVery quickQuick once you have a snippet
DependencyRelies on the plugin staying activeLives in your code, no third party dependency
ControlCommon options exposed in a formEvery argument available
PortabilityTied to the plugin's dataMove the file, move the post type
Best forSite owners, quick builds, prototypingDevelopers, client sites, long term projects

A practical middle path many people use: prototype with a plugin to get the shape right, then have a developer move the definition into code before launch so there is no lingering dependency. We will cover both methods in full so you can pick.

Method 1: Create a CPT With a Plugin

The most widely used plugin for this is Custom Post Type UI, a free plugin that gives you a form for creating post types and taxonomies without writing code. Here is how the process works, described step by step.

Step 1: Install the plugin

In your dashboard go to Plugins, then Add New, search for Custom Post Type UI, install it, and activate it. A new menu item labelled CPT UI appears in the left hand admin menu. This is where all your post type and taxonomy settings will live.

Step 2: Add a new post type

Open CPT UI, then Add / Edit Post Types. You will see a form. The first field is the post type slug, the internal name WordPress uses, which should be lowercase, short, and use no spaces, for example portfolio. Below that are the plural and singular labels, such as Portfolios and Portfolio, which are the words that appear throughout the admin. There is a handy button that auto fills all the label text for you from those two words, which saves a lot of typing.

Step 3: Set the important options

Scroll down to the Settings section. The options that matter most for a normal, publicly visible post type are these. Set Public to true so the post type is visible on the site and in the admin. Set Has Archive to true if you want an archive page that lists all items, for example a page at /portfolio/. Under Supports, tick the editing features you want the post type to have, such as Title, Editor, Featured Image (called Thumbnail), and Excerpt. Choose a menu icon and a menu position if you like, so your new type gets a recognisable icon in the admin sidebar. Make sure Show in REST is on, which is required for the block editor to work and for the post type to appear in the REST API.

Step 4: Save and check

Click Add Post Type at the bottom. Your new post type appears in the admin menu straight away, with Add New and All Portfolios items, exactly like Posts. Add one to test it. Because the plugin flushes the permalink rules for you when you save, the archive and single URLs usually work immediately, which avoids the 404 trap we cover later.

That is the whole process. In a couple of minutes you have a working custom post type with no code. The one thing to keep in mind is the dependency: if you deactivate Custom Post Type UI, the post type registration disappears and your items, while still safe in the database, stop showing up until it is reactivated or the type is registered again in code. That is the main reason developers often prefer the code method for sites that need to last.

Prefer it done right the first time?Get a free, no-obligation quote and we will register your post types in clean, dependency free code that survives plugin changes.
Get a free quote
Ready to bring your WordPress project to life?Get a free consultation and a fixed-scope quote. A senior engineer replies within 24 hours. No obligation.
Get a Free Quote

Method 2: Register a CPT With Code

The code method uses a single WordPress function, register_post_type(), called on the init hook. You can place this code in a small custom plugin (the cleaner choice) or in your theme's functions.php file. If you use a theme file, always use a child theme so your changes are not wiped out when the parent theme updates. Better still, put it in a tiny plugin so the post type survives a theme change as well, which is exactly what a small custom WordPress plugin is for.

Here is a complete, working example that registers a Portfolio post type with sensible labels and options.

<?php
function wpd_register_portfolio_cpt() {
    $labels = array(
        'name'               => 'Portfolios',
        'singular_name'      => 'Portfolio',
        'menu_name'          => 'Portfolio',
        'add_new'            => 'Add New',
        'add_new_item'       => 'Add New Project',
        'edit_item'          => 'Edit Project',
        'new_item'           => 'New Project',
        'view_item'          => 'View Project',
        'search_items'       => 'Search Projects',
        'not_found'          => 'No projects found',
        'all_items'          => 'All Projects',
    );

    $args = array(
        'labels'             => $labels,
        'public'             => true,
        'has_archive'        => true,
        'rewrite'            => array( 'slug' => 'portfolio' ),
        'menu_position'      => 20,
        'menu_icon'          => 'dashicons-portfolio',
        'supports'           => array( 'title', 'editor', 'thumbnail', 'excerpt' ),
        'show_in_rest'       => true,
    );

    register_post_type( 'portfolio', $args );
}
add_action( 'init', 'wpd_register_portfolio_cpt' );

Save the file, reload the admin, and a Portfolio menu appears. A few things about this code are worth understanding so you can adapt it. The function is hooked to init, which is the correct time to register post types. The first argument to register_post_type() is the post type key, here portfolio, which must be twenty characters or fewer and should not clash with an existing type. The $args array holds every setting, and the next section explains the ones that trip people up.

Notice the wpd_ prefix on the function name. Prefixing your function names with something unique to you avoids collisions with other code on the site, which is a small habit that prevents mysterious fatal errors down the line.

Understanding the Key Arguments

The $args array is where a custom post type gets its personality. You do not need to set every possible option, because WordPress fills in sensible defaults, but a handful of arguments decide how the type behaves. These are the ones to know.

  • public: The master switch. Setting this to true is a shortcut that turns on visibility on the front end, in the admin, and in search. For most content people want to display, true is correct. Set it to false only for internal, hidden data.
  • has_archive: When true, WordPress creates an archive page that lists all items, reachable at the post type slug, for example /portfolio/. Turn this off for types that should only ever appear as single items or inside other pages, like testimonials embedded in a slider.
  • supports: An array listing which editing features the post type has. Common values are title, editor (the main content area), thumbnail (the featured image), excerpt, author, and custom-fields. If your featured image box is missing from the editor, it is almost always because thumbnail was left out of this array.
  • rewrite: Controls the URL structure. Passing array( 'slug' => 'portfolio' ) sets the URL base. This is also where the permalink flushing pitfall lives, covered below.
  • show_in_rest: Must be true for the block editor (Gutenberg) to load for this post type and for the type to appear in the WordPress REST API. If your custom post type opens in the old classic editor unexpectedly, this is usually why. It also matters for headless WordPress setups that read content over the API.
  • menu_position and menu_icon: Cosmetic but useful. Position is a number that decides where the menu item sits in the admin sidebar (5 is under Posts, 20 is under Pages), and the icon accepts a Dashicons class like dashicons-portfolio so your type is easy to spot.
  • hierarchical: When true, the post type behaves like pages, with parent and child relationships and a page style editor. When false (the default), it behaves like posts. Most custom types are non hierarchical.

The full list of arguments is long, and the official register_post_type reference documents every one. You rarely need more than the handful above. Get those right and the post type behaves exactly as you expect.

A few more arguments are worth knowing once the basics click. Setting show_in_menu lets you tuck a post type under another menu rather than giving it a top level item, which keeps the admin sidebar tidy when you have several related types. The capability_type argument controls which user roles can edit the content, defaulting to the same permissions as normal posts, and you can point it at a custom set of capabilities when a post type should only be editable by specific roles. The exclude_from_search argument decides whether items appear in your site's search results, which you might turn on for internal content like testimonials that should show in a slider but not clutter search. And menu_icon accepts not just a Dashicons class but also a base64 encoded SVG or a URL to an image file, so a client's brand icon can sit in the admin menu if you want it there.

One habit that saves time later: decide up front whether a post type is public facing content or internal data, because that single decision drives most of the other arguments. Public content wants public true, an archive, search visibility, and templates. Internal data, the kind you read in code but never show directly, often wants public false, no archive, and show_in_rest only if you need it in the editor or API. Being clear about that intent from the start stops you fighting the defaults.

Adding Custom Taxonomies

A taxonomy is a way of grouping content. Categories and tags are the two taxonomies that come with posts. A custom taxonomy does the same job for your custom post type, letting you file and filter items into groups. For a Portfolio type you might add a Project Type taxonomy with terms like Branding, Web, and Print, so visitors can browse projects by kind.

Taxonomies come in two flavours, and the difference matters. A hierarchical taxonomy works like categories, with parent and child terms and tick box selection. A non hierarchical taxonomy works like tags, a flat list you type into. Choose hierarchical for structured groupings and non hierarchical for free form labels.

You register a taxonomy with register_taxonomy(), also on the init hook. Here is a Project Type taxonomy attached to the portfolio post type.

<?php
function wpd_register_project_type_taxonomy() {
    $labels = array(
        'name'          => 'Project Types',
        'singular_name' => 'Project Type',
        'menu_name'     => 'Project Types',
        'all_items'     => 'All Project Types',
        'edit_item'     => 'Edit Project Type',
        'add_new_item'  => 'Add New Project Type',
        'search_items'  => 'Search Project Types',
    );

    $args = array(
        'labels'            => $labels,
        'public'            => true,
        'hierarchical'      => true,
        'show_admin_column' => true,
        'show_in_rest'      => true,
        'rewrite'           => array( 'slug' => 'project-type' ),
    );

    register_taxonomy( 'project_type', array( 'portfolio' ), $args );
}
add_action( 'init', 'wpd_register_project_type_taxonomy' );

The first argument is the taxonomy key, the second is the post type or types it applies to (you can attach one taxonomy to several post types), and the third is the settings array. Setting show_admin_column to true adds a handy column in the admin list showing each item's terms. As with the post type, show_in_rest true keeps the block editor and the API happy, and the rewrite slug sets the URL base for term archives like /project-type/branding/. If you created your post type with Custom Post Type UI, that same plugin has an Add / Edit Taxonomies screen that does all of this through a form.

Portfolio custom post type Project Type taxonomy Branding, Web, Print archive-portfolio.php lists all projects single-portfolio.php one project page Custom fields (ACF) add client, year, and gallery to each project
How the pieces fit: a post type, an optional taxonomy to group it, and template files to display it. Structure is illustrative.
Want a clear plan and price for your website?Get a free consultation and a fixed-scope quote. A senior engineer replies within 24 hours. No obligation.
Get a Free Quote

Adding Custom Fields

A custom post type gives you the container, but most structured content also needs extra fields. A portfolio project wants a client name, a year, and a project URL. A team member wants a role and social links. An event wants a date and a venue. These extra pieces of data are called custom fields, and the friendly way to add them is a fields plugin.

The most popular is Advanced Custom Fields, usually shortened to ACF. It lets you define a group of fields, choose their types (text, image, date picker, true or false, repeater, and many more), and attach that group to your custom post type. Once set up, the editing screen for each item shows clean, labelled boxes for exactly the data you want, so the person filling it in cannot get it wrong. This is far tidier than the raw custom fields box WordPress includes by default, which is unlabelled and error prone.

The workflow is: install ACF, create a new field group, add your fields, then set the location rule to "Post Type is equal to Portfolio". Now every portfolio item has those fields. To show a field on the front end you call it in your template, for example the_field('client_name') to print a value or get_field('project_url') to fetch one for use in code. Registering the fields to show in REST also makes them available to the API, which matters if you display content with blocks or build a headless front end.

You can register fields in code too, which keeps them version controlled alongside the post type, and on client projects that is often the better long term choice. Whether you use the plugin's interface or code, the goal is the same: give each item the specific fields its content needs, so the content is structured data rather than one undifferentiated blob of text.

It helps to plan the fields before you build them. Sit down with whoever will actually enter the content and list every piece of information a single item carries. For an event that might be a start date, an end date, a venue name, an address, a ticket link, and a short summary. Writing that list first stops you from adding fields piecemeal later, which leaves older entries with gaps. It also reveals which fields should be required, which should have a fixed set of choices, and which need a specific input type like a date picker or an image uploader so the person entering data cannot make a mistake.

Custom fields also open the door to filtering and sorting. Because the values are stored as real data rather than buried in the body text, you can build an archive that sorts events by date, or a properties page that filters by bedrooms, using a query that reads those fields. That is the payoff of structuring content properly: once the data is clean and separated, the ways you can display and organise it multiply. A blog post approach, where the same details are typed into a paragraph, can never do that because the information is not stored as data the site can read.

Displaying Your Custom Post Type

Registering a post type creates the content and the admin screens, but WordPress needs to know how to display it on the front end. By default it falls back to your theme's generic archive and single templates, which often do not suit the new content. To control the look, you add template files named after your post type, and WordPress picks them up automatically through its template hierarchy.

The two templates you will most often create live in your theme (again, use a child theme so updates do not erase them):

Template fileWhat it controlsFalls back to
archive-portfolio.phpThe listing page at /portfolio/ showing all projectsarchive.php, then index.php
single-portfolio.phpAn individual project pagesingle.php, then index.php
taxonomy-project_type.phpA term archive, for example all Branding projectsarchive.php, then index.php

The naming pattern is the key idea. WordPress looks for single-{post_type}.php for a single item and archive-{post_type}.php for the archive, where you swap in your post type key. Because the file exists, WordPress uses it instead of the generic template, and you get full control of the layout. Inside these files you write normal template code: the loop, template tags like the_title() and the_content(), and your ACF field calls like the_field('client_name').

If you are on a block theme or a page builder, the approach differs slightly. Block themes let you edit templates for a custom post type in the Site Editor, and popular builders and many themes offer template builders where you design the single and archive layouts without writing PHP. The underlying idea is identical: you are telling WordPress how this specific content type should look. To pull a few items into any page, for example a "recent projects" strip on the home page, you can use a query loop block or a WP_Query in code that asks for posts of your type.

This is the single most common frustration with custom post types, so it gets its own section. You register a post type with code, add an item, click to view it, and get a 404 Not Found page. The post type is fine, the content is saved, but the URL does not resolve. What went wrong?

WordPress caches its URL routing rules, called rewrite rules, for performance. When you add a new post type with an archive and a rewrite slug, those new rules are not active until the cache is refreshed, a step called flushing the permalinks. Until you flush, WordPress does not know that /portfolio/riverside-cafe/ should map to your new type, so it returns a 404.

The fix is simple and you do not need code for it. Go to Settings, then Permalinks, and click Save Changes. You do not have to change anything, because the act of saving that screen flushes the rewrite rules and your custom post type URLs start working immediately. Do this every time you add a new post type or taxonomy in code, or change a rewrite slug.

A word of caution developers should know: it is tempting to call flush_rewrite_rules() inside your init function so it happens automatically, but that is the wrong place, because it runs on every single page load and slows the site down. If you want to flush in code, do it only on plugin activation with register_activation_hook(), not on init. For most people, visiting the Permalinks screen once after registering the type is the easiest and safest fix. Plugins like Custom Post Type UI flush for you when you save, which is why the 404 rarely appears with the plugin method.

Common Pitfalls and How to Avoid Them

Beyond the permalink trap, a handful of mistakes catch people again and again. Knowing them in advance saves a lot of head scratching.

Choosing a reserved or clashing post type key

Your post type key must be unique and must not use one of WordPress's reserved names such as post, page, attachment, revision, or nav_menu_item. It also must be twenty characters or fewer. Using a generic word risks clashing with a plugin that registers the same key. Prefix your keys with something short and specific to the site, and keep them lowercase with underscores or hyphens, no spaces.

Losing your post type when a plugin is deactivated

If you created the type with a plugin and then deactivate that plugin, the registration disappears and your items vanish from the admin. The content is still safe in the database, but nothing displays until the type is registered again. This is the strongest argument for registering post types in code, ideally in a small standalone plugin, so the definition does not depend on a third party staying installed.

Missing features because supports was incomplete

If the featured image box, the excerpt field, or the main editor is missing from your post type's edit screen, the cause is almost always the supports array. Add the feature you need, such as thumbnail for featured images, and it reappears. This one confuses a lot of people because nothing is broken, the feature was simply never switched on.

The block editor will not load

If your custom post type opens in the old classic editor instead of the block editor, set show_in_rest to true. The block editor is built on the REST API and refuses to load for a post type that is not exposed to it.

Editing the parent theme instead of a child theme

If you put your registration code or your templates in the parent theme's files, the next theme update overwrites them and your work is gone. Always use a child theme for template files, or a small plugin for the registration code, so your changes survive updates.

Forgetting the archive is a real page you can link to

With has_archive true, the archive lives at your rewrite slug, but it is not a page in the Pages list, so it will not appear automatically in menus. To add it to navigation, use a custom link in the menu editor pointing at /portfolio/, or your theme may offer the archive as a menu option.

Running into one of these traps?Get a free, no-obligation quote and our developers will register your post types, taxonomies, and templates the reliable way.
Get a free quote

Custom Post Type Checklist

Here is the whole process as a quick checklist you can work through when adding a new custom post type, whichever method you use.

StepWhat to doWhy it matters
Pick a keyLowercase, unique, 20 chars or fewer, prefixedAvoids clashes and reserved names
Set labelsSingular and plural, filled through the adminClear, correct wording everywhere
Choose methodPlugin for speed, code for portabilityDecides your long term dependency
Set public and has_archiveTrue for most visible contentControls front end visibility
Set supportsTitle, editor, thumbnail, excerpt as neededTurns on the editing features you want
Turn on show_in_restSet to trueEnables the block editor and the API
Add taxonomiesRegister any groupings you needLets visitors filter and browse
Add custom fieldsACF or coded fields for extra dataMakes the content structured
Flush permalinksSave the Permalinks screen onceStops the 404 on new URLs
Add templatessingle and archive files in a child themeControls how the content looks

Work through that list and your custom post type will be registered, grouped, structured, and displayed the way you intended, with none of the common traps left open.

When to Get Help

Creating a basic custom post type is well within reach for a confident site owner, especially with a plugin, and this guide gives you everything you need to try it. But custom post types are also where a simple site starts to become a real application, and past a certain point it pays to have a developer plan the structure properly. A post type that sits at the centre of your site, with several taxonomies, many custom fields, custom templates, and relationships between content types, is worth getting right the first time, because reworking it later once you have hundreds of entries is far more work.

We design and build custom post types, taxonomies, and fields as part of everyday WordPress work, and we register them in clean, portable code that does not depend on a plugin staying installed. We can build the admin experience so your team enters content without mistakes, create the templates that display it, and connect it to search, filtering, or an API if you need a headless front end. If your content model is the heart of the project, our WordPress development services cover it end to end. You can also read more about how we approach custom builds on our services page.

If you want your content types built the reliable way, you can get a free quote and we will map out the structure your project needs. Or book a free consultation and we will talk through your content and how best to model it, with no obligation. Getting the structure right early is one of the highest value decisions in a WordPress build, and the first conversation is free.

Hamza Hai

Hamza Hai writes about WordPress development, performance, and growth for businesses.

FAQ

Frequently asked questions

A custom post type is a content type you define yourself, separate from the built in posts and pages. It gets its own menu in the dashboard, its own editing screen, and its own place in the database, so you can manage a specific kind of content, like a portfolio or a list of events, on its own terms rather than mixing it in with blog posts. WordPress ships with a few content types already, and a custom post type simply adds a new one to that list.

No. You can create one with a plugin like Custom Post Type UI, which gives you a form and needs no code, or you can register it with a few lines of code using register_post_type() in a small plugin or your child theme's functions file. The plugin route is faster for non technical users, while the code route is more portable because it does not depend on a plugin staying installed. Both produce the same result.

Almost always because the permalink rules have not been refreshed. When you register a new post type in code, WordPress does not yet know how to route its URLs until you flush the rewrite rules. The fix is to go to Settings, then Permalinks, and click Save Changes without altering anything. That refreshes the routing and your custom post type URLs start working immediately. Plugins usually flush for you, which is why the 404 mostly appears with the code method.

WordPress uses template files named after your post type. Create archive-{type}.php for the listing page and single-{type}.php for individual items, placed in a child theme so updates do not erase them. WordPress picks these up automatically through its template hierarchy and uses them instead of the generic templates. On block themes and page builders you design these templates visually instead of writing PHP, but the idea is the same.

A custom post type is the content itself, like a portfolio project or an event. A taxonomy is a way of grouping that content, the way categories and tags group blog posts. You might create a Portfolio post type and then a Project Type taxonomy to file projects into Branding, Web, or Print. Post types hold the content, taxonomies organise it, and the two work together.

Your content stays safe in the database, but it stops displaying if the post type is no longer registered. So if you created the type with a plugin and deactivate that plugin, the items vanish from the admin until the type is registered again. The content is not deleted, it is just hidden because nothing is telling WordPress the type exists. This is why many developers register post types in code, so the definition does not depend on a plugin.

Set show_in_rest to true in the post type's arguments. The block editor is built on the REST API and will not load for a post type that is not exposed to it, so it falls back to the classic editor. Turning show_in_rest on fixes the editor and also makes the post type available to the REST API, which matters for headless setups and for content that uses blocks.

Usually yes, because most structured content needs extra data beyond a title and body: a client name, a date, a price band, a location. The popular way to add these is Advanced Custom Fields, which gives you clean, labelled boxes on the editing screen and helper functions to display the values in your templates. You can also register fields in code to keep them version controlled. Custom fields are what turn a post type into properly structured content.

Have a project?

Let's Build Your Next WordPress Website

Get a free consultation and a fixed-scope quote. No obligations.

  • Free Consultation
  • No Hidden Costs
  • 100% Confidential

Request your free quote

Tell us what you are building. A senior engineer replies within 24 hours.

Please enter your name.

Please enter a valid email address.

Please tell us a little more about your project (10+ characters).

No obligation. Your details are only used to prepare your quote.

Click to call us +1 (365) 440-1786