Publishing on the WordPress.org plugin directory

Prepare the plugin and its readme for review, build a clean release, ship versions with SVN and support users once it is live.

  • Intermediate
  • 10 min read
  • Updated 17 Oct 2026

What you will learn

  • Prepare a plugin for review
  • Release with SVN
  • Write a valid readme.txt
  • Check a plugin with the Plugin Check tool before every release

Before you start

The WordPress.org plugin directory is how most WordPress users find plugins. Hosting there gives you a listing page, built-in updates, automatic translations, a support forum and usage statistics, all free. In return your plugin must follow the directory's guidelines and pass a review by the Plugin Review Team. This lesson covers what reviewers look for, the files the directory reads, the SVN release process and what happens after launch.

Is the directory the right home?

The directory hosts free, GPL-licensed plugins. Before preparing a submission, check the plugin fits the guidelines. The main points, paraphrased:

Guideline areaWhat it means for you
LicensingAll code, including bundled libraries, must be GPL-compatible
Complete and functionalNo trialware: features cannot be locked or expire behind a payment. Upselling a separate premium add-on is allowed
Human-readable codeNo obfuscated or minified-only code. Ship the sources of built JavaScript, or link to a public repository where they live
No tracking without consentCollecting usage data or contacting external servers needs explicit opt-in, and must be documented
No remote codeThe plugin may not download and run code from elsewhere, or install updates from servers other than WordPress.org
Services are allowedA plugin can be the interface to an external service, provided the service is documented in the readme, with terms and privacy links
Respect the adminNotices must be relevant and dismissible; no hijacking the dashboard with adverts
No unasked-for credits"Powered by" links or credits on the public site must be opt-in
Use what WordPress shipsLoad bundled libraries such as jQuery from core rather than including your own copies
TrademarksYour plugin's name and slug must not start with someone else's trademark

Read the full guidelines, linked in the resources, before you submit. They change from time to time, and the current text is what reviewers apply.

Lesson 23's updater does not belong in a directory plugin. Updates come from WordPress.org, and an Update URI pointing elsewhere is not allowed for hosted plugins.

Preparing the code

Reviewers read code. Most rejections are for the same handful of issues, all covered earlier in this course:

  • Security: every output escaped late, every input sanitised and unslashed, nonces and capability checks on every state change, $wpdb->prepare() for every query with variables. The security checklist lesson is the reference.
  • Prefixes: unique prefixes or namespaces on every function, class, constant, option, hook and global. Generic prefixes such as wp_, plugin_ or my_ collide with other code.
  • Direct access guards: defined( 'ABSPATH' ) || exit; at the top of PHP files.
  • Internationalisation: every user-facing string translatable, with a text domain that matches the slug. WordPress.org loads translations for hosted plugins automatically, so you do not need to bundle language files.
  • Enqueued assets only: no <script> or <link> tags printed directly; use wp_enqueue_script() and wp_enqueue_style().
  • No development files: no node_modules, test fixtures or build configuration in the release, unless the guidelines require the sources.

The slug comes from the plugin name in your submission and cannot be changed after approval, so choose the name carefully. The running example uses myplugin purely for illustration; a real submission needs a distinctive name.

The Plugin Check tool

Plugin Check is a free tool, maintained by WordPress contributors and published on WordPress.org, that runs many of the checks reviewers care about: directory requirements, security, performance, internationalisation and readme validity. Install it on a development site, then run it from Tools > Plugin Check, or from WP-CLI:

Shell
wp plugin install plugin-check --activate
wp plugin check myplugin

Fix every error, and read every warning. Add the WP-CLI command to CI alongside PHPCS from lesson 19 and PHPUnit from lesson 18, so a release candidate is checked automatically.

readme.txt

The directory builds your plugin page from readme.txt in the plugin root, not from the PHP header. A complete example:

Plain text
=== My Plugin Events ===
Contributors: yourwporgusername
Tags: events, bookings, calendar, rsvp
Requires at least: 6.5
Tested up to: 7.0
Requires PHP: 8.1
Stable tag: 1.4.0
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Publish events, take bookings and send reminders, with blocks for listings and event details.

== Description ==

My Plugin Events adds an events post type with dates, prices, event types and speakers...

= Features =

* Upcoming events block
* Bookings with guest limits
* Privacy export and erasure for bookings

== Installation ==

1. Install the plugin from Plugins > Add New, or upload the ZIP file.
2. Activate it.
3. Go to Settings > Events to set the maximum number of guests.

== Frequently Asked Questions ==

= Does it work on Multisite? =

Yes. Each site has its own events and bookings.

== Screenshots ==

1. The upcoming events block in the editor.
2. The bookings settings page.

== Changelog ==

= 1.4.0 =
* Added: event date column on bookings for faster reports.
* Fixed: guest limit not applied to REST bookings.

== Upgrade Notice ==

= 1.4.0 =
Adds a database column. Large sites update existing bookings in the background.

The fields that matter most:

  • Contributors: WordPress.org usernames, comma-separated. They appear on the plugin page and can be given commit access.
  • Tags: a few relevant terms. Only the first five are used.
  • Tested up to: the latest WordPress version you have tested against. Out-of-date values trigger a warning on the plugin page, so update it with each major WordPress release, even without a code change.
  • Stable tag: the SVN tag users receive. More on this below.
  • Short description: the line after the headers. It is limited to 150 characters and appears in search results.
  • Screenshots: each numbered caption matches an image in the SVN assets folder.

Keep Requires at least, Requires PHP and the version in step with the main plugin file. The readme validator on WordPress.org checks the format before you commit.

Building the release

Build a clean ZIP from a clean checkout, with production dependencies only:

Shell
composer install --no-dev --optimize-autoloader
npm ci
npm run build
wp dist-archive . ../myplugin.zip

wp dist-archive comes from a WP-CLI package that is not part of every WP-CLI install. If the command is missing, add it once with wp package install wp-cli/dist-archive-command. It builds an archive of the plugin and honours the .distignore file from lesson 17. Unzip the result and test it on a fresh site: this is exactly what reviewers and users will receive.

Submitting

Submit the ZIP through the plugin developer pages on WordPress.org. Automated checks run first, then a member of the Plugin Review Team reviews the code and replies by email. Reply to the email with fixes rather than submitting again. Reviewers often list several issues of the same type with examples, and expect you to fix every instance, not only the lines quoted.

Make sure your account has two-factor authentication enabled, because committing to the plugin directory requires it.

Releasing with SVN

Once approved, you receive a Subversion repository at https://plugins.svn.wordpress.org/<slug>/. It is a release channel, not a development repository: develop in Git, and commit to SVN only when you release.

The repository has fixed folders:

FolderContains
trunk/The latest code, including readme.txt
tags/<version>/One frozen copy per release, such as tags/1.4.0/
assets/Banners, icons and screenshots for the plugin page; never shipped to users
branches/Optional; rarely used

A release:

Shell
# Once: check out the repository.
svn checkout https://plugins.svn.wordpress.org/myplugin myplugin-svn

# Copy the built plugin into trunk, removing files that no longer exist.
rsync -a --delete --exclude=.svn /path/to/build/myplugin/ myplugin-svn/trunk/

cd myplugin-svn

# Tell SVN about added and removed files.
svn add --force trunk
svn status | grep '^!' | awk '{print $2}' | xargs -r svn delete

# Tag the release from trunk.
svn copy trunk tags/1.4.0

# Review, then commit. Use the SVN password from your WordPress.org profile.
svn status
svn commit -m "Release 1.4.0" --username yourwporgusername

How users get it: the directory reads Stable tag from trunk/readme.txt, then serves the code in tags/1.4.0/. If Stable tag were trunk, users would get whatever is in trunk at any moment, which is why a numbered tag is strongly preferred.

Before every commit, check that these four values agree:

  1. Version: in the main plugin file header.
  2. MYPLUGIN_VERSION in the code.
  3. Stable tag: in readme.txt.
  4. The tag folder name.

To bump only Tested up to after a new WordPress release, edit readme.txt in trunk and in the current tag and commit. No new version is needed.

Plugin page images go in assets/: banner-772x250.png and banner-1544x500.png for the header, icon-128x128.png and icon-256x256.png (or a single icon.svg) for the icon, and screenshot-1.png, screenshot-2.png and so on to match the readme captions.

Commit small, deliberate releases. Every commit to trunk can trigger rebuilds of your ZIP and language packs, and SVN history is permanent, so never commit secrets.

After launch

  • Support forum: every plugin has one. Answer promptly, and mark resolved threads. Response rates are shown on the plugin page.
  • Translations: volunteers translate your strings on translate.wordpress.org. Language packs are delivered automatically to users, which only works if your text domain matches the slug.
  • Security reports: publish a way to report vulnerabilities privately. If a vulnerability is reported to the plugin team, they may close the plugin until a fixed version is released, so respond quickly and keep releases simple to make.
  • Ownership: add trusted co-maintainers as committers through the plugin's advanced settings, so releases do not depend on one person.
  • Closing: if you stop maintaining the plugin, say so, and ask the plugin team to close it or look for a new owner, rather than leaving users on unpatched code.

Summary

  • The directory hosts free, GPL-compatible plugins that are complete, readable, private by default and respectful of the admin; read the detailed guidelines before submitting.
  • Fix security, prefixing, i18n and enqueuing issues first; run Plugin Check, PHPCS and tests on every release candidate.
  • readme.txt drives the plugin page: keep Tested up to, Requires at least, Requires PHP and Stable tag accurate.
  • Release by copying a clean build into trunk/, copying trunk to tags/<version>/ and committing; Stable tag decides what users receive.
  • After launch, support users in the forum, rely on translate.wordpress.org for translations, and handle security reports quickly.

Further reading