Directory structure
Root
| Path | Contents |
|---|---|
backend/ | All PHP: the app namespace, migrations and route files |
frontend/ | The React + TypeScript app built by Vite |
tests/ | PHPUnit tests and their bootstrap |
bin/, scripts/ | Build and release scripts |
wp-kit | The CLI that scaffolds the plugin and generates classes |
.github/workflows/ | CI |
vendor/, node_modules/ | Installed dependencies. Never edited by hand |
Configuration sits at the root, one file per tool: composer.json and package.json, vite.config.ts and the tsconfig.*.json set, tailwind.config.mjs and postcss.config.mjs, eslint.config.mjs, stylelint.config.mjs, commitlint.config.mjs, playwright.config.ts, phpunit.xml.dist, phpcs.xml, phpstan.neon, phpinsights.php, rector.php, cspell.json, .wp-env.json for the Docker environment, and .env.example.
The plugin entry file is not in the repository — php wp-kit plugin:init generates it, with the plugin headers filled in from your answers. See Installation.
backend/
| Path | Contents |
|---|---|
backend/bootstrap.php | Boots the plugin: autoloading, config, providers |
backend/hooks/ajax.php | AJAX route definitions |
backend/hooks/api.php | REST route definitions |
backend/db/Migrations/ | Schema migrations, one class per table or alteration |
backend/app/ | The application namespace, PSR-4 mapped to YourPlugin\ |
backend/app/
| Path | Contents |
|---|---|
HTTP/Controllers/ | Controllers. One per resource, named <Resource>Controller |
HTTP/Requests/ | Form requests holding reusable rule sets |
HTTP/Middleware/ | Middleware classes with a handle() method |
Models/ | Models, one per table. See Models |
Rules/ | Custom validation rules |
Services/ | Business logic too large for a controller, called by controllers |
Providers/ | Bootstrappers that register hooks, rewrite rules and installers |
Helpers/ | Small stateless utilities |
Factories/ | Object construction that needs branching logic |
Views/ | PHP that renders admin page markup |
Config.php | Plugin constants: slug, prefixes, version |
Plugin.php | Container: boots providers, holds the middleware registry |
src/ | Domain code specific to this plugin, grouped by feature |
The starter ships HTTP/Middleware, Providers, Views, src, Config.php, Dotenv.php and Plugin.php. The rest appear as you generate them:
php wp-kit make:controller # creates HTTP/Controllers
php wp-kit make:model # creates Model
php wp-kit make:migration # creates db/Migrations and registers it
Where a request goes
Which folder owns each stage. For the boot order and how the routers are built, see Request lifecycle.
Conventions
- Every PHP file starts with the
ABSPATHguard, so the file is inert if hit directly. - Controllers, middleware and other leaf classes are
finalunless something extends them. - Third-party packages are namespace-prefixed at build time, so
bitapps/wp-kitis imported asYourPlugin\Deps\BitApps\WPKit\....