Overview
Visual Portfolio includes a custom post type called portfolio for organizing and displaying portfolio items. This post type provides a dedicated content structure for showcasing your work, projects, or products.
The Portfolio post type is registered in Visual_Portfolio_Custom_Post_Type class at classes/class-custom-post-type.php:15
Registration
The Portfolio post type is registered during WordPress initialization:
// Located in: classes/class-custom-post-type.php:39
public function __construct () {
// Custom post types
// Priority < 10 for compatibility with 'post-terms' block
add_action ( 'init' , array ( $this , 'add_custom_post_type' ), 9 );
// Custom post roles
add_action ( 'init' , array ( $this , 'add_role_caps' ) );
}
Enabling/Disabling
The Portfolio post type can be toggled in settings:
// Located in: classes/class-settings.php:267
array (
'name' => 'register_portfolio_post_type' ,
'label' => esc_html__ ( 'Register Portfolio Post Type' , 'visual-portfolio' ),
'desc' => esc_html__ ( 'Add custom post type `portfolio` to showcase your works.' , 'visual-portfolio' ),
'type' => 'toggle' ,
'default' => 'on' ,
)
Navigate to Settings
Go to Visual Portfolio > Settings in the WordPress admin
General Tab
Find the “Register Portfolio Post Type” option
Toggle Setting
Enable or disable as needed (requires permalink flush)
Post Type Features
Supported Features
The Portfolio post type supports:
Title and editor
Featured images
Excerpts
Custom fields
Taxonomies (categories and tags)
Gutenberg editor
Thumbnail preview in admin
Custom Taxonomies
Portfolio Categories:
'portfolio_category' => array (
'hierarchical' => true ,
'label' => __ ( 'Portfolio Categories' , 'visual-portfolio' ),
'rewrite' => array ( 'slug' => 'portfolio-category' ),
)
Portfolio Tags:
'portfolio_tag' => array (
'hierarchical' => false ,
'label' => __ ( 'Portfolio Tags' , 'visual-portfolio' ),
'rewrite' => array ( 'slug' => 'portfolio-tag' ),
)
Admin Interface
// Located in: classes/class-custom-post-type.php:98
public static function get_menu_slug () {
return self :: portfolio_post_type_is_registered ()
? 'edit.php?post_type=portfolio'
: 'visual-portfolio-settings' ;
}
Admin Columns
The admin list includes custom columns:
// Located in: classes/class-custom-post-type.php:49
add_filter ( 'manage_portfolio_posts_columns' , array ( $this , 'add_portfolio_img_column' ) );
add_filter ( 'manage_portfolio_posts_custom_column' , array ( $this , 'manage_portfolio_img_column' ), 10 , 2 );
Custom Columns:
Featured Image Thumbnail
Portfolio Categories
Portfolio Tags
Date
Filtering by Taxonomies
// Located in: classes/class-custom-post-type.php:40
add_action ( 'restrict_manage_posts' , array ( $this , 'filter_custom_post_by_taxonomies' ), 10 );
Adds dropdown filters for categories and tags in the admin list.
Visual Portfolio Lists
The plugin also registers a vp_lists post type for storing saved portfolio configurations:
'vp_lists' => array (
'public' => false ,
'show_ui' => true ,
'show_in_menu' => true ,
'supports' => array ( 'title' , 'editor' , 'revisions' ),
)
Saved Layouts
The vp_lists post type stores portfolio block configurations, allowing you to create reusable portfolio layouts.
Admin Features:
Shortcode column showing usage code
Block ID for referencing
Filter by layout type
Template selector
// Located in: classes/class-custom-post-type.php:56
add_filter ( 'manage_vp_lists_posts_columns' , array ( $this , 'add_vp_lists_custom_columns' ) );
add_action ( 'manage_vp_lists_posts_custom_column' , array ( $this , 'manage_vp_lists_custom_columns' ), 10 , 2 );
Capabilities
Custom capabilities for the Portfolio post type:
// Located in: classes/class-custom-post-type.php:43
public function add_role_caps () {
$capabilities = array (
'edit_portfolio' ,
'read_portfolio' ,
'delete_portfolio' ,
'edit_portfolios' ,
'edit_others_portfolios' ,
'publish_portfolios' ,
'read_private_portfolios' ,
'delete_portfolios' ,
'delete_private_portfolios' ,
'delete_published_portfolios' ,
'delete_others_portfolios' ,
'edit_private_portfolios' ,
'edit_published_portfolios' ,
);
// Assign to Administrator and Editor roles
}
Archive Page Setup
Configure a custom archive page for portfolio items:
// Located in: classes/class-settings.php:274
array (
'name' => 'portfolio_archive_page' ,
'label' => esc_html__ ( 'Archive Page' , 'visual-portfolio' ),
'desc' => esc_html__ ( 'Base page of your portfolio, where will be placed your works archive.' , 'visual-portfolio' ),
'type' => 'select' ,
'options' => self :: get_pages_list (),
'sanitize_callback' => array ( 'Visual_Portfolio_Archive_Mapping' , 'save_archive_page_option' ),
)
Archive Mapping
The Archive Mapping feature automatically creates portfolio layouts for archive pages:
// Located in: classes/class-archive-mapping.php
class Visual_Portfolio_Archive_Mapping {
/**
* Check if archive mapping is active
*/
$is_archive_query =
'post-based' === $options [ 'content_source' ] &&
'current_query' === $options [ 'posts_source' ];
}
Changing the archive page or toggling the Portfolio post type requires flushing permalinks. This is handled automatically via the defer_flush_rewrite_rules() method.
Gutenberg Integration
Forced Gutenberg Editor
Portfolio post type always uses Gutenberg:
// Located in: classes/class-custom-post-type.php:64
add_action ( 'classic_editor_enabled_editors_for_post_type' ,
array ( $this , 'vp_lists_classic_plugin_force_gutenberg' ), 150 , 2 );
add_action ( 'use_block_editor_for_post_type' ,
array ( $this , 'vp_lists_classic_plugin_force_gutenberg_2' ), 150 , 2 );
This ensures compatibility even when Classic Editor plugin is active.
Allowed Blocks
The vp_lists post type restricts available blocks:
// Located in: classes/class-custom-post-type.php:62
add_filter ( 'allowed_block_types_all' ,
array ( $this , 'vp_lists_allowed_block_types_all' ), 10 , 2 );
Custom Meta Fields
Portfolio settings are stored as post meta:
// Located in: classes/class-custom-post-meta.php
class Visual_Portfolio_Custom_Post_Meta {
/**
* Meta key for portfolio settings
*/
const META_KEY = 'vp_settings' ;
/**
* Get portfolio settings
*/
$settings = get_post_meta ( $post_id , self :: META_KEY , true );
}
Template Hierarchy
WordPress template files for Portfolio post type:
single-portfolio.php → Single portfolio item
archive-portfolio.php → Portfolio archive
taxonomy-portfolio_category.php → Category archive
taxonomy-portfolio_tag.php → Tag archive
Theme developers can override these templates in their theme directory.
REST API Support
Portfolio post type is exposed via REST API:
'show_in_rest' => true ,
'rest_base' => 'portfolio' ,
Endpoints:
GET /wp-json/wp/v2/portfolio - List portfolio items
GET /wp-json/wp/v2/portfolio/{id} - Get single item
POST /wp-json/wp/v2/portfolio - Create new item
PUT /wp-json/wp/v2/portfolio/{id} - Update item
DELETE /wp-json/wp/v2/portfolio/{id} - Delete item
Sitemap Integration
Portfolio items are included in XML sitemaps:
// Located in: classes/class-sitemap.php
class Visual_Portfolio_Sitemap {
public function __construct () {
add_filter ( 'wp_sitemaps_post_types' , array ( $this , 'add_to_sitemap' ) );
}
}
SEO Optimization
Built-in SEO support for portfolio items:
// Located in: classes/class-seo-optimization.php
class Visual_Portfolio_SEO_Optimization {
/**
* Add schema markup for portfolio items
*/
public function add_schema_markup ( $post ) {
// Adds structured data for better SEO
}
}
Quick access to portfolio items from the admin bar:
// Located in: classes/class-custom-post-type.php:77
add_action ( 'wp_before_admin_bar_render' ,
array ( $this , 'wp_before_admin_bar_render' ) );
Shows dropdown with portfolios available on the current page.
Migration Support
When updating from older versions:
// Located in: classes/class-migration.php
class Visual_Portfolio_Migration {
/**
* Run migrations for Portfolio post type changes
*/
public function maybe_migrate () {
// Handles data structure updates
}
}
Related Classes
Visual_Portfolio_Custom_Post_Type - Post type registration (classes/class-custom-post-type.php)
Visual_Portfolio_Custom_Post_Meta - Meta fields handling (classes/class-custom-post-meta.php)
Visual_Portfolio_Archive_Mapping - Archive page integration (classes/class-archive-mapping.php)
Visual_Portfolio_Sitemap - Sitemap integration (classes/class-sitemap.php)
See Also
Content Sources Using Portfolio items as a content source
Archive Mapping Configure portfolio archives
Custom Post Meta Working with portfolio meta data
REST API Access portfolio items via API