Build WordPress plugins from scratch: actions and filters, shortcodes, settings pages, custom post types, meta boxes, AJAX, REST endpoints, custom tables, cron and blocks.
Lessons
A custom post type is a new kind of content — books, products, events — registered with register_post_type() so it gets its own admin menu, editor, URLs and archive just like posts and pages.
<?php
function gdc_books_register_post_type() {
$labels = array(
'name' => _x( 'Books', 'post type general name', 'gdc-books' ),
'singular_name' => _x( 'Book', 'post type singular name', 'gdc-books' ),
'add_new_item' => __( 'Add New Book', 'gdc-books' ),
'edit_item' => __( 'Edit Book', 'gdc-books' ),
'new_item' => __( 'New Book', 'gdc-books' ),
'view_item' => __( 'View Book', 'gdc-books' ),
'search_items' => __( 'Search Books', 'gdc-books' ),
'not_found' => __( 'No books found.', 'gdc-books' ),
'not_found_in_trash' => __( 'No books found in Trash.', 'gdc-books' ),
'all_items' => __( 'All Books', 'gdc-books' ),
'menu_name' => __( 'Books', 'gdc-books' ),
);
register_post_type(
'gdc_book',
array(
'labels' => $labels,
'public' => true,
'has_archive' => 'books', // Archive at /books/.
'rewrite' => array( 'slug' => 'book' ), // Single at /book/the-hobbit/.
'menu_icon' => 'dashicons-book',
'menu_position' => 20,
'supports' => array( 'title', 'editor', 'thumbnail', 'excerpt', 'custom-fields', 'revisions' ),
'show_in_rest' => true, // Required for the block editor.
'capability_type' => 'post',
)
);
}
add_action( 'init', 'gdc_books_register_post_type' );| Argument | Effect |
|---|---|
Post type key gdc_book | Up to 20 characters, lowercase, no spaces. Prefix it — book alone will clash with other plugins. |
public | Visible on the front end and in the admin. |
has_archive | Creates an archive page. A string sets its URL slug. |
rewrite | The URL slug for single items. |
supports | Which editor panels appear: title, editor, featured image, excerpt… |
show_in_rest | Exposes the type to the REST API. Without it, the block editor is not used — you get the classic editor. |
hierarchical | true for page-like parent/child items. |
menu_icon | A Dashicon name or an SVG data URI. |
After registering, visiting /books/ gives a 404 until WordPress rebuilds its URL rules. Do it on activation, as in lesson 7 — never on every init:
<?php
register_activation_hook( __FILE__, function () {
gdc_books_register_post_type();
flush_rewrite_rules();
} );Tip: While developing, you can flush manually by visiting Settings → Permalinks and clicking Save.
Custom post types do not appear in the main posts list by default. Add them with pre_get_posts:
<?php
function gdc_books_in_home_query( $query ) {
if ( ! is_admin() && $query->is_main_query() && $query->is_home() ) {
$query->set( 'post_type', array( 'post', 'gdc_book' ) );
}
}
add_action( 'pre_get_posts', 'gdc_books_in_home_query' );The plugin registers the type; the theme decides how it looks with single-gdc_book.php and archive-gdc_book.php. The WordPress Theme Development path covers those templates. A plugin can also ship default templates and let themes override them — the template_include filter makes that possible.
gdc_book with the labels above, activate the plugin and add three books./books/ and a single book. If you get a 404, flush permalinks.show_in_rest to false temporarily and notice the editor change to the classic editor.In accordance with Section 6 & Section 7 of the DPDP Act 2023, third-party analytics and marketing trackers are strictly gated behind your affirmative consent. You may withdraw consent at any time under Section 6(4).
Essential for session authentication (ci_session), Cross-Site Request Forgery security (csrf_cookie_name), and Cloudflare DDoS/bot prevention. Cannot be disabled.
Gated under DPDP Section 7. Allows Google Analytics 4 (Google Consent Mode v2) to measure aggregate, anonymized tool usage.
Enables browser local storage to preserve your theme selection (dark/light mode) and code editor layout between visits.
Used to display developer sponsorships and native tool partner notices.