---
tags:
  - wordpress
  - fse
  - php
  - cpt
  - custom-post-types
title: Registering Custom Post Types for FSE (The Right Way)
---

# Registering Custom Post Types for FSE (The Right Way)

While there are many plugins (like CPT UI) to generate Custom Post Types, creating them manually in `functions.php` gives you version-controllable code and cleaner setups.

For Full Site Editing (FSE), there are specific arguments you **must** include to ensure the Block Editor works and that you can create templates for this post type in the Site Editor.

## 1. The Basic Registration Code

Add this function to your theme's `functions.php` or a custom functionality plugin.

```php
function my_register_portfolio_cpt() {
    $labels = array(
        'name'                  => _x( 'Projects', 'Post Type General Name', 'my-textdomain' ),
        'singular_name'         => _x( 'Project', 'Post Type Singular Name', 'my-textdomain' ),
        'menu_name'             => __( 'Projects', 'my-textdomain' ),
        'all_items'             => __( 'All Projects', 'my-textdomain' ),
        'add_new_item'          => __( 'Add New Project', 'my-textdomain' ),
        'edit_item'             => __( 'Edit Project', 'my-textdomain' ),
        'view_item'             => __( 'View Project', 'my-textdomain' ),
    );

    $args = array(
        'label'                 => __( 'Project', 'my-textdomain' ),
        'labels'                => $labels,
        'supports'              => array( 'title', 'editor', 'thumbnail', 'excerpt', 'custom-fields' ),
        'taxonomies'            => array( 'category', 'post_tag' ), // Optional: Share WP categories
        'hierarchical'          => false, // False = Posts (Time based), True = Pages (Parent/Child)
        'public'                => true,
        'show_ui'               => true,
        'show_in_menu'          => true,
        'menu_position'         => 5,
        'menu_icon'             => 'dashicons-art', // https://developer.wordpress.org/resource/dashicons/
        'show_in_admin_bar'     => true,
        'show_in_nav_menus'     => true,
        'can_export'            => true,
        'has_archive'           => true, // Crucial for FSE Archive Templates
        'exclude_from_search'   => false,
        'publicly_queryable'    => true,
        'capability_type'       => 'post',
        'show_in_rest'          => true, // CRITICAL FOR FSE / GUTENBERG
    );

    register_post_type( 'portfolio', $args );
}
add_action( 'init', 'my_register_portfolio_cpt', 0 );
```

## 2. Key FSE Arguments Explained

### `show_in_rest => true`
**Mandatory.** This enables the REST API. Without this:
1.  The Block Editor (Gutenberg) will **not load**. You will be stuck with the Classic Editor.
2.  The FSE Site Editor cannot see the post type.

### `has_archive => true`
This enables the archive slug (e.g., `example.com/portfolio/`).
*   **FSE Impact:** If set to `true`, you can create an `archive-portfolio.html` template in the Site Editor to design the project grid.

### `supports`
Defines what panels appear in the editor.
*   `'editor'`: The content area (Block Editor).
*   `'thumbnail'`: The "Featured Image" panel. Required if you want to use the "Post Featured Image" block in your templates.
*   `'excerpt'`: The "Excerpt" panel. Required for the "Post Excerpt" block.

## 3. Creating Templates in FSE

Once registered, go to **Appearance > Editor > Templates**.
You will likely see options to create:
*   **Single Item: Project** (Renders `single-portfolio.html`)
*   **Archive: Projects** (Renders `archive-portfolio.html`)

If you don't see them, ensure `public`, `show_ui`, and `show_in_rest` are all true.

## 4. Flushing Rewrite Rules (The 404 Fix)

After adding a new CPT, visiting its URL often results in a 404 error because WordPress hasn't updated its permalink database.

**The Fix:**
1.  Go to **Settings > Permalinks**.
2.  Click **Save Changes** (you don't need to change anything).
3.  This flushes the rewrite rules and fixes the 404s.