3 min read

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.

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.