WordPress ships with exactly two content types out of the box: posts (blog entries, organized by category and date) and pages (standalone, hierarchical content like an About or Contact page). Most real sites need a third kind of content that fits neither mold — projects in a portfolio, team member profiles, testimonials, products. That's what a custom post type is for.
A custom post type behaves exactly like a regular post — it gets an editor screen, a URL, an admin listing — but under its own name, with its own admin menu, and without dragging along everything that comes bundled with regular posts (categories and tags, for one, which rarely make sense for a list of team members).
| Built for | Organized by | |
|---|---|---|
| Post | Blog-style, date-ordered content | Categories and tags |
| Page | Standalone, mostly-static content | Parent/child page hierarchy |
| Custom Post Type | Any other repeating content type a site needs | Whatever custom taxonomy you attach to it (next lesson) — or none at all |
A portfolio site needs "Projects" — each with its own title, description, images, and client name. Trying to force that into regular posts means either polluting the blog with non-blog content, or using a category as a stand-in for "this is a project," which breaks down fast: there's no dedicated admin screen, no way to add project-specific fields cleanly, and no clean separation from actual blog posts. A project custom post type solves all of that at once.
Same table, different post_type
Under the hood, a custom post type isn't a separate database table — it's stored in the exact same wp_posts table as regular posts and pages, just tagged with a different post_type value. That's why it inherits so much for free: an editor screen, revisions, featured images, custom fields — all of it already knows how to work with any post type, not just the built-in two.
The next lesson registers an actual custom post type — no PHP required, using the CPT UI plugin installed back in the setup lesson.