📦 Beyond Blog Posts: Portfolio, Products, Events
Default “post” not enough. Custom Post Types (CPT) create dedicated content structures. Separate admin menus, custom fields, different templates.
📝 Register CPT
// functions.php
function create_portfolio_cpt() {
register_post_type('portfolio',
array(
'labels' => array(
'name' => __('Portfolio'),
'singular_name' => __('Portfolio Item'),
'add_new' => __('Add New'),
'add_new_item' => __('Add New Portfolio Item'),
'edit_item' => __('Edit Portfolio Item'),
'new_item' => __('New Portfolio Item'),
'view_item' => __('View Portfolio Item'),
'search_items' => __('Search Portfolio'),
'not_found' => __('No portfolio items found'),
'not_found_in_trash' => __('No portfolio items found in trash')
),
'public' => true,
'has_archive' => true,
'supports' => array('title', 'editor', 'thumbnail', 'excerpt'),
'menu_icon' => 'dashicons-portfolio',
'show_in_rest' => true, // Block editor support
'rewrite' => array('slug' => 'work')
)
);
}
add_action('init', 'create_portfolio_cpt');
🎯 Display CPT
// archive-portfolio.php
<?php
$portfolio = new WP_Query(array(
'post_type' => 'portfolio',
'posts_per_page' => 9
));
if ($portfolio->have_posts()) :
while ($portfolio->have_posts()) : $portfolio->the_post(); ?>
<div class="portfolio-item">
<?php the_post_thumbnail('medium'); ?>
<h3><?php the_title(); ?></h3>
<?php the_excerpt(); ?>
<a href="<?php the_permalink(); ?>">View Project</a>
</div>
<?php endwhile;
wp_reset_postdata();
endif;
?>
💡 Use Cases
- Portfolio (work samples)
- Products (e-commerce)
- Events (calendar)
- Testimonials (client reviews)
- Team members (staff profiles)
“Portfolio and blog posts mixed together. Created CPT for portfolio. Separate admin menu, custom fields, different URL structure. Much cleaner.”
