How to build a custom post type for your portfolio or projects
A portfolio built with ordinary WordPress posts becomes difficult to manage once client work, side projects and technical write-ups start competing for the same categories. A custom post type gives each project its own editing workflow, archive and URL, while a purpose-built template controls how the evidence appears.
That separation is more than cosmetic. You can store project summaries, technologies, outcomes and dates consistently, then query selected work for a services page without copying paragraphs into hand-built pages. Many Australian engineers call a useful portfolio piece a “proper write-up”: the problem, their contribution and the result. A dedicated project library makes that depth repeatable.
The goal is not to make WordPress more complicated; it is to give repeatable content a proper home. Start by deciding which fields visitors genuinely need, which categories will help them browse, and which parts must remain editable by you. The implementation below keeps that model small, portable and maintainable.
Choose the right content model
Compare three approaches before writing code. Regular pages are simple but awkward to sort or filter. A custom post type adds a dedicated content structure and editorial controls. A page-builder layout can look polished quickly, yet it often embeds presentation into content, making the portfolio harder to reuse.
| Approach | Main strength | Main limitation | Best fit |
|---|---|---|---|
| Regular WordPress pages | Minimal setup | Limited sorting and metadata | A small, fixed portfolio |
| Custom post type | Consistent structure, queries and archives | Requires templates and maintenance | Repeatable client and freelance work |
| Static or page-builder layouts | Fast visual control | Difficult to update and reuse | A one-off visual showcase |
For most engineers, a custom post type named portfolio_project is the cleanest starting point. If you also publish long-form articles, retain posts for those and use the new type only for completed work. This keeps the blog and the project library distinct in navigation, search and analytics.
Decide whether one entry represents a client engagement, a freelance deliverable or a substantial personal build. A clearer rule prevents a project from being counted twice. For example, a Melbourne café website and an Adelaide ecommerce build can both remain projects, even when they use different technologies and business models.
Register the post type in WordPress
Put the registration in a small site plugin rather than the active theme’s functions.php. A plugin survives a theme change, which is useful when your developer in Brisbane and a design studio in Sydney maintain different parts of the site. Use a prefixed function name or namespace to avoid collisions with other plugins.
<?php
function yuuki_register_portfolio_project() {
register_post_type( 'portfolio_project', array(
'labels' => array(
'name' => __( 'Projects', 'yuuki' ),
'singular_name' => __( 'Project', 'yuuki' ),
),
'public' => true,
'show_in_rest' => true,
'has_archive' => true,
'rewrite' => array( 'slug' => 'projects' ),
'supports' => array( 'title', 'editor', 'excerpt', 'thumbnail' ),
'menu_icon' => 'dashicons-portfolio',
) );
}
add_action( 'init', 'yuuki_register_portfolio_project' );
After activation, visit Settings → Permalinks and save the page once so WordPress refreshes its rewrite rules. The new type then appears in the admin menu and opens in the block editor. The REST API powers that editor and provides a supported route for future integrations or headless WordPress experiments.
The slug is public-facing, so choose it before publishing many entries. A clean /projects/ archive and /projects/client-name/ permalink communicates how the work is organised. The internal post type name can remain technical because visitors never see it in the URL.
Add project fields and taxonomies
Use the block editor for the narrative and add structured fields for information that must stay consistent. Depending on your stack, Advanced Custom Fields or a lightweight custom-fields plugin can store client, role, duration, live URL and measurable outcome. Entering these details manually makes sorting unreliable and increases the chance of typing errors.
Create text fields for the client and your role, a number field for duration, and a URL field for the live build. Reserve the editor for the challenge, your decisions and the result. Keep company names out of taxonomies: a client field behaves like metadata, whereas a taxonomy behaves like an archive category.
Taxonomies provide another layer of organisation. A hierarchical project_discipline taxonomy might contain Web, Mobile and DevOps, while project_type distinguishes Client Work from Personal Build. These archive-friendly categories should not replace fields for dates, budgets or outcomes.
Keep the vocabulary narrow. In Australian freelance briefs, buyers often want to compare scope and reliability as well as technical ability. Use Australian English in visible labels, quote local work in AUD, and state clearly on invoices whether GST is included where applicable and include your ABN if you are GST-registered.
Create archive and detail templates
WordPress can fall back to generic templates, but a portfolio deserves deliberate layouts. Create archive-portfolio_project.php for the project grid and single-portfolio_project.php for an individual case study. Your theme can then supply a consistent header, footer and spacing without a page builder holding the content together.
On an archive, show a featured image, title, summary and discipline. On a detail page, lead with the problem, the outcome and your role before describing the build. Use a thumbnail size that matches the actual layout, and link each project to relevant services or related case studies. For a homepage selection, use WP_Query with post_type set to portfolio_project rather than duplicating featured work.
Readers may arrive from a search result, scan the result and leave without opening the contact details. Strong summaries, related-project links and obvious next steps can reduce your bounce rate, although the measure still needs to be interpreted alongside enquiry quality.
Protect editing and organise access
Public content does not need public editing. Give the post type its own capabilities, then assign them to suitable roles: editors can publish projects, contributors can prepare them, and other users can read them without changing the site. This separation reduces accidental changes when a virtual assistant updates copy.
Choose a staging workflow before adding many entries. WordPress revisions, scheduled publishing and duplicate previews provide a basic safety net, while a plugin can add clearer drafts and review states. Keep confidential client results out of public queries and REST API responses until approval.
Set availability in a timezone clients recognise. A call between a developer in Perth and a client in Brisbane crosses two hours, while Brisbane and Sydney do not always share the same daylight-saving offset. Label times with the zone and avoid promising a permanent offset that will be wrong in summer.
Improve discoverability and page speed
Treat each project as a search-friendly case study, not an image gallery. Write a unique title and meta description, use a sensible heading order, and make sure the featured image has descriptive alternative text. A dedicated post type can power an XML sitemap automatically, but it does not replace useful copy or relevant internal links.
Performance deserves the same attention as content. Optimise images, defer non-essential scripts and check the project template on a mid-range Android phone, since portfolio traffic often arrives on mobile. The practical checks in improve Core Web Vitals are particularly relevant to image-heavy portfolios.
Structured data can describe the project type, while readable URLs and internal links help search engines connect it to the rest of your site. Avoid publishing thin entries that exist only to fill the archive. Three substantial projects with measurable outcomes will usually serve a prospective client better than twenty screenshots with no context.
Publish a reliable first release
Before announcing the portfolio, test the full publishing path in staging: create a project, assign its fields and taxonomy, preview the archive, publish it, then update it. Check that drafts are absent from public queries, permalinks resolve correctly and the featured image appears at every required size.
Test as different roles, including an editor who should not manage site settings. Then check the page on mobile and with JavaScript disabled, and confirm that contact links still work. Add analytics events for project views and enquiry clicks only if they answer a business question; generic traffic counts rarely improve the portfolio itself.
The practical takeaway is to keep the content model small, the template consistent and the publishing checks repeatable. That makes each new case study faster to maintain without adding another layer of complexity, while keeping the evidence clear for visitors and search engines.