Dirga Raj Lama
Web Developer
How to Create Custom Post Types Without a Plugin – 2026 Guide
WordPress is powerful out of the box, but sometimes you need more than posts and pages. Maybe you want to add Portfolios, Testimonials, Books, or Team Members as separate content types. The easiest method is using a plugin, but that adds extra weight and potential security risks. The better solution? Learn to create custom post types without a plugin using only a few lines of code in your theme’s functions.php file. In this guide, I’ll show you exactly how to do it safely and efficiently.
Why Avoid Plugins for Custom Post Types?
Plugins like Custom Post Type UI are convenient, but they come with downsides:
- Performance overhead—each active plugin adds PHP and database calls.
- Plugin dependencies—if the plugin stops being updated, your content structure could break.
- Learning opportunity—coding it yourself gives you full control and helps you understand WordPress better.
By learning to create custom post types without a plugin, you keep your site lean, fast, and future-proof.
What You Need Before Starting
- A WordPress site (any version 5.0+).
- Access to your theme files (via FTP or cPanel).
- A child theme (recommended) so updates don’t wipe your changes.
- Basic familiarity with PHP (but I’ll provide ready-to-use code).
Step-by-Step: Create Custom Post Types Without a Plugin
Step 1: Open Your Theme’s functions.php File
Navigate to Appearance → Theme File Editor (not recommended for production) or use an FTP client to edit /wp-content/themes/your-child-theme/functions.php. If you don’t have a child theme, create one (see our internal guide on setting up child themes first).
Step 2: Add the Basic Register Function
Paste this code at the bottom of functions.php (before the closing ?> tag if it exists):
function create_book_post_type() {
$args = array(
'public' => true,
'label' => 'Books',
'supports' => array( 'title', 'editor', 'thumbnail', 'excerpt' ),
);
register_post_type( 'book', $args );
}
add_action( 'init', 'create_book_post_type' );
Save the file. You’ve just created a Book custom post type. Visit your WordPress dashboard – you’ll see a new “Books” menu item.
Step 3: Customize the Arguments
The magic is in the $args array. Here’s a more advanced example for a Portfolio item:
function create_portfolio_post_type() {
$labels = array(
'name' => 'Portfolios',
'singular_name' => 'Portfolio',
'add_new' => 'Add New',
'add_new_item' => 'Add New Portfolio',
'edit_item' => 'Edit Portfolio',
'new_item' => 'New Portfolio',
'view_item' => 'View Portfolio',
'search_items' => 'Search Portfolios',
'not_found' => 'No portfolios found',
'not_found_in_trash' => 'No portfolios found in trash',
);
$args = array(
'labels' => $labels,
'public' => true,
'publicly_queryable' => true,
'show_ui' => true,
'show_in_menu' => true,
'query_var' => true,
'rewrite' => array( 'slug' => 'portfolio' ),
'capability_type' => 'post',
'has_archive' => true,
'hierarchical' => false,
'menu_position' => 20,
'menu_icon' => 'dashicons-portfolio',
'supports' => array( 'title', 'editor', 'thumbnail', 'excerpt', 'custom-fields' ),
);
register_post_type( 'portfolio', $args );
}
add_action( 'init', 'create_portfolio_post_type' );
This creates a fully functional post type with custom labels, slug, archive page, and dashboard icon.
Step 4: Flush Permalinks
After adding the code, go to Settings → Permalinks and click “Save Changes” once. This flushes the rewrite rules so your new post type URLs (e.g., yoursite.com/portfolio/my-item) work correctly.
Step 5: Add Custom Taxonomies (Optional)
Want categories or tags specifically for your custom post type? Use register_taxonomy():
function add_portfolio_taxonomies() {
register_taxonomy(
'portfolio_category',
'portfolio',
array(
'label' => 'Portfolio Categories',
'rewrite' => array( 'slug' => 'portfolio-category' ),
'hierarchical' => true,
)
);
}
add_action( 'init', 'add_portfolio_taxonomies' );
Now your portfolio items can have their own categories, just like posts.