This repository is a standalone WordPress plugin template for building extensions to WikiPress. It is deliberately separate from the WikiPress core repository: copy or clone this project, give it your own identity, and add your integration here.
The template demonstrates the complete path from a WordPress plugin bootstrap to a registered WikiPress extension. It includes examples for settings, shortcodes, capabilities, admin pages and menus, the WikiPress in-page sidebar, assets, translations, activation, and database versioning. The examples are intentionally small so you can remove the providers you do not need.
pluginname.php WordPress bootstrap and WikiPress registration bridge
src/PluginName.php Plugin metadata and provider contract adapter
src/Includes/Includes.php Composition root for plugin-owned modules
src/Includes/Core/ Capabilities and other core plugin behavior
src/Includes/Functions/ Shortcodes and feature functions
src/Includes/Settings/ Settings defaults, fields, and sanitization
src/Includes/WP/ Activation, deactivation, database, and i18n lifecycle
src/Assets/ Asset registration and source JavaScript/Sass
src/Admin/ Plugin-owned admin hooks and page rendering
src/Languages/ Plugin-owned POT and MO catalogs
dev-stubs/ Development-only WordPress and WikiPress definitions
scripts/ Rename and translation catalog utilities
webpack.config.js Frontend asset build configuration
composer.json PHP package metadata and PSR-4 autoloading
package.json Node scripts and frontend development dependencies
The main plugin class is an adapter, not the place for every feature. It implements PluginInterface and whichever optional provider interfaces the integration needs. The implementation is delegated to the modules under src/.
- PHP 8.1 or later with Composer
- Node.js and npm
- A WordPress installation
- WikiPress installed and active when testing the integration
Clone the template, then work from its directory:
git clone https://github.com/TrilB-Dev/WikiPress-Demo-Plugin.git my-wikipress-plugin
Set-Location my-wikipress-pluginInstall the PHP and Node development dependencies:
composer install
npm installThe repository contains template names such as PluginName, PLUGINNAME, plugin-name, and plugin_name. Use the guided rename assistant before writing feature code:
npm run renameThe assistant asks for the display name, slug, PHP namespace, main class, shortcode and settings prefix, text domain, bootstrap filename, asset basename, author metadata, and Composer vendor. It previews content changes and filename changes, then requires the exact confirmation APPLY before modifying files.
Review the preview carefully. The assistant excludes .git, vendor, node_modules, compiled output, binary files, and the assistant itself. It does not rename the containing directory, so rename the cloned folder separately after the script finishes if required.
To inspect the plan without any confirmation prompt or file changes:
npm run rename -- --dry-runAfter applying a rename, regenerate the generated metadata and assets:
composer dump-autoload
npm run i18n:pot
npm run i18n:mo
npm run build- Copy the renamed plugin directory into
wp-content/plugins/, or create a junction/symlink for local development. - Activate WikiPress.
- Activate the renamed integration plugin.
- Open WikiPress settings and find the integration's settings tab.
- Try the example shortcode using the renamed shortcode prefix.
The bootstrap waits for WikiPress's wikipress_register_plugin action. If WikiPress is not active or the action is never fired, the external plugin remains unregistered instead of causing a fatal error.
WikiPress provides the extension contracts and shared services. The external plugin owns its feature logic, settings, capabilities, templates, assets, translations, REST routes, and admin callbacks.
The registration flow is:
- WordPress loads the plugin bootstrap.
- The bootstrap loads Composer and waits for
wikipress_register_plugin. - WikiPress passes its plugin manager to the registration callback.
- The external plugin registers an instance of its main class.
- WikiPress invokes optional providers for an active plugin.
- The main class delegates initialization to
src/Includes/Includes.php.
The main class should remain a thin contract adapter. Put behavior in focused modules and use the plugin's composition root to initialize them. Keep callbacks and page renderers in the external plugin; WikiPress registers generic menu, settings, asset, and lifecycle behavior around the data your provider returns.
The contracts are defined in WikiPress at src/Includes/Plugins/PluginsInterface.php. Implement only the interfaces the integration needs:
SettingsProviderInterfacefor settings registrationSettingsPageProviderInterfacefor a generated WikiPress settings tabShortcodeProviderInterfacefor shortcode definitionsDatabaseProviderInterfacefor plugin database tablesAssetsProviderInterfacefor scripts and stylesAdminPageProviderInterfacefor plugin-owned admin pagesAdminMenuProviderInterfacefor WikiPress submenus or a plugin menu treeAdminSidebarProviderInterfacefor the WikiPress in-page sidebarRestRouteProviderInterfacefor REST endpointsFrontendProviderInterfacefor frontend hooksI18nProviderInterfacefor the plugin text domain
Use the shared WikiPress helpers and services where they exist. Sanitize settings before persisting them, use a real permission callback for private REST routes, and keep capabilities and settings keys unique to the integration.
Composer provides two important pieces:
- The PSR-4 mapping loads the renamed plugin namespace from
src/. require-devinstalls WordPress and Elementor stub definitions for editor support and static analysis.
After changing the namespace, main class, or source layout, run:
composer dump-autoloadThe files in dev-stubs/ are local development definitions for WordPress, Elementor, and WikiPress contracts. Add them to your IDE or analysis configuration when needed. They are not production dependencies and must never be loaded by the plugin bootstrap.
The vendor/ directory is generated by Composer and is intentionally ignored by the rename assistant. The same applies to node_modules/ and compiled output. Regenerate these directories after changing the template identity rather than editing generated files by hand.
Start by removing demo providers and files that your integration does not use. Then grow the plugin through its existing ownership boundaries:
- Put settings defaults, field metadata, validation, and sanitization in
src/Includes/Settings/. - Put shortcodes and reusable feature hooks in
src/Includes/Functions/. - Put capabilities in
src/Includes/Core/Capabilities.phpand register them through the WikiPress capability extension point. - Put activation, deactivation, database versioning, and text-domain loading in
src/Includes/WP/. - Put source JavaScript and Sass in
src/Assets/js/andsrc/Assets/scss/; register page-specific output insrc/Assets/Assets.php. - Put admin pages, menu callbacks, and admin-only behavior in
src/Admin/or the owning feature module. - Keep translations in
src/Languages/and use the integration's own text domain. - Add REST routes only with deliberate validation, authorization, and response handling.
Use LoaderHelper for component hooks and compose WikiPress services instead of extending them. Core service classes are generally final by design.
Most new behavior belongs in this external plugin, not in WikiPress core. Before changing WikiPress, apply this test:
- Can the behavior be implemented entirely in the plugin? If yes, keep it here.
- Is the same generic need already shared by at least two plugins? If no, keep it here and do not add a core special case.
- If the need is genuinely shared, add a generic provider interface, service method, hook, or filter that does not know this plugin's slug, class, settings, labels, or business rules.
When a core extension is necessary, document the contract in WikiPress and let the external plugin provide the data or behavior. Do not add plugin-specific branches to shared settings managers, asset managers, admin renderers, API services, or helpers. This keeps WikiPress reusable and lets separately installed plugins evolve independently.
For the core-side documentation and contracts, see:
Docs/API.mdfor REST and response helpersDocs/HELPERS.mdfor shared helper conventionsDocs/SETTINGS.mdfor settings integrationDocs/WORDPRESS_PLUGINS.mdfor external registration and provider examplessrc/Includes/Plugins/PluginsInterface.phpfor the provider contracts
Run these commands from the plugin directory:
php -l pluginname.php
php -l src/PluginName.php
php -l src/Includes/Includes.php
php -l src/Includes/Functions/Shortcodes.php
php -l src/Includes/Settings/Settings.php
php -l src/Includes/WP/Activator.php
php -l src/Includes/WP/Deactivator.php
php -l src/Includes/WP/Database.php
php -l src/Includes/WP/I18n.php
php -l src/Assets/Assets.php
php -l src/Admin/Admin.php
git diff --checkWhen source assets change, run npm run build. When translatable strings change, run npm run i18n:pot and npm run i18n:mo. The asset module is intentionally inactive until compiled files exist under src/Assets/dist/.