WordPress has standard post types like posts and pages, but the code below creates a new custom post type called Portfolio. The code saves the data you entered in the meta boxes (e.g., client name, project URL) whenever you save a portfolio item. Displays the portfolio items on the website’s frontend using a shortcode.
// Register Custom Post Type "Portfolio" function create_portfolio_cpt() { $labels = array( 'name' => 'Portfolios', 'singular_name' => 'Portfolio', 'menu_name' => 'Portfolios', 'name_admin_bar' => 'Portfolio', 'add_new' => 'Add New', 'add_new_item' => 'Add New Portfolio', 'new_item' => 'New Portfolio', 'edit_item' => 'Edit Portfolio', 'view_item' => 'View Portfolio', 'all_items' => 'All Portfolios', 'search_items' => 'Search Portfolios', 'not_found' => 'No portfolios found.', ); $args = array( 'labels' => $labels, 'public' => true, 'show_in_menu' => true, 'supports' => array('title', 'editor', 'thumbnail', 'custom-fields'), 'has_archive' => true, ); register_post_type('portfolio', $args); } add_action('init', 'create_portfolio_cpt'); // Add Meta Boxes for Portfolio function portfolio_meta_boxes() { add_meta_box( 'portfolio_details', 'Portfolio Details', 'portfolio_meta_box_callback', 'portfolio' ); } add_action('add_meta_boxes', 'portfolio_meta_boxes'); // Meta Box Callback Function function portfolio_meta_box_callback($post) { $client_name = get_post_meta($post->ID, 'client_name', true); $project_url = get_post_meta($post->ID, 'project_url', true); $project_date = get_post_meta($post->ID, 'project_date', true); $project_description = get_post_meta($post->ID, 'project_description', true); ?> <p> <label for="client_name">Client Name:</label> <input type="text" name="client_name" id="client_name" value="<?php echo esc_attr($client_name); ?>" /> </p> <p> <label for="project_url">Project URL:</label> <input type="url" name="project_url" id="project_url" value="<?php echo esc_attr($project_url); ?>" /> </p> <p> <label for="project_date">Project Date:</label> <input type="date" name="project_date" id="project_date" value="<?php echo esc_attr($project_date); ?>" /> </p> <p> <label for="project_description">Short Description:</label><br> <textarea name="project_description" id="project_description" rows="4" style="width: 100%;"><?php echo esc_textarea($project_description); ?></textarea> </p> <?php } // Save Meta Box Data function save_portfolio_meta_box_data($post_id) { if (array_key_exists('client_name', $_POST)) { update_post_meta($post_id, 'client_name', sanitize_text_field($_POST['client_name'])); } if (array_key_exists('project_url', $_POST)) { update_post_meta($post_id, 'project_url', esc_url($_POST['project_url'])); } if (array_key_exists('project_date', $_POST)) { update_post_meta($post_id, 'project_date', sanitize_text_field($_POST['project_date'])); } if (array_key_exists('project_description', $_POST)) { update_post_meta($post_id, 'project_description', sanitize_textarea_field($_POST['project_description'])); } } add_action('save_post', 'save_portfolio_meta_box_data'); // Display Portfolio on Frontend function display_portfolio_items() { $args = array('post_type' => 'portfolio', 'posts_per_page' => 10); $loop = new WP_Query($args); while ($loop->have_posts()) : $loop->the_post(); ?> <h2><?php the_title(); ?></h2> <p><?php the_content(); ?></p> <p><strong>Client:</strong> <?php echo esc_html(get_post_meta(get_the_ID(), 'client_name', true)); ?></p> <p><strong>Project URL:</strong> <a href="<?php echo esc_url(get_post_meta(get_the_ID(), 'project_url', true)); ?>" target="_blank"><?php echo esc_url(get_post_meta(get_the_ID(), 'project_url', true)); ?></a></p> <p><strong>Project Date:</strong> <?php echo esc_html(get_post_meta(get_the_ID(), 'project_date', true)); ?></p> <p><strong>Description:</strong> <?php echo esc_html(get_post_meta(get_the_ID(), 'project_description', true)); ?></p> <?php endwhile; wp_reset_postdata(); } // Add shortcode for frontend display add_shortcode('display_portfolio', 'display_portfolio_items');