Code contributions, bug reports, and feature requests are welcome! The following sections provide guidelines for contributing to this project, as well as information about development processes and testing.
- Directory Structure
- Local setup
- Code Contributions (Pull Requests)
- Running Tests
- Internationalization
- Building the plugin for distribution
- Releasing
Click to expand
.
├── .github/
│ ├── workflows/
│ │ ├── ...
│ │ └── README.md # Documentation for GitHub workflows.
│ ├── .codecov.yml # Codecov configuration for test coverage reporting.
│ └── dependabot.yml # Dependabot configuration for automated dependency updates.
│
├── assets/ # Static assets that do not need compiling.
├── build/ # Compiled JS/CSS assets (generated by webpack.config.js).
│
│ # Project documentation.
├── docs/
│ ├── CODE_OF_CONDUCT.md
│ ├── CONTRIBUTING.md
│ ├── DEVELOPMENT.md # 👈 You are here.
│ └── SECURITY.md
│
│ # Reusable framework library (shared across plugins).
│ # In local projects, changes should be kept to a minimum so they can be kept in sync with the scaffold.
├── framework/
│ ├── ...
│ └── README.md # Documentation for the framework library.
│
│ # PHP source files (plugin-specific code).
├── inc/
│ ├── Core/
│ │ ├── Assets.php # Registers scripts, styles, blocks.
│ │ └── Templates.php # Template loader and helper functions.
│ │
│ ├── Modules/
│ │ ├── CLI/ # wp-cli command definitions.
│ │ ├── Example/ # Example module.
│ │ │ ├── Example_Post_Type.php
│ │ │ ├── Example_Taxonomy.php
│ │ │ ├── Example_Post_Type_Meta.php
│ │ │ └── Example_REST_Controller.php
│ │ └── Settings/ # Settings module.
│ │ ├── Settings.php
│ │ └── Admin_Screen.php
│ │
│ ├── Autoloader.php # PSR-4 autoloader.
│ └── Main.php # Main plugin entrypoint.
│
├── languages/ # Translation files (generated).
│
├── templates/ # Reusable PHP templates and partials.
│
│ # Scripts and styles that are compiled by webpack to `build/`.
│ # Each root directory is a separate entry point to a WordPress-registerable asset.
├── src/
│ ├── admin/ # Admin UI entrypoint.
│ ├── editor/ # Editor UI entrypoint.
│ ├── example-module/ # Example module entrypoint.
│ ├── frontend/ # Frontend UI entrypoint.
│ ├── global-styles/ # Global styles.
│ └── blocks/ # Gutenberg blocks.
│ ├── dynamic-block/ # Example dynamic block with server-side rendering.
│ ├── interactive-block/ # Example block using @wordpress/interactivity API.
│ └── static-block/ # Example static block.
│
│ # Tests
├── tests/
│ │ # Generated results and caches.
│ ├── _output/
│ │ ├── debug.log # WordPress debug log.
│ │ ├── js-coverage/ # Jest code coverage reports.
│ │ └── php-coverage.xml # PHPUnit code coverage report (XML).
│ │ # Playwright end-to-end tests.
│ ├── e2e/
│ │ # Jest unit tests.
│ ├── js/
│ │ ├── __mocks__/ # Mock implementations.
│ │ ├── setup.ts # Jest setup file.
│ │ └── tsconfig.json # Test TypeScript config.
│ │ # PHPUnit tests.
│ └── php/
│ ├── Framework/ # Framework tests.
│ ├── Unit/ # Unit tests.
│ ├── bootstrap.php # PHPUnit bootstrapper.
│ └── TestCase.php # Base test case class.
│
├── plugin-skeleton-d.php # Root plugin entrypoint.
├── uninstall.php # Plugin uninstall script.
│
├── readme.txt # WordPress plugin readme.
├── README.md # Main README.
├── CHANGELOG.md # Changelog.
│
│ # Config files.
├── .browserslistrc # Browserslist configuration.
├── .distignore # Files to exclude from installation via Composer.
├── .editorconfig # Editor configuration.
├── .gitignore # Git ignore rules.
├── .gitattributes # Git attributes.
├── .lefthook.yml # Git hooks configuration.
├── .lintstagedrc.mjs # Lint-staged configuration.
├── .nvmrc # Node.js version specification.
├── .phpcs.xml.dist # PHPCS configuration.
├── .prettierignore # Prettier ignore patterns.
├── .prettierrc.js # Prettier configuration.
├── .release-please-manifest.json # Release Please manifest file.
├── .stylelint.config.js # Stylelint configuration.
├── .stylelintignore # Stylelint ignore patterns.
├── .wp-env.json # wp-env configuration.
├── blueprint.json # WordPress Playground blueprint configuration.
├── babel.config.js # Babel configuration.
├── composer.json # PHP dependencies.
├── eslint.config.mjs # ESLint configuration.
├── jest.config.js # Jest configuration.
├── LICENSE.md # License file.
├── package.json # Node.js dependencies.
├── playwright.config.ts # Playwright configuration.
├── phpstan.neon.dist # PHPStan configuration.
├── phpunit.xml.dist # PHPUnit configuration.
├── release-please-config.json # Release Please configuration.
├── tsconfig.base.json # TypeScript base configuration.
├── tsconfig.json # TypeScript configuration.
└── webpack.config.js # Webpack configuration.- Node.js: v22.21.1+ (NVM recommended)
- npm: v10.9.4+
- Docker
- Optional: Composer (if you prefer to run the Composer tools locally instead of using wp-env's built-in Composer)
You can use Docker and the wp-env tool to set up a local development environment, instead of manually installing the specific testing versions of WordPress, PHP, and Composer. For more information, see the wp-env documentation.
-
Clone the repository:
git clone https://github.com/justlevine/plugin-skeleton-d.git
-
Change into the project folder and install the NPM dependencies.
# If you're using NVM, make sure to use the correct Node.js version: nvm install && nvm use # Then install the NPM dependencies: npm install
-
Start the local development environment:
npm run wp-env start
This will start a local WordPress environment with the plugin installed and the following default configuration:
- Site URL: http://localhost:8888
- WP Admin URL: http://localhost:8888/wp-admin/
- WP Admin Username:
admin - WP Admin Password:
password
- WP Admin Username:
-
Install the PHP dependencies using Composer, using either your local Composer installation or wp-env's built-in Composer:
# With wp-env: npm run wp-env:cli -- composer install # Or with local Composer: composer install
You should now have a fully functional local development environment with the plugin ready for development and testing.
npm install: Install JavaScript dependencies.composer install: Install PHP dependencies.- To use wp-env's built-in Composer, you can run
npm run wp-env:cli -- composer installto execute the command in the wp-env CLI container.
- To use wp-env's built-in Composer, you can run
npm run wp-env start: Start the local development environment.npm run wp-env stop: Stop the local development environment.npm run wp-env run cli -- --env-cwd=wp-content/plugins/plugin-skeleton-d {YOUR_CMD_HERE}: Run WP-CLI commands in the local environment.npm run wp-env:test run cli -- --env-cwd=wp-content/plugins/plugin-skeleton-d {YOUR_CMD_HERE}: Run Composer/PHP tooling in the tests container.npm run wp-env clean all: Resets the wp-env database.
For more information on using wp-env, see the wp-env documentation.
npm run format: Formats code using Prettier.npm run lint:css: Runs stylelint on the CSS code.npm run lint:css:fix: Autofixes stylelint issues.npm run lint:js: Runs ESLint on the JavaScript code.npm run lint:js:fix: Autofixes ESLint issues.npm run lint:js:types: Runs TypeScript'stscto check for type errors.npm run lint:php: Runs PHPCS linting on the PHP code.npm run lint:php:fix: Autofixes PHPCS linting issues.npm run lint:php:stan: Runs PHPStan static analysis on the PHP code.npm run prepare: Installs git hooks with Lefthook.
npm run start:js: Starts the JS/CSS watcher (development mode).npm run build:dev: Builds assets for development.npm run build:prod: Builds assets for production and installs optimized PHP dependencies.npm run clean: Cleans generated assets.
This repository uses a single long-lived branch: main. Always create a new branch from main when working on a feature or bug fix.
Branches should be prefixed with the type of change (e.g. feat, chore, tests, fix, etc.) followed by a short description of the change. For example, a branch for a new feature called "Add new feature" could be named feat/add-new-feature.
Pull requests are squash-merged into main. Use a Conventional Commits title (for example, feat: add settings page) so the squash commit on main can drive automated releases.
This project uses several tools to ensure code quality and standards are maintained:
This project uses ESLint through @wordpress/scripts and @wordpress/eslint-plugin for JavaScript linting, following WordPress coding standards and best practices.
Our specific ESLint configuration is defined in the eslint.config.mjs file.
You can run ESLint on JavaScript files using:
npm run lint:jsTo automatically fix JavaScript linting issues:
npm run lint:js:fixThis project uses PHP_CodeSniffer to enforce WordPress Coding Standards. We use rtCamp's coding-standards-d ruleset, which is tailored for modern WordPress development.
Our specific ruleset is defined in the .phpcs.xml.dist file.
You can run the PHP_CodeSniffer checks using the following command:
npm run lint:phpPHP_CodeSniffer can automatically fix some issues. To fix issues automatically, run:
npm run lint:php:fixThis project uses PHPStan to perform static analysis on the PHP code. PHPStan is a PHP Static Analysis Tool that focuses on finding errors in your code without actually running it.
Our specific configuration is defined in the phpstan.neon.dist file.
You can run PHPStan using the following command:
npm run lint:php:stanThis project uses wp-prettier, a WordPress-specific fork of Prettier for code formatting that is compatible with WordPress Coding Standards.
Our specific Prettier configuration is defined in the .prettierrc.js file.
You can run Prettier to format the code using:
npm run formatThis project uses Stylelint through @wordpress/scripts for CSS linting, following WordPress coding standards and best practices.
Our specific Stylelint configuration is defined in the .stylelint.config.js file.
You can run Stylelint on CSS files using:
npm run lint:cssTo automatically fix CSS linting issues:
npm run lint:css:fixThis project uses TypeScript for type checking in JavaScript files. The project-specific configuration is in tsconfig.json file, which extends the base configuration in tsconfig.base.json.
You can run the TypeScript compiler to check for type errors using:
npm run lint:js:typesThis project uses Lefthook to manage Git hooks. The configuration is defined in the .lefthook.yml file.
By default, lefthook calls lint-staged to run linters on staged files before each commit. The lint-staged configuration is defined in the .lintstagedrc.mjs file.
The project uses WordPress Playground to demo the release plugin, and on pull requests. The blueprint.json file enables easy testing and demos in the WordPress Playground.
The README.md and plugin preview use the ../blueprint.json file to load the latest release of the plugin for testing and demos.
Pull requests automatically generate a Playground preview from the build artifacts of the PR branch, using the PR preview workflow.
PHPUnit tests can be run using the following command:
npm run test:phpTo generate a code coverage report, make sure to start the testing environment with coverage mode enabled:
npm run wp-env:test start -- --xdebug-mode=coverage
npm run test:phpYou should see the html coverage report in the tests/_output/html directory and the clover XML report in tests/_output/php-coverage.xml.
We use Jest for JavaScript/TypeScript unit testing, configured via jest.config.js and extending @wordpress/scripts defaults.
Jest can be run with the following commands:
# Run all tests
npm run test:js
# Run tests in watch mode
npm run test:js:watch
# Run tests with coverage
npm run test:js:coverageTests can be placed in two locations:
- Co-located with source:
src/**/__tests__/*.test.ts(x)- Tests live next to the code they test - Centralized:
tests/js/**/*.test.ts(x)- Shared tests and utilities
The setup file (tests/js/setup.ts) provides mocks for common WordPress packages:
@wordpress/block-editor-useBlockProps,InspectorControls, etc.@wordpress/components-PanelBody,ToggleControl, etc.@wordpress/data-useSelect,useDispatch@wordpress/i18n-__,_x,sprintf@wordpress/element- React with WordPress extensions@wordpress/interactivity- Interactivity API mocks
End-to-end tests using Playwright can be run with the following command:
npm run test:e2eTo run Playwright tests with UI mode enabled (which opens the browser and shows the test execution), use:
npm run test:e2e -- --uiGitHub workflows are set up to run tests on pull requests and on the main branch. The workflow files are located in the .github/workflows/ directory, and each workflow has its own documentation in the relative README.md file.
You can test the workflows locally using act, which is also documented in the relative README.md file.
To generate the translation files, you can use the following commands:
npm run i18n:make-potTo build the plugin for distribution, you can use the following commands:
# Clean install of node modules.
nvm use && npm ci
# Only install production dependencies with Composer:
npm run wp-env:cli -- install --optimize-autoloader --no-dev
# Create a production-ready build:
npm run build:prod
# Generate translation files:
npm run i18n:make-pot
# Create the zip file for distribution:
npm run plugin-zipUnderneath the hood, the plugin uses @wordpress/scripts for the build process, which uses our webpack configuration to compile the assets and prepare the plugin for distribution.
Releases are automated with Release Please and Conventional Commits.
- Merge pull requests into
mainwith squash merge and a Conventional Commit title. - Release Please updates and maintains a release PR from
mainusing: - Merge the release PR when you're ready to ship.
- Release Please creates the GitHub Release, which then triggers the release workflow to build and upload the plugin zip asset.