Production-ready WordPress plugin boilerplate with OOP architecture, REST API endpoints, admin UI, and full test suite.
A battle-tested WordPress plugin boilerplate built for developers who want to skip the scaffolding and start building. Everything is wired up β activation hooks, admin menus, REST endpoints, WP-CLI commands, and a full PHPUnit test suite.
Stop copying and pasting from old projects. Clone this, rename, and ship.
- β OOP architecture with autoloading (PSR-4 via Composer)
- β Custom REST API endpoints with authentication
- β Admin settings page with tabbed UI
- β Custom post types and taxonomies scaffold
- β WP-CLI commands for common operations
- β PHPUnit test suite pre-configured
- β Webpack build pipeline for JS/CSS assets
- β Internationalization (i18n) ready
- β Multisite compatible
wp-plugin-boilerplate-pro/
βββ includes/
β βββ class-plugin.php # Main plugin class
β βββ class-activator.php # Activation/deactivation hooks
β βββ class-deactivator.php
β βββ admin/
β β βββ class-admin.php # Admin menu and pages
β β βββ class-settings.php # Settings API wrapper
β βββ api/
β β βββ class-rest-controller.php # Base REST controller
β β βββ endpoints/ # Individual endpoint classes
β βββ post-types/
β β βββ class-custom-post-type.php
β βββ cli/
β βββ class-cli-commands.php
βββ admin/
β βββ css/
β βββ js/
β βββ partials/ # Admin page templates
βββ public/
β βββ css/
β βββ js/
βββ languages/ # .pot file for translations
βββ tests/
β βββ bootstrap.php
β βββ test-sample.php
βββ composer.json
βββ package.json
βββ webpack.config.js
βββ plugin-name.php # Main plugin file
git clone https://github.com/TradeStackDev/wp-plugin-boilerplate-pro.git my-plugin
cd my-plugin
# Run the rename script (replaces all placeholder strings)
php rename.php --name="My Plugin" --slug="my-plugin" --prefix="mp"composer install
npm installnpm run build # Production build
npm run dev # Development with watchUpload to /wp-content/plugins/ or symlink for local dev, then activate in WP Admin.
The boilerplate includes a base REST controller you extend:
class My_Endpoint extends REST_Controller {
public function register_routes() {
register_rest_route( $this->namespace, '/items', [
[
'methods' => WP_REST_Server::READABLE,
'callback' => [ $this, 'get_items' ],
'permission_callback' => [ $this, 'get_items_permissions_check' ],
'args' => $this->get_collection_params(),
],
[
'methods' => WP_REST_Server::CREATABLE,
'callback' => [ $this, 'create_item' ],
'permission_callback' => [ $this, 'create_item_permissions_check' ],
],
] );
}
public function get_items( $request ) {
// Your logic here
return rest_ensure_response( $data );
}
}Settings are registered via the WordPress Settings API with a clean tabbed interface:
$settings = new Settings( [
'tabs' => [
'general' => [
'label' => __( 'General', 'my-plugin' ),
'fields' => [
'api_key' => [ 'type' => 'text', 'label' => 'API Key' ],
'enable_x' => [ 'type' => 'checkbox', 'label' => 'Enable Feature X' ],
'mode' => [ 'type' => 'select', 'label' => 'Mode', 'options' => ['live', 'test'] ],
],
],
'advanced' => [ ... ],
],
] );# List all plugin items
wp my-plugin items list
# Create a new item
wp my-plugin items create --title="My Item" --status=publish
# Run plugin diagnostics
wp my-plugin doctor
# Flush plugin cache
wp my-plugin cache flush# Install WordPress test suite
bash bin/install-wp-tests.sh wordpress_test root '' localhost latest
# Run tests
composer test
# Run with coverage
composer test-coverageThe boilerplate uses these strings throughout β the rename script replaces them all:
| Placeholder | Replace With |
|---|---|
Plugin_Name |
Your plugin class name |
plugin-name |
Your plugin slug |
plugin_name |
Your plugin prefix |
PLUGIN_NAME |
Your plugin constant prefix |
Your Name |
Your name |
yourplugin.com |
Your website |
GPL-2.0-or-later Β© Adam Johnson