Creator Portfolio Lite
A lightweight portfolio custom post type plugin for creators.
by Bill Piotrowski · github.com/billpiotrowski/creator-portfolio-lite
Install
No release zip yet. The repository archive installs, but the folder name will carry the branch suffix and updates will not flow:
wp plugin install https://github.com/billpiotrowski/creator-portfolio-lite/archive/refs/heads/main.zipA lightweight WordPress plugin that registers a custom post type for creative projects — films, albums, books, or whatever a creator makes. No upsells, no freemium, no bloat.
Requirements
| Tool | Version | Purpose |
|---|---|---|
| PHP | >= 8.0 | Runtime |
| Composer | Any current | Dependency management |
| Node.js + npm | Any current LTS | Running wp-env |
| Docker | Any current | wp-env spins up containers |
First-Time Setup
Clone the repo, then install PHP dependencies:
composer install
This generates vendor/ and the autoloader. The vendor/ directory is gitignored — it is never committed. composer.lock is committed and pins every dependency to an exact version, so composer install will always produce an identical result for everyone.
That's it. The plugin is now functional as source code.
How autoloading works
composer.json maps the CreatorPortfolioLite\ namespace to the src/ directory:
"autoload": {
"psr-4": {
"CreatorPortfolioLite\\": "src/"
}
}
Any class in src/ under the CreatorPortfolioLite\ namespace is available anywhere in the plugin without a require_once. The file path must mirror the namespace — CreatorPortfolioLite\PostType\Projects lives at src/PostType/Projects.php.
The entry point (creator-portfolio-lite.php) loads the autoloader with a single line:
require_once plugin_dir_path( __FILE__ ) . 'vendor/autoload.php';
Running Unit Tests
Unit tests use WP_Mock to mock WordPress functions. They run without WordPress or Docker.
# Run all tests
./vendor/bin/phpunit
# Run only the Unit suite
./vendor/bin/phpunit --testsuite Unit
# Run only the Integration suite (requires wp-env — see below)
./vendor/bin/phpunit --testsuite Integration
Or via the Composer script shorthand:
composer test
Test files live in tests/Unit/ and tests/Integration/. PHPUnit discovers any file ending in Test.php in those directories automatically.
Testing with wp-env
wp-env spins up a local WordPress instance inside Docker with this plugin automatically loaded. No separate site repo or manual plugin installation needed.
Install wp-env (once, globally)
npm install -g @wordpress/env
Start the environment
npx wp-env start
On first run this pulls Docker images and takes a few minutes. Subsequent starts are fast.
| URL | Details |
|---|---|
http://localhost:8888 |
WordPress front end |
http://localhost:8888/wp-admin |
Admin panel |
| Username | admin |
| Password | password |
The plugin will be listed under Plugins and can be activated from there.
Other useful wp-env commands
npx wp-env stop # Stop the containers
npx wp-env destroy # Wipe everything (database included) and start fresh
npx wp-env logs # Stream WordPress/PHP logs
npx wp-env run cli wp plugin list # Run WP-CLI commands inside the container
How wp-env knows about this plugin
.wp-env.json at the project root tells wp-env what to load:
{
"core": null,
"plugins": ["."]
}
"core": null means use the latest stable WordPress. "plugins": ["."] mounts the current directory as a plugin inside the container.
VS Code + Intelephense Setup
WordPress functions (add_action, register_post_type, plugin_dir_path, etc.) are not part of PHP itself, so your editor needs a hint about where they come from.
Two things handle this:
1. The stubs Composer package
php-stubs/wordpress-stubs is installed as a dev dependency. Intelephense automatically indexes vendor/ and picks up the WordPress function signatures from there. This also provides type information for static analysis tools like PHPStan or Psalm.
2. .vscode/settings.json
This activates Intelephense's built-in WordPress stub set. Important: the intelephense.stubs workspace setting replaces (not merges with) the user-level default. The standard PHP stubs (Core, standard, etc.) are included in this list for that reason — without them, common PHP built-ins would show as undefined.
If you ever see an "undefined function" warning on a standard PHP function, the relevant extension stub is likely missing from this list. The full list of available stubs is in the Intelephense documentation.
After cloning, you may need to run Intelephense: Index workspace from the VS Code command palette (Cmd+Shift+P) for changes to take effect.
Distributing the Plugin
vendor/ is gitignored, so the repo is not directly installable as a WordPress plugin by someone without Composer. For distribution, use the included zip script (TODO: add zip script) to bundle the plugin with its production dependencies:
# coming soon
./bin/build.sh
The zip excludes dev dependencies (phpunit, wp_mock, etc.), tests, and tooling config — only what WordPress needs to run the plugin.
For now, composer install --no-dev followed by a manual zip of the project directory (excluding .git, tests/, and dev config) produces a valid installable plugin zip.