Swap the API address for GitHub's signed download address on upgrader_package_options, before any upgrader_pre_download filter runs. GPLVault Updater returns false there for every package at priority 999999999, which threw away the downloaded file and left WordPress fetching the API address without the token (404). private_download() stays as a fallback; both use signed_address(). For wpallstars/seoprostack#261
WP Plugin Starter
A clean start for a WordPress plugin: a settings screen, a Read Me tab, updates from GitHub and release scripts, ready for your features.
WP Plugin Starter is what wpallstars plugins are made from. It has no features of its own: it holds the parts every plugin needs, built and tested in real plugins, so a new plugin starts with them working and spends its time on what makes it different.
If this saves you time, headaches and costs, feel free to buy me a coffee, or whatever you like, to invest in making more things open-source.
Version: {WPSTARTER_VERSION}
What you get
- A settings screen (Settings → WP Plugin Starter) that features fill by declaring their settings: switches, numbers, text, lists, choices and Media Library pictures, saved instantly with no Save button, searchable, in tabs. With no features yet it shows one empty tab.
- A Read Me tab that shows this file, banner included, so users read the same guide inside WordPress as on GitHub.
- Features as classes: one file per feature, off by default, with settings, hooks, one-off imports from the plugins it replaces and clean uninstall.
- Replaced plugins: a feature that does another plugin's job imports its settings once, waits while that plugin is active, and the Plugins screen suggests deactivating and deleting it.
- Updates from GitHub: the shared wpallstars updater (
includes/github-updater/). Sites get each GitHub release as a normal WordPress update. Every wpallstars plugin carries a copy and only the newest copy on a site runs, so they are all checked together, once. - Two builds of each version: the GitHub release, and a WordPress.org build without the updater, as WordPress.org requires.
- Scripts and CI: lint (PHP 7.4, WordPress coding and security rules, PHPStan), a smoke test on a real WordPress, the release build, a preflight check of both zips, Plugin Check, a preview site, the banner build, and
scripts/sync-core.shto keep each plugin's shared parts the same as the starter's. - Shared rules for people and AI:
STANDARDS.md(structure, code rules, releases, styling, testing),DEVELOPMENT.md(set-up and checks) andRELEASING.md, the same in every plugin made from the starter.
Start a plugin
- On GitHub, choose Use this template to make your repository, and clone it.
- Give it its names:
scripts/rename-plugin.sh --slug my-plugin --name "My Plugin" --prefix MyPlugin. Add--css mpfor a short CSS prefix and--repo owner/repoif it is not under wpallstars. Review withgit diff, then commit. - Replace this README,
readme.txt,changelog.txtandAGENTS.mdwith your plugin's own, and its banner (.wordpress-org/banner.svg, thenscripts/build-banner.sh). - Add features: a class in
includes/features/listed inMyPlugin_Setup::FEATURES(see Developers below andSTANDARDS.md). - Keep the shared parts up to date: change them in the starter first, then run
scripts/sync-core.shin each plugin (--checklists what differs).
The easiest way to do all of this is with aidevops: open the repository with it and describe the plugin you want. It reads AGENTS.md and STANDARDS.md, builds the features, tests them on a real site and runs the release checks.
Where to find it
Go to Settings → WP Plugin Starter. The screen has two groups of tabs:
- Settings: General, empty until features add settings. Changes save instantly; there is no Save button. Search features (next to the plugin name) finds settings on every tab.
- About: this Read Me.
Report a problem, at the top right of the screen, opens the plugin’s GitHub issues in a new tab. Say what you did, what you expected and what happened, with the versions of WordPress, PHP and WP Plugin Starter. Leave out passwords, licence keys and personal data, since issues are public. Buy me a coffee, next to it, opens the maker’s Buy Me a Coffee page in a new tab.
Requirements
- WordPress 6.2 or later
- PHP 7.4 or later
Updates and releases
There are two builds of each version:
- GitHub release (
wp-plugin-starter-template-X.Y.Z.zipon the repository’s Releases page): everything, including the shared updater inincludes/github-updater/, so sites get each release as a normal update. - WordPress.org: the same files without the updater (listed in
.distignore-wporg) and without theGitHub Plugin URI,Primary BranchandRelease Assetheader lines, because plugins hosted there may not install or update code from elsewhere.
The updater waits while Git Updater is active, so the two never both update a plugin.
Releasing on GitHub:
- Merge the version change (
Version:andWPSTARTER_VERSIONinwp-plugin-starter-template.php,Stable tag:inreadme.txt) tomain. - Straight away, tag that commit
vX.Y.Zand publish a GitHub release withwp-plugin-starter-template-X.Y.Z.zipattached.scripts/build-release.sh --ref vX.Y.Zbuilds it (and the WordPress.org zip) from the tag with.distignoreapplied, everything inside awp-plugin-starter-template/folder;scripts/preflight-release.shandscripts/plugin-check.shcheck them first. Sites pick the latest release whose tag is a plain version number and the asset whose name starts withwp-plugin-starter-template, so never attach the WordPress.org zip. Full steps:RELEASING.md. - Sites offer the update when they next check (within 12 hours, or at once with Check again on the Updates screen).
Mark test builds as pre-releases on GitHub (or tag them with letters, such as v1.2.0-rc1): sites never offer those. Do not add an Update URI header: WordPress.org rejects it, and Plugin Check reports it as an updater.
Developers
A feature is a class in includes/features/class-wpstarter-{name}.php that extends WPStarter_Feature, listed in WPStarter_Setup::FEATURES. It declares its settings in settings(), adds its hooks in boot() (returning early unless self::enabled()), and can import another plugin’s settings once in migrate() with self::import_setting(). Anything only this plugin needs goes in WPStarter_Setup (includes/class-wpstarter-setup.php): features, settings tabs, header links, settings version and its own helpers. The other files in includes/ and admin/ are the starter’s core files: STANDARDS.md → Structure.
Filters:
wpstarter_features: register a feature class that extendsWPStarter_Feature.wpstarter_settings_schema: add or change settings. Each entry setstype(bool, int, text, url, lines, domains, select, multi, times or media, a picture from the Media Library stored as its attachment ID),default,label,descriptionand eithertaborparent; select and multi also takeoptions(an array or a callable), and multi takesopento keep saved values that are not currently registered. A child setting can takehidden(true): it is not shown or searched, for wiring that code sets.reload(true) makes the saved message ask to reload the page, for changes that show only after a page load.replaces(slug => name) shows which plugin a feature replaces. Settings render and save automatically.wpstarter_admin_tabs: add or reorder admin tabs. Each tab setslabel,group(settings, discover or about), arendercallback and an optionalcapability; tabs the current user lacks the capability for are hidden.wpstarter_admin_script_depsandwpstarter_admin_script_data: the settings screen script’s dependencies and the data it reads aswpstarterAdmin(both with the active tab).wpstarter_can_change_settings: return false to stop the current user changing WP Plugin Starter’s settings (on top ofmanage_options).wpstarter_replaced_plugin_extras: what a replaced plugin does on this site that WP Plugin Starter does not (plain names, plugin folder). The Plugins screen names them instead of saying the plugin can go.wpstarter_stored_active_pluginsandwpstarter_plugins_skipped: for code that skips plugins on some requests, the active plugin files as stored and whether some are skipped on this request, so features still count those plugins as active.wpallstars_github_plugins(GitHub builds, shared updater): change which plugins update from GitHub releases (plugin file =>repoas owner/repo,asset_only,version,name).wpallstars_github_token(GitHub builds, shared updater): GitHub token for a repository (token, owner/repo), for private repositories; defaults to theWPALLSTARS_GITHUB_TOKENconstant.wpallstars_github_updater_enabledandwpallstars_github_updater_early(GitHub builds, shared updater): whether it runs (false while Git Updater is active) and whether plugins also on WordPress.org take GitHub releases first.
Actions:
wpstarter_admin_enqueue: enqueue the plugin’s own admin styles and scripts on its settings screen (active tab), depending onwpstarter-admin. Its script can usewpstarterAdmin.api(post,speak,errorMessage).wpstarter_setting_saved: a setting was saved from the admin screen.wpstarter_setting_panel: print status at the top of a setting’s options panel (setting key, schema entry); wrap it in<div class="wps-panel-note">.wpstarter_settings_tab_after: print a section after a settings tab’s cards (tab slug).
Read a setting with WPStarter_Settings::get( 'key' ).
Uninstall
Deleting the plugin removes its settings, its cached data, who hid lines of the Plugins screen notice about replaced plugins, and the cached GitHub releases.
Changelog
1.0.0
- A fresh start, made from the parts every wpallstars plugin needs, taken from plugins in daily use: the settings screen with search, the Read Me tab, features as classes, replaced plugins, the shared GitHub updater, the release and check scripts, CI and the shared rules (
STANDARDS.md,DEVELOPMENT.md,RELEASING.md). Earlier versions of this starter are retired; start again from this one. - New:
scripts/rename-plugin.shgives a copy of the starter its own names, andscripts/sync-core.shkeeps a plugin's core files the same as the starter's (--checklists any that differ).
Built with AI
WP Plugin Starter is built and maintained with aidevops, the same developer's open-source AI harness for creating and managing anything online with AI, plugins like this one included. It is free on GitHub.
License
GPL-2.0-or-later.