WordPress Plugin Project Structure
PHP-based WordPress plugin with admin settings, hooks, shortcodes, and optional Gutenberg blocks.
Project Directory
my-plugin/
my-plugin.php
Main plugin file
includes/
Core PHP classes
class-plugin.php
Main plugin class
class-loader.php
Hook loader
class-activator.php
Activation logic
class-deactivator.php
Deactivation cleanup
admin/
Admin-facing code
class-admin.php
Admin hooks and pages
partials/
Admin view templates
settings-page.php
css/
admin.css
js/
admin.js
public/
Public-facing code
class-public.php
Frontend hooks
partials/
shortcode-output.php
css/
public.css
js/
public.js
blocks/
Gutenberg blocks (optional)
my-block/
block.json
Block metadata
index.js
Block registration
edit.js
Editor component
save.js
Frontend render
style.css
languages/
Translation files
my-plugin.pot
uninstall.php
Cleanup on uninstall
readme.txt
WordPress.org readme
composer.json
PHP dependencies
package.json
For block assets
.gitignore
Why This Structure?
This structure separates admin and public code, uses a class-based architecture, and follows WordPress coding standards. The includes/ folder contains shared logic, while admin/ and public/ handle their respective contexts.
Key Directories
- my-plugin.php-Plugin header, bootstrap, and activation hooks
- includes/-Core classes and shared functionality
- admin/-Admin menus, settings pages, and assets
- blocks/-Gutenberg blocks with React components
Main Plugin File
run();
Getting Started
- Create plugin folder in
wp-content/plugins/ - Add main PHP file with plugin header comment
- Create
includes/class-plugin.phpwith hook registration - Activate plugin in WordPress admin
- Use
wp scaffold pluginfor quick scaffolding
WordPress Hooks
- Actions-
add_action('init', ...)to run code at specific points - Filters-
add_filter('the_content', ...)to modify data - Shortcodes-
add_shortcode('my_tag', ...)for content embeds - AJAX-
wp_ajax_*hooks for async requests
Best Practices
- Prefix all functions, classes, and hooks with unique slug
- Use
wp_enqueue_script/stylefor assets, never inline - Escape output with
esc_html(),esc_attr(), etc. - Use nonces for form security
- Make strings translatable with
__()and_e()
Common APIs
- Options API-
get_option(),update_option()for settings - Settings API-Built-in settings pages with validation
- REST API-
register_rest_route()for custom endpoints - Custom Post Types-
register_post_type()for custom content
When To Use This
- Adding features to WordPress sites
- Custom admin functionality
- Integrating third-party services
- Custom post types and taxonomies
- Gutenberg editor extensions
Trade-offs
- PHP required-Must know PHP for core functionality
- Global namespace-Risk of conflicts without proper prefixing
- Review process-WordPress.org has strict review guidelines