@sabbir1991/wpscaffold
v1.0.0
Published
Create a production-ready WordPress plugin scaffold instantly
Maintainers
Readme
🧱 wpscaffold
Instantly scaffold a production-ready WordPress plugin from the command line.
✨ What is wpscaffold?
wpscaffold is a zero-config CLI that generates a fully wired WordPress plugin in seconds — complete with PHP class structure, Gutenberg block support, admin UI, GitHub Actions CI, PHPUnit tests, ESLint, Stylelint, PHPCS, and more. Stop copy-pasting boilerplate. Start building.
🚀 Quick Start
# Install globally
npm install -g @sabbir1991/wpscaffold
# Scaffold a plugin
wpscaffold create "My Awesome Plugin"That's it. Follow the prompts, and your plugin directory is ready.
📦 Installation
Global (recommended)
npm install -g @sabbir1991/wpscaffoldLocal development / testing
git clone https://github.com/sabbir1991/wpscaffold.git
cd wpscaffold
npm link
# Now available anywhere on your machine:
wpscaffold create "My Plugin"
# Unlink after publishing:
npm unlink -g @sabbir1991/wpscaffold
npm install -g @sabbir1991/wpscaffold🛠️ Usage
# Pass plugin name directly (recommended)
wpscaffold create "My Awesome Plugin"
# Or let the tool prompt you
wpscaffold createAfter running, you'll see an interactive prompt session:
╔══════════════════════════════╗
║ Create WordPress Scaffold ║
╚══════════════════════════════╝
Press Enter to accept default values in brackets.
Plugin Name [My Plugin]:
Slug / text-domain [my-plugin]:
Description [A WordPress plugin.]:
Author Name [Your Name]:
Author Email:
Author URI [https://yoursite.com]:
Plugin URI [https://yoursite.com/my-plugin]:
Namespace Vendor [Your]:
Namespace Package [MyPlugin]:
Plugin Type [admin / block / both]:🎛️ Prompts Reference
| Prompt | Default | Description |
|--------|---------|-------------|
| Plugin Name | CLI argument or My Plugin | Human-readable plugin name |
| Slug / text-domain | kebab-case from name | Used for directories, function prefixes, text-domain |
| Description | A WordPress plugin. | Short plugin description |
| Author Name | git config user.name | Auto-detected from Git |
| Author Email | git config user.email | Auto-detected from Git |
| Author URI | https://yoursite.com | Your personal/company URL |
| Plugin URI | {authorUri}/{slug} | Plugin homepage URL |
| Namespace Vendor | First word of author (PascalCase) | PHP namespace vendor segment |
| Namespace Package | PascalCase of slug | PHP namespace package segment |
| Constant Prefix | UPPER_SNAKE from slug | PHP constant prefix (e.g. MY_PLUGIN) |
| Plugin Type | both | Controls what files are scaffolded |
🧩 Plugin Types
Choose the type that matches what you're building:
| Type | 🏗️ Includes | 🗑️ Omits |
|------|------------|---------|
| admin | Admin menu, admin JS/CSS assets | Gutenberg block source |
| block | Gutenberg block(s), block editor packages | Admin menu, admin JS/CSS |
| both | Everything — admin UI + blocks | Nothing |
Tip: Not sure? Pick
both. You can always delete what you don't need.
📁 Generated Structure
my-awesome-plugin/
│
├── 📄 my-awesome-plugin.php ← Plugin entry point
├── 📄 readme.txt ← WordPress.org readme
├── 📄 composer.json
├── 📄 phpcs.xml.dist
├── 📄 phpunit.xml.dist
├── 📄 eslint.config.js
├── 📄 lefthook.yml ← Git hooks (lint on commit)
│
├── 🔧 .editorconfig
├── 🔧 .gitignore
├── 🔧 .nvmrc
├── 🔧 .stylelintignore
│
├── 📂 .github/
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug_report.yml
│ │ ├── config.yml
│ │ └── feature_request.yml
│ ├── PULL_REQUEST_TEMPLATE.md
│ └── workflows/
│ ├── lint.yml ← ESLint + Stylelint CI
│ ├── phpcs.yml ← PHP CodeSniffer CI
│ └── phpunit.yml ← PHPUnit CI (PHP 8.1–8.4 matrix)
│
├── 📂 includes/ ← PHP classes (PSR-4 autoloaded)
│ ├── Admin/
│ │ └── Menu.php ← Admin menu registration
│ ├── Traits/
│ │ └── Singleton.php
│ ├── Assets.php ← Enqueue scripts/styles
│ ├── Blocks.php ← Block registration (block/both)
│ └── Plugin.php ← Core bootstrap
│
├── 📂 src/
│ ├── block/ ← Gutenberg block (block/both)
│ │ ├── block.json
│ │ ├── edit.js
│ │ ├── index.js
│ │ ├── render.php
│ │ ├── view.js
│ │ └── style.scss
│ └── global/ ← Admin assets (admin/both)
│ ├── js/admin.js
│ └── css/admin.scss
│
├── 📂 tests/
│ ├── bootstrap.php
│ └── Unit/
│ ├── AbstractTestCase.php
│ ├── AssetsTest.php
│ └── MenuTest.php
│
└── 📂 languages/⚙️ Generated Plugin Commands
Once inside your scaffolded plugin directory:
Setup
composer install # Install PHP dependencies (PHPCS, PHPUnit)
npm install # Install JS dependencies (@wordpress/scripts)Development
npm run build # Production build
npm run start # Watch mode (blocks)
npm run start:custom # Watch mode (admin assets)Linting & Formatting
npm run lint:js # ESLint
npm run lint:css # Stylelint
npm run lint:php # PHP CodeSniffer
npm run fix:js # Auto-fix JS
npm run fix:css # Auto-fix CSS
npm run fix:php # Auto-fix PHP
npm run format # wp-scripts formatTesting
npm run test:php # Run PHPUnit testsInternationalization
npm run makepot # Generate .pot translation fileRelease
npm run zip # Build + create installable .zip with production Composer autoload🏗️ PHP Architecture
Generated plugins follow PSR-4 autoloading with a clean namespace structure:
YourVendor\YourPlugin\ → includes/
YourVendor\YourPlugin\Admin\ → includes/Admin/
YourVendor\YourPlugin\Traits\ → includes/Traits/Service classes use the Singleton trait for consistent instantiation:
use YourVendor\YourPlugin\Traits\Singleton;
class Assets {
use Singleton;
}
// Bootstrap helper in the main plugin file.
my_plugin()->run();🔄 CI / CD Out of the Box
Your plugin ships with three GitHub Actions workflows:
| Workflow | Trigger | What it checks |
|----------|---------|---------------|
| lint.yml | Push / PR | ESLint + Stylelint |
| phpcs.yml | Push / PR | PHP CodeSniffer (WordPress coding standards) |
| phpunit.yml | Push / PR | PHPUnit on PHP 8.1, 8.2, 8.3, 8.4 matrix |
📋 Requirements
| Tool | Version | Purpose | |------|---------|---------| | Node.js | ≥ 20.0.0 | Run wpscaffold | | PHP | ≥ 8.1 | Plugin development | | Composer | ≥ 2.0 | PHP dependency management | | WordPress | ≥ 6.4 | Target environment |
🔑 How It Works
- Collects prompts — plugin name, slug, namespace, type, author info
- Builds replacements — maps placeholder strings (
plugin-skeleton,PluginSkeleton,sabbir1991) to your values - Copies template/ recursively — applies type markers and text replacements to every text file
- Removes unused code — strips block or admin sections based on chosen type
- Renames entry file —
plugin-skeleton.php→{your-slug}.php - Writes package.json — dynamically built with the correct scripts and dependencies for your plugin type
Type Markers
Template files use marker comments to gate type-specific code:
/* @skeleton-admin */
// This code only appears in admin and both types
/* @skeleton-admin-end */
/* @skeleton-block */
// This code only appears in block and both types
/* @skeleton-block-end */🤝 Contributing
- Fork the repo
- Create your branch:
git checkout -b feature/my-feature - Make changes in
lib/generator.jsortemplate/ - Test locally:
npm link && wpscaffold create "Test Plugin" - Submit a pull request
When adding new PHP classes to
template/includes/, mirror the pattern inbuildReplacements(). The placeholder namespace isPluginVendor\PluginSkeletonand the slug placeholder isplugin-skeleton.
