How do you create custom post types in WordPress without a plugin?
You can set up custom post types in WordPress without plugins by writing PHP code directly into your theme’s functions.php file or a site-specific plugin using the register_post_type() and register_taxonomy() functions, which keeps your website faster and reduces reliance on third-party software.

By default, WordPress gives you two main types of content: Posts and Pages. Posts are for timely blog entries, while Pages are for static information like an “About Us” or “Contact” page. But what if you are building a website for a real estate agency in Dhaka, an online recipe blog, or a student portfolio? You need a way to organize different kinds of information cleanly.
A Custom Post Type (CPT) is a brand-new type of content separate from standard posts and pages. Taxonomies are systems to group that content, much like categories and tags do for standard posts. Doing this through code rather than a plugin saves server memory, improves loading speeds, and gives you complete control over your site’s structure.
Why should you avoid plugins for custom post types?
Avoiding plugins for custom post types prevents “plugin bloat,” reduces security vulnerabilities, and ensures your site remains portable if you switch themes or hosting providers in the future.
Many beginners rely on plugins like Custom Post Type UI because they have graphical user interfaces. While helpful, every extra plugin adds a small amount of overhead to your server. If you deactivate that plugin later, your custom content can suddenly disappear from public view unless you migrate the code properly.
Writing your own code teaches you how WordPress actually works under the hood. It makes troubleshooting easier because you know every line of code running on your server. However, it does require careful attention to detail, as a single missing semicolon in PHP can cause a “White Screen of Death” error.
How do you write the code for a custom post type step-by-step?
To write the code for a custom post type, you hook a custom PHP function into the init action hook using WordPress native functions to define labels, visibility, and supported features.

Before editing any code, always take a complete backup of your website or test your changes on a local development environment like LocalWP. Never edit live code directly on a production server if you can avoid it.
- Access your theme files: Open your WordPress dashboard, go to Appearance > Theme File Editor, or use an FTP client / cPanel File Manager to access your active theme folder. Open the
functions.phpfile. - Add the registration function: Paste the PHP code snippet that registers your new post type. For example, if we want to create a “Book” post type for a bookstore website:
function anontow_register_book_post_type() {
$labels = array(
'name' => 'Books',
'singular_name' => 'Book',
'add_new' => 'Add New Book',
'add_new_item' => 'Add New Book',
'edit_item' => 'Edit Book',
'new_item' => 'New Book',
'view_item' => 'View Book',
'search_items' => 'Search Books',
'not_found' => 'No books found',
'not_found_in_trash' => 'No books found in trash',
'menu_name' => 'Books'
);
$args = array(
'labels' => $labels,
'public' => true,
'has_archive' => true,
'publicly_queryable' => true,
'show_ui' => true,
'show_in_menu' => true,
'query_var' => true,
'rewrite' => array( 'slug' => 'books' ),
'capability_type' => 'post',
'hierarchical' => false,
'supports' => array( 'title', 'editor', 'author', 'thumbnail', 'excerpt' ),
'show_in_rest' => true, // Enables the Gutenberg Block Editor
);
register_post_type( 'book', $args );
}
add_action( 'init', 'anontow_register_book_post_type' );
3. Save and flush permalinks: Save your functions.php file. Then, go back to your WordPress admin dashboard, navigate to Settings > Permalinks, and click “Save Changes” twice. This refreshes your URL rules so your new post type does not return a 404 error.
How do you add custom taxonomies without plugins?
You add custom taxonomies without plugins by using the register_taxonomy() function inside your functions.php file, linking your taxonomy to one or more specific post types.
Taxonomies can be hierarchical (like categories, meaning they can have parent and child terms) or non-hierarchical (like tags, meaning they are flat lists). For our “Book” post type, we might want a hierarchical taxonomy called “Genres” and a non-hierarchical taxonomy called “Authors”.
Here is how you add a custom taxonomy to your code:
function anontow_register_book_taxonomy() {
$labels = array(
'name' => 'Genres',
'singular_name' => 'Genre',
'search_items' => 'Search Genres',
'all_items' => 'All Genres',
'parent_item' => 'Parent Genre',
'parent_item_colon' => 'Parent Genre:',
'edit_item' => 'Edit Genre',
'update_item' => 'Update Genre',
'add_new_item' => 'Add New Genre',
'new_item_name' => 'New Genre Name',
'menu_name' => 'Genre',
);
$args = array(
'hierarchical' => true,
'labels' => $labels,
'show_ui' => true,
'show_admin_column' => true,
'query_var' => true,
'rewrite' => array( 'slug' => 'genre' ),
'show_in_rest' => true,
);
register_taxonomy( 'genre', array( 'book' ), $args );
}
add_action( 'init', 'anontow_register_book_taxonomy' );
Once you add this code below your post type function and flush your permalinks, you will see a new “Genres” menu item nested underneath your “Books” menu in the dashboard.
What can go wrong and how do you fix it?
Common issues when coding custom post types include 404 errors on single pages, syntax errors breaking the site, and missing editor support.

| Problem | Possible Cause | Solution |
|---|---|---|
| 404 Not Found Error | Permalinks have not been refreshed after registration. | Go to Settings > Permalinks and click Save Changes twice. |
| White Screen of Death | A typo or missing syntax (like a semicolon or bracket) in PHP. | Access files via FTP/cPanel, revert the last change, or check error logs. |
| Classic Editor showing instead of Gutenberg | 'show_in_rest' => true was omitted from the arguments array. |
Add 'show_in_rest' => true to your post type and taxonomy registration arrays. |
Another crucial practice: if you ever decide to change your theme, code placed directly inside a theme’s functions.php file will be lost if you switch to a non-child theme. For a permanent and professional setup, consider putting your custom post types into a simple, single-file site-specific custom plugin instead of your theme.
Frequently Asked Questions
Where should I put my custom post type code?
You can place your code inside your active theme's functions.php file, or preferably, inside a custom site-specific plugin so your content types do not disappear if you change themes later.
Why am I getting a 404 error when viewing my custom post type?
This almost always happens because WordPress permalinks need to be refreshed. Go to Settings > Permalinks in your dashboard and click 'Save Changes' to update the rewrite rules.
How do I make my custom post type work with the Gutenberg block editor?
You must include 'show_in_rest' => true inside the argument array when calling the register_post_type() and register_taxonomy() functions.






Leave a Reply
You must be logged in to post a comment.