Skip to content
wp-skills
Register
tools/custom-post-type-generator

Custom Post Type Generator

WordPress custom post type generator is a tool that allows you to more easily and effectively manage customized content on your WordPress site.

Used across the labels — “Add New Book”, “Edit Book”. Capitalised as it should read.

The menu entry and the list screen's heading.

Stored in wp_posts.post_type, a varchar(20). Lower case, no spaces, and prefixed if you can — “book” is a name another plugin may also want.

Not shown anywhere by core. Some themes and plugins read it.

Your theme or plugin's own domain, for the labels above.

Properties

Supports

Comma separated, and they must already be registered. This connects existing taxonomies; it does not create them.

A Dashicon. The list is what WordPress ships; a custom SVG needs a data URI instead.

How the archive and single URLs are built. Any change here needs the permalinks flushed once — visiting Settings → Permalinks is enough.

Replaces post_type= in a non-pretty URL. Rarely worth changing.

The path segment, so /books/my-title/. Defaults to the post type key when left blank.

Required for the block editor. Off puts this post type back on the classic editor, whatever else is installed.

The route segment under /wp-json/wp/v2/. Defaults to the post type key, which is singular — plural usually reads better here.

Only worth setting if you have subclassed it. The default handles everything a normal post type needs.

snippet.php
// Register custom post type
// Post type: My Custom Post
function create_my_custom_post_post_type() {
	$labels = array(
		'name'                  => _x( 'My Custom Posts', 'Post Type General Name', 'text-domain' ),
		'singular_name'         => _x( 'My Custom Post', 'Post Type Singular Name', 'text-domain' ),
		'menu_name'             => _x( 'My Custom Posts', 'Admin Menu text', 'text-domain' ),
		'name_admin_bar'        => _x( 'My Custom Post', 'Add New on Toolbar', 'text-domain' ),
		'archives'              => __( 'My Custom Post Archives', 'text-domain' ),
		'attributes'            => __( 'My Custom Post Attributes', 'text-domain' ),
		'parent_item_colon'     => __( 'Parent My Custom Post:', 'text-domain' ),
		'all_items'             => __( 'All My Custom Posts', 'text-domain' ),
		'add_new_item'          => __( 'Add New My Custom Post', 'text-domain' ),
		'add_new'               => __( 'Add New', 'text-domain' ),
		'new_item'              => __( 'New My Custom Post', 'text-domain' ),
		'edit_item'             => __( 'Edit My Custom Post', 'text-domain' ),
		'update_item'           => __( 'Update My Custom Post', 'text-domain' ),
		'view_item'             => __( 'View My Custom Post', 'text-domain' ),
		'view_items'            => __( 'View My Custom Posts', 'text-domain' ),
		'search_items'          => __( 'Search My Custom Post', 'text-domain' ),
		'not_found'             => __( 'Not found', 'text-domain' ),
		'not_found_in_trash'    => __( 'Not found in Trash', 'text-domain' ),
		'featured_image'        => __( 'Featured Image', 'text-domain' ),
		'set_featured_image'    => __( 'Set featured image', 'text-domain' ),
		'remove_featured_image' => __( 'Remove featured image', 'text-domain' ),
		'use_featured_image'    => __( 'Use as featured image', 'text-domain' ),
		'insert_into_item'      => __( 'Insert into My Custom Post', 'text-domain' ),
		'uploaded_to_this_item' => __( 'Uploaded to this My Custom Post', 'text-domain' ),
		'items_list'            => __( 'My Custom Posts list', 'text-domain' ),
		'items_list_navigation' => __( 'My Custom Posts list navigation', 'text-domain' ),
		'filter_items_list'     => __( 'Filter My Custom Posts list', 'text-domain' ),
	);

	$args = array(
		'label'                 => __( 'My Custom Post', 'text-domain' ),
		'description'           => __( 'Lorem ipsum dolor sit amet.', 'text-domain' ),
		'labels'                => $labels,
		'menu_icon'             => 'dashicons-admin-appearance',
		'supports'              => array( 'title', 'editor', 'thumbnail', 'revisions', 'author' ),
		'taxonomies'            => array(),
		'hierarchical'          => false,
		'exclude_from_search'   => false,
		'publicly_queryable'    => true,
		'has_archive'           => true,
		'public'                => true,
		'show_ui'               => true,
		'show_in_menu'          => true,
		'show_in_admin_bar'     => true,
		'can_export'            => true,
		'show_in_nav_menus'     => true,
		'menu_position'         => 5,
		'capability_type'       => 'post',
		'show_in_rest'          => true,
		'rewrite'               => true,
		'query_var'             => true,
	);

	register_post_type( 'custom-post', $args );
}
add_action( 'init', 'create_my_custom_post_post_type', 0 );

// Permalinks for a new post type only work once the rewrite rules are rebuilt.
// Visiting Settings > Permalinks is enough; flush_rewrite_rules() on every load
// is not, and is expensive.