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 plugin starts as a single PHP file inside its own folder in wp-content/plugins/, with a comment header that tells WordPress its name, version and requirements — that is all it takes to appear on the Plugins screen.
cd wp-content/plugins
mkdir gdc-books
touch gdc-books/gdc-books.phpName the main file after the folder. WordPress identifies a plugin by the path gdc-books/gdc-books.php, and that string is what it stores when the plugin is activated.
<?php
/**
* Plugin Name: GDC Books
* Plugin URI: https://gizdevcraft.in/learn/wordpress-plugins
* Description: Manage a catalogue of books with genres, details, a shortcode and a block.
* Version: 1.0.0
* Requires at least: 6.4
* Requires PHP: 7.4
* Author: Your Name
* Author URI: https://example.com
* License: GPL v2 or later
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
* Text Domain: gdc-books
* Domain Path: /languages
*/
// Stop direct access: this file must only ever be loaded by WordPress.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}Go to Plugins → Installed Plugins. GDC Books is listed, with your description and version. Activate it — nothing visible happens yet, and nothing breaks. That is a working plugin.
| Field | Required? | Purpose |
|---|---|---|
Plugin Name | Yes | The only field WordPress strictly needs. |
Version | Recommended | Used for upgrades and for cache-busting your assets. |
Requires at least / Requires PHP | Recommended | WordPress refuses to activate the plugin on older versions instead of letting it crash. |
Text Domain | For translation | Must match the folder name, gdc-books. |
License | For WordPress.org | GPL-compatible, because WordPress is GPL. |
Requires Plugins | Optional | Comma-separated slugs of plugins this one depends on (WordPress 6.5+). |
Every PHP file in your plugin can be requested directly by URL: https://site.com/wp-content/plugins/gdc-books/gdc-books.php. Run that way, WordPress is not loaded, and code that calls WordPress functions throws errors that can reveal file paths. ABSPATH is defined only when WordPress itself is running, so the check exits early. Put it at the top of every PHP file.
Add this below the guard. It appends a line to the end of every single post:
<?php
/**
* Adds a thank-you line after the content of single posts.
*
* @param string $content The post content.
* @return string The content with the note appended.
*/
function gdc_books_thank_you_note( $content ) {
if ( is_singular( 'post' ) && in_the_loop() && is_main_query() ) {
$content .= '<p class="gdc-books-note">' . esc_html__( 'Thanks for reading!', 'gdc-books' ) . '</p>';
}
return $content; // A filter must always return the value.
}
add_filter( 'the_content', 'gdc_books_thank_you_note' );Open any post: the note appears under it. Deactivate the plugin: it disappears, and the post content in the database was never touched. That is the plugin model in miniature.
Watch out: Never leave a closing ?> at the end of a plugin file. Any whitespace after it is sent to the browser before WordPress sends headers, causing "headers already sent" errors on redirects and logins.gdc-books/gdc-books.php with the full header and activate it.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.