Create A Professional Portfolio Using WordPress 3.0 Custom Post Types
WordPress 3.0 will be released in the near future and the first release candidate (RC1) is currently available to download and have a play around with. There are lots of great new features included in the latest update with one of the most interesting and useful being that of custom post types.
In this tutorial I’ll show you how to make use of the new custom post functionality to create a portfolio for your WordPress site.
What Are Custom Posts?
Custom posts are similar to blog posts in that you can add and edit them in the same way, but they differ in that they can be used to represent any sort of concept. So, for example, you might use a custom post to add a new project to a portfolio, a book to an online library, or a new member to subscription site.
When you create a new custom post type it will appear in your WordPress Admin menu and will enable you to create new “things” in much the same way you currently create posts and pages.

There are several advantages to this – for instance, it will make things much tidier and easier to manage as we’ll no longer have to use numerous custom fields to create sites that have portfolios, galleries, products, and any other type of custom post.
It will also be much better for those who are not experienced WordPress users – it will make it far easier for them to configure and maintain sites themselves as the interface will be much more intuitive.
For example, when adding a new product to an ecommerce site, all they will need to do is select the “Add New Product” link, provide some details about that product (e.g. a name, image, price and description) in the fields provided, and then save their updates.
Nice and easy!
Creating A Portfolio
Now we know what custom posts are, it’s time to get our hands dirty. We’ll be adding a website portfolio that makes use of the new custom post functionality to the Kanzoo WordPress theme. Whilst I’ll be using this theme to demonstrate what you need to do, you’ll be able to use the code provided in any of your own sites/themes.
We’re aiming for something simple that has just a few portfolio items – you can then use this as a template to create a bigger and better portfolio – this is what we’re looking to build:

Create The Custom Post Type
The first step in creating the portfolio is to actually create the new custom post type – you can do this by adding the following code to your functions.php file:
<?php add_action('init', 'create_portfolio'); function create_portfolio() { $portfolio_args = array( 'label' => __('Portfolio'), 'singular_label' => __('Portfolio'), 'public' => true, 'show_ui' => true, 'capability_type' => 'post', 'hierarchical' => false, 'rewrite' => true, 'supports' => array('title', 'editor', 'thumbnail') ); register_post_type('portfolio',$portfolio_args); } ?>
The first line of this code uses the “init” hook to ensure that the “create_portfolio” function is called when WordPress is initialized. This function is then defined on line 2 and essentially creates the new custom type via an array called $portfolio_args.
The “register_post_type” function is then passed the name of our custom post type (i.e. “portfolio”) and the “$portfolio_args” array that defines the custom type.
You can view the available arguments for “register_post_type” in the WordPress codex.
Input Fields For Our Portfolio
The next step is to create an input field that allows the user to enter some related details about the portfolio items. We’re going to keep things simple and will add a textfield where users can enter a website URL that points to a live demo of a project – add the following code to your functions.php file:
<?php add_action("admin_init", "add_portfolio"); add_action('save_post', 'update_website_url'); function add_portfolio(){ add_meta_box("portfolio_details", "Portfolio Options", "portfolio_options", "portfolio", "normal", "low"); } function portfolio_options(){ global $post; $custom = get_post_custom($post->ID); $website_url = $custom["website_url"][0]; ?> <div id="portfolio-options"> <label>Website URL:</label><input name="website_url" value="<?php echo $website_url; ?>" /> </div><!--end portfolio-options--> <?php } function update_website_url(){ global $post; update_post_meta($post->ID, "website_url", $_POST["website_url"]); } ?>
The first line of code here simply states that when the WordPress admin panel is initializing, call the “add_portfolio” function. This is defined on line 3 and basically adds a new section to the custom post called “Portfolio Options” and tells WordPress to use the “portfolio_options” function (line6) to display the appropriate elements in the new section.
The second line of code above is for recording user input whenever a custom post is updated – this is implemented by calling the “update_website_url” function which then ensures that any input is stored.
Your portfolio page should look something like the following (you can access this page by selecting the new “Portfolio” link in your WP Admin):

We now need to add some more appropriate columns to the the “Portfolio Overview” page – add the following code to the functions.php file:
<?php add_filter("manage_edit-portfolio_columns", "portfolio_edit_columns"); add_action("manage_posts_custom_column", "portfolio_columns_display"); function portfolio_edit_columns($portfolio_columns){ $portfolio_columns = array( "cb" => "<input type=\"checkbox\" />", "title" => "Project Title", "description" => "Description", ); return $portfolio_columns; } function portfolio_columns_display($portfolio_columns){ switch ($portfolio_columns) { case "description": the_excerpt(); break; } } ?>
This will enable users to easily see details of the projects that they have added to their portfolio:

Displaying The Portfolio
OK, so now that we have the backend sorted and the custom “portfolio” post type created, we want to display the portfolio items on the screen. Let’s create a new page template called “portfolio.php” – here’s the code for that file:
<?php /* Template Name: Portfolio */ ?> <?php get_header(); ?> <div id="content"> <?php $loop = new WP_Query(array('post_type' => 'portfolio', 'posts_per_page' => 10)); ?> <?php while ( $loop->have_posts() ) : $loop->the_post(); ?> <?php $custom = get_post_custom($post->ID); $screenshot_url = $custom["screenshot_url"][0]; $website_url = $custom["website_url"][0]; ?> <div id="portfolio-item"> <h1><?php the_title(); ?></h1> <a href="<?=$website_url?>"><?php the_post_thumbnail(); ?> </a> <?php the_content(); ?> </div> <?php endwhile; ?> </div><!-- #content --> <?php get_footer(); ?>
Let’s break that down a bit – lines 1-3 tell WordPress that this is a page template called “Portfolio”:
/*
Template Name: Portfolio
*/The important bit of code is the following:
$loop = new WP_Query(array('post_type' => 'portfolio', 'posts_per_page' => 10));
This tells WordPress to loop through the portfolio post type and display the individual portfolio items. The rest of the code is essentially defining what should be displayed on the screen for each individual portfolio item.
Now create a new page in your WordPress admin panel and assign the “Portfolio” template that we just created to it.

Now create some new portfolio items and add a thumbnail to each one:

If you now view your page in the browser, you should see the thumbnails being displayed for each individual project, along with the project title and description. However, it may look a little messy and require some styling – here’s the CSS code that I used for the Kanzoo theme – you many need to adapt this for your site to make the look and feel consistent:
<style> #content { width: 1200px; margin: 20px 0 0 -60px; } #portfolio-item { float: left; margin: 0 0 0 60px; width: 280px; } #portfolio-item h1 { font-size: 16px; margin: 20px 0 5px 0; } #portfolio-item img { border: 1px #ccc solid; margin: 0 0 10px 0; } </style>
This results in the Portfolio looking a little tidier:

All Done!
So, that’s it – the example provided in this tutorial can be adapted for all sorts of custom posts (books, people, products, films, phones, cars, etc.), so have a play around and see how it easy it is to enhance your themes.
I hope you found the tutorial useful – leave comment below if you have any questions/feedback.

















June 8th, 2010 at 4:33 am
thanx
will try that
June 8th, 2010 at 9:01 am
Nice approach! It made quite easy to understand the new features… I had no problems with the custom-types itself, but creating and updating the meta_boxes have always been a mess… Anyway, great article =)
June 8th, 2010 at 9:15 am
Cheers Abraão – glad it was useful.
June 8th, 2010 at 10:55 am
Very excited about this new feature but didn’t know where to start. Thanks for the great write-up!
June 8th, 2010 at 10:57 pm
Wow… Its what I need to make a portfolio for a client, I just need a little more fields. Thanks a lot for share.
June 10th, 2010 at 9:57 am
What if you wanted to create custom details pages for each portfolio item?
Is there a way to include a child custom post type?
June 10th, 2010 at 4:54 pm
Hi Matt – that’s a good question – I’ve not looked into the possibility of child custom post types yet, but they could potentially be useful in some scenarios. I suppose a quick fix for now would be to use custom fields in combination with the primary custom post type (in this case a portfolio item), but then you lose some of the advantages that custom posts provide. Might be a good tutorial for a future post.
June 15th, 2010 at 12:20 am
Actually wouldn’t it be as simple as keeping the same post structure and just include the permalink instead of the URL for each image?
June 15th, 2010 at 2:29 am
Yes, that would enable you to see the details of the portfolio item – maybe I misunderstood what you were asking.
I was thinking you meant something like having different page layouts for different types of portfolio items – so, for example, you might have worked on different projects (web design, online marketing, advertising) where you’d want a custom page layout for each.
If you’re simply looking to display further details about the portfolio item then what you suggest should work.
June 17th, 2010 at 10:36 am
Yeah sorry I wasn’t clear.
How would you modify that code in order to do that?
Basically I want to add all the data in one post… but just display a title and tumb on the list page and then for the single post page the title but additional details to that item… just like a portfolio.
I was thinking it be just as easy as creating custom posts and only displaying the title and thumb like you have…. the post details on the secondary page but not completely sure if this will work or not.
June 22nd, 2010 at 2:25 pm
Echoing Matt…what code modifications would I make to do the above?
June 23rd, 2010 at 5:01 pm
@Matt & @Noah – something like what Matt suggests should work. I’ll look into it as soon as I get a chance and post a solution.
June 11th, 2010 at 2:43 am
it doesn´t save the url
June 14th, 2010 at 5:34 pm
yep… looks like there’s a problem with the “website URL”.
but nice work. thanks for this!
June 15th, 2010 at 2:31 am
That’s strange – it should be working. Can you provide some more details – what’s the actual problem you’re having?
June 17th, 2010 at 11:51 am
I changed the href in line 19 and it seemed to work:
June 17th, 2010 at 11:52 am
argh.
Didn’t post the code.
Try again:
php echo $website_url
June 11th, 2010 at 12:05 pm
nice article.. if only I new where to begin coding my site into a wordpress theme..
June 18th, 2010 at 12:56 pm
I copied all the code into my functions.php file and once I saved that file and uploaded it every time I tried to publish something it went to a blank page. If I went back and refreshed it was still their in the admin panel but actually going to the portfolio page did not load either. I didn’t alter any of this code I simply did what was said to do in the tutorial. Did something change with the live version of wp 3?
June 20th, 2010 at 10:58 am
This is amazing..
June 23rd, 2010 at 11:25 am
Hi,
Thanks for the very clear tutorial. This has been a big help getting an idea of how to use Custom Post Types.
One question though:
I can’t seem to get the page templates to show up as an option on the Portfolio edit page. The Parent page option shows in the Attributes section but not the Portfolio template…or any of the other page templates.
Any help or ideas where to look would be great. thank you so much for the tutorial.
Chris
June 23rd, 2010 at 4:59 pm
Hi Chris – not sure if I completely follow, but the problem you’re having might be down to your “Portfolio edit page” being a post. If so, you wont see the page templates drop-down by default – you’ll only see this option on *pages* that you’ve created.
June 25th, 2010 at 10:52 am
Hi,
I too can’t see the page template selection. I’m sure it’s due to it being a post, rather than a page, but I followed your tutorial and it a post & not a page still. What have I missed?
Ash
June 23rd, 2010 at 7:58 pm
Hi Chris,
Thanks for a great tutorial. I’ve been looking and looking and this was exactly what I was hoping to find.
I am, however, having a problem saving data into the custom field (in this case, you are calling it Website URL).
I enter a value in my field and when I update the post, it doesn’t save. The data gets wiped out and the field goes back to empty.
I haven’t seen anyone else report this problem and was wondering if you have any ideas.
June 23rd, 2010 at 8:37 pm
My bad. I went back and pasted the code exactly as you wrote it and it does work (with the fix Derek Barnes added above to echo the value). User error is all mine in my edits.
Buuut, while I’m here, I’ll float a couple more questions your way.
1. How would one go about creating multiple fields in the Portfolio Options box?
2. How do I display the website URL in the overview with the columns? I have the header showing but have come up empty on actually displaying the data like you’ve done for description and title.
Thanks for your help and again, great tutorial!
June 23rd, 2010 at 9:07 pm
Geez, I guess I’m going to just take over your blog here. Sorry for the multiple posts, but I missed this earlier and it’s probably important.
Data that gets saved into a field (i.e. Website URL) only lasts about 3-4 minutes before it just disappears. It’s like the database is getting wiped clean of the field value.
June 28th, 2010 at 4:39 pm
Im having the same problem with values that disappear after a few minutes.
July 10th, 2010 at 7:43 am
i am facing the same problem … can u help me out y its happening ?? thanx
June 24th, 2010 at 3:08 pm
Hi, really good tutorial.
Is there any way to bulk move posts already published to the portfolio section you create?
Cheers
S
June 26th, 2010 at 1:01 am
I’m trying to add this to a theme i’m working on, and the portfolio item isn’t showing up in the admin section.
I’ve tried to create my own custom portfolio elements, and then just copy and pasted yours. They show up when I add the code to the twenty ten them, just not my own.
What am I missing??
June 26th, 2010 at 1:27 am
I left a sort of desperate comment before, turns out WordPress Reusables was fubaring the custom posts.
June 27th, 2010 at 5:20 pm
Can you just make a video of this? I know how to edit php slightly but when I go to function.php I don’t know where exactly to enter. Do I just throw it in the middle? Please advise
__(‘Portfolio’),
’singular_label’ => __(‘Portfolio’),
‘public’ => true,
’show_ui’ => true,
‘capability_type’ => ‘post’,
‘hierarchical’ => false,
‘rewrite’ => true,
’supports’ => array(‘title’, ‘editor’, ‘thumbnail’)
);
register_post_type(‘portfolio’,$portfolio_args);
}
?>
June 29th, 2010 at 1:18 am
This is exactly what i was looking for ever since i installed wordpress, and now with my current wordpress 3 upgrade and this tutorial, I will happen.
Thanks.
June 29th, 2010 at 1:54 pm
Doesn´t work whith arras-theme, someone can explain?
June 30th, 2010 at 1:41 am
Hey,
Thanks for writing this article. I found it extremely helpful, especially the code for adding the Web Site URL which was exactly what I was looking to do with my custom post type.
Thanks!
June 30th, 2010 at 10:31 am
Unfortunately it is not possible to print your page with Firefox, content is cut after the first page
Please correct that, I am printing essential articles / post as PDF and study them on the way to work in the train ;=)
July 1st, 2010 at 10:54 am
Thank you so much for sharing this. I have trouble creating custom post types and their respective meta fields until I was directed to your post by a friend. It’s such a life saver!
However, regarding the display of the URL of each site on the portfolio, I failed to fetch the URL using
<?=$website_url?>. I’ve substituted that withinstead
July 3rd, 2010 at 8:23 am
Following this tutorial, I’ve successfully added the gallery page to my website.
I’ve faced a problem where the “next”1,2,3 … “previous” page failed to show on the gallery.
The code as below, the posts_per_page is set to 9 but I’ve 11 posts created:
$loop = new WP_Query(array(‘post_type’ => ‘portfolio’, ‘posts_per_page’ => 9));
I’ve tried to insert the code from theme I purchased but failed, the code as below:
Any idea where I did wrong?
July 5th, 2010 at 9:29 am
Hi and thanks for this tutorial.
I have added another column for the year and the label, how would I display it when viewing all the portfolios in the admin section? I’m stuck here as I added the coloumn, but just don’t know what I need to put there for the year to display in the table, your assistance would be appreciated.
July 5th, 2010 at 12:05 pm
For the most part things seem to be working. The problem I’m having is when creating a post the column to create a thumbnail doesn’t appear and when I look at my portfolio page all I get is this error message:
Fatal error: Call to undefined function the_post_thumbnail() in \portfolio.php on line 20
that’s the line that reads:
<a href="ID, ‘website_url’, true) ?>”>
Am I missing something?
August 20th, 2010 at 6:34 am
I’m having this same problem… did you figure it out?
September 2nd, 2010 at 1:23 pm
http://codex.wordpress.org/Function_Reference/the_post_thumbnail
You need to make sure your theme supports the thumbnails.
July 8th, 2010 at 3:20 pm
Featured image section is built in wordpress 3.0?
What if I want to show further post options in custom post like send Send Trackbacks, Discussion, All in one SEO?
In my situation, I am using this for product display. My products have sub categories like Main Category -> Sub Category. Do I need to install custom post type for every sub category?
July 9th, 2010 at 12:17 pm
every thing is fine, how to do the perfect way of paging for this portfolio, if you guys share that to, that will be really awesome
cheers
Yoosuf
August 4th, 2010 at 9:03 am
I got paging to work on my own project by using the Simple Custom Post Type Archives plugin: http://wordpress.org/extend/plugins/simple-custom-post-type-archives/
July 10th, 2010 at 8:17 am
Data that gets saved into a field (i.e. Website URL) only lasts about 3-4 minutes before it just disappears. It’s like the database is getting wiped clean of the field value.
Please help me out
thanx
July 14th, 2010 at 7:16 pm
Nice application. Thanks. Custom post types are going to change things quite a bit
July 15th, 2010 at 8:48 am
Hi,
Awesome tutorial by the way! I’ve got it all working but I would like to know how to add LightBox to the gallery so when the thumbnails are clicked the large image appears in the centre of the screen.
Many Thanks
Christine
July 23rd, 2010 at 9:26 am
No worries, worked out myself with the jQuery PrettyPhoto plugin.
July 18th, 2010 at 1:02 am
Hey, nice post!
Any idea how can you get the “Category” option in a custom post type?
Thanks!
July 20th, 2010 at 1:52 am
Really wonderful post, thank you Chris.
There is just one small issue I thought I should mention, in case anyone else has issues. I found that when adding custom meta boxes, the autosave feature tends to wipe any existing values.
Replacing your code:
function update_website_url(){
global $post;
update_post_meta($post->ID, “website_url”, $_POST["website_url"]);
}
with:
function update_website_url(){
global $post;
if (defined(‘DOING_AUTOSAVE’) && DOING_AUTOSAVE) {
return $post_id;
} else {
update_post_meta($post->ID, “website_url”, $_POST["website_url"]);
}
}
did the trick for me.
Still, this is a very readable and thorough article and I am very grateful for the introduction to this great feature!
John
July 20th, 2010 at 1:56 am
Sorry, $post_id should be $post->ID…
July 26th, 2010 at 4:13 pm
Thanks John Sparrow, I appreciate you sharing that code. The whole disappearing custom values thing was getting frustrating. Good work fella!
August 1st, 2010 at 9:47 am
Thanks so much Mr Sparrow. I don’t think I would have worked out that autosave was making my values disapear.
September 1st, 2010 at 4:41 am
Thanks! I was having the exact same problems as well.
July 22nd, 2010 at 1:18 am
Hi again,
I liked the tutorial and have edited it a bit and am stuck a bit. I want to show a drop down box by the post meta whereby the user must select which month the work was done. I created an array to hold the months and need to know how to get the dropdown working on the meta box.
It would also be nice if you could also show checkboxes and radio buttons. This will not only help me, but others also.
July 24th, 2010 at 7:35 pm
Great tutorial! I would like to know how to add categories to my portfolio items as well. I’d like to create filters of my different types of work that I’m displaying.
July 25th, 2010 at 12:19 pm
nice approach.
I’m experimenting with custom post types at the moment and this gives me lots of food for thought.
cheers,
Ed
July 29th, 2010 at 8:44 am
Nice tutorial! I have one question, I want my portfolio to show only the results with some summery and when you click on it, you’ll get the hole process and everything. Does someone knows how to do this?
July 29th, 2010 at 10:44 am
Unfortunately, John’s fix did not work for me (thanks for posting it though). I found a fix that worked for me and posted it here: http://alohathemes.com/news/custom-post-fields-entries-not-saving-solved/
Hope that helps!
Thanks again for the great Tut!
August 4th, 2010 at 7:07 am
Thank you for giving such a tutorial but i am getting error as
” Warning: Cannot modify header information – headers already sent by (output started at /home/ashief/public_html/myodmu/wp-content/themes/buddypress-widget-theme/functions.php:116) in /home/ashief/public_html/myodmu/wp-includes/pluggable.php on line 890 ”
after doing updation its updating but this warning is arising how i can remove this warning…..
August 4th, 2010 at 9:08 am
I released a portfolio theme that is similar to this one- but it solves the paging issues and has some different features (like post type icon, jquery hover). People are welcome to download it and check out the code: http://wptheming.com/2010/07/portfolio-theme/
August 11th, 2010 at 7:57 am
good article, thanks a lot!
August 23rd, 2010 at 4:19 am
Thanks for this. I Love WP and u can use it easy as a cms for normaly Websites! This feauture is something, i needed.
September 3rd, 2010 at 10:16 am
Big respect!