You wrote the plugin. You submitted it. After some back-and-forth on the name and a rejection or two, you got the approval email with your repository URL — and then you discovered that WordPress.org runs on Subversion, which you have possibly never used, and the official documentation assumes you have.
I hadn’t. I’ve been building for the web for years and I have never once touched SVN. My mental model for “putting files on a server” was FTP, and my mental model for version control was Git, and SVN here is neither.
Here’s the part that trips people up: SVN on WordPress.org is not a version control workflow. It’s a publishing mechanism. You are not committing your development history. You are placing finished files into specific directories that mean specific things to the directory software. Keep developing wherever you develop. SVN is the last step, not the process.
Here’s what I wish someone had told me before I started.
Before anything else: your SVN password is not your password
WordPress.org uses per-service passwords. Your SVN credentials are separate from the password you log into wordpress.org with, and you have to generate them.
Go to your profile, into Account & Security, and generate a dedicated SVN password. Copy it somewhere safe immediately. Your SVN username is your wordpress.org username and it is case-sensitive. It will not accept your email address.
Every “authentication failed” post I found while flailing at this turned out to be someone using their site login.
The four directories
When you check out your repository, you get four top-level folders. Three of them matter.
/trunk — your current code. This is the working copy of your plugin.
/tags — frozen snapshots. Each release gets a folder named for its version number: tags/1.2.2/. This is what users actually download.
/assets — banner, icon, and screenshots for your directory listing page.
/branches — ignore it. You won’t need it.
That third one is the single most common point of confusion, so I’ll say it plainly: your plugin’s banner image does not go inside your plugin. It goes in /assets, at the repository root, alongside /trunk — not inside it. These files are never shipped to users. They exist only to render your listing page. I had to read that three times before it stopped feeling wrong.
The sequence
If you’re comfortable at a command line, the whole thing is five commands. Check out the repository:
svn co https://plugins.svn.wordpress.org/your-plugin-slug
cd your-plugin-slug
Copy your plugin files into trunk/, then tell SVN about them. New files must be explicitly added — SVN will not notice them on its own, and this is the difference that catches Git users:
svn add trunk/* --force
svn ci -m "Initial commit of version 1.0.0"
Now create the tag. Critically, you do this server-side with svn cp, not by copying files around in your file manager:
svn cp trunk tags/1.0.0
svn ci -m "Tagging version 1.0.0"
Then the assets:
svn add assets/*
svn ci -m "Adding directory assets"
That’s the whole publishing model. It is genuinely simple once you can see it.
Doing this on Windows, in TortoiseSVN
I did this on Windows with no SVN client installed, which is how I suspect a fair number of people arrive at it. TortoiseSVN is the right tool — it’s a shell extension, so everything happens through right-click menus in Explorer rather than a separate application.
It also introduces about four ways to fail that don’t exist at the command line. I hit three of them.
Put your working copy somewhere boring
I created mine at C:\svn\canary-site-monitor\. Deliberately not in OneDrive, not in Documents, not anywhere a sync client is watching.
Sync services and SVN working copies interact badly. SVN keeps its own metadata in a hidden .svn directory, and a sync client that decides to helpfully reorganize or partially upload that metadata will corrupt the working copy in ways that are tedious to unpick. Pick a plain path outside any synced folder.
Make sure you’re committing the right build
If you use Freemius or any similar service, it generates two zips: a premium build and a free build. Only the free build goes to WordPress.org. The premium build contains your paid code, and in my case also contained a gatekeeper key that had no business being in a public repository.
Check before you stage. Open the zip and confirm you’re looking at the one without your Pro directory in it.
The commit will be rejected if you leave the message blank
WordPress.org runs a pre-commit hook that requires a commit message. TortoiseSVN will happily let you click OK with an empty box, and the server will refuse the commit.
It’s not a warning. It’s a rejection. Write something.
Tagging is where I lost the most time
This is the part worth reading carefully, because I failed twice and both failures looked like they’d worked.
First failure: I right-clicked the working copy root and chose Branch/Tag. Wrong. You need to right-click the trunk folder specifically — that’s the thing being copied.
Second failure: the destination path in the dialog resolved to trunk rather than tags/1.2.2. TortoiseSVN’s path field is relative in a way that is easy to misread, and I ended up copying trunk onto itself.
What finally worked: use the Repo-browser instead. Right-click → TortoiseSVN → Repo-browser, navigate to your trunk, right-click it, choose Copy to, and type the full, explicit destination URL:
https://plugins.svn.wordpress.org/canary-site-monitor/tags/1.2.2
No relative paths, no ambiguity about what’s being copied where. It committed cleanly on the first try.
Windows hides file extensions, and it will cost you a commit
I committed my assets — icon, banner, screenshots — and the listing page didn’t update. Every filename in the repository had a doubled extension: icon-256x256.png.png.
Windows Explorer hides known file extensions by default. So a file already named banner-772x250.png displays as banner-772x250, and when you rename it to what you think it should be called, you get banner-772x250.png.png. The directory software looks for exact filenames, finds nothing, and shows you the default placeholder.
Turn on View → File name extensions in Explorer before you touch anything in /assets. Then rename, re-add, and commit again.
The things that will bite you regardless of platform
Your version numbers must agree in three places: the Stable tag in readme.txt, the Version: header in your main plugin file, and the name of the tag folder. If Stable tag says 1.2.2 and no tags/1.2.2/ folder exists, users get nothing.
Stable tag is what controls what users download — not the highest tag number present, not what’s in trunk. This is the most important sentence in this post. It means your rollback mechanism, if you ship something broken, is to edit one line in trunk’s readme.txt to point at the previous tag. That’s it. That’s the whole rollback. You don’t delete anything or revert anything.
Never edit a tag after publishing it. Tags are meant to be immutable snapshots. Fix the problem in trunk and cut a new tag.
Assets can take time to appear after you commit, and search results can take up to 72 hours to fully update. Don’t re-commit repeatedly assuming it failed. Check the raw asset URL first.
Validate your readme before you commit. There’s an official readme validator, and a malformed readme.txt produces a listing page that looks broken in ways that are genuinely hard to diagnose after the fact.
Check that your readme has a == Screenshots == section at all. Mine didn’t. The images were committed correctly and displaying, but with no captions, because captions live in the readme and are matched to screenshots by number. Worth also checking that none of your screenshots show a paid feature — a locked upsell screen on a free listing page is a bad first impression, and I had to renumber mine after dropping one.
It’s tedious, not hard
That’s the honest summary. There’s no clever part. There’s a publishing model that takes about ten minutes to understand and a handful of platform-specific traps that are individually trivial and collectively responsible for an entire afternoon.
The plugin went live at version 1.2.2, serving from tags/1.2.2, with assets rendering correctly, after two failed tag attempts, one rejected commit, and a set of image files that all thought they were named .png.png.
Canary Site Monitor is free on WordPress.org. Getting it approved in the first place took six rejections, which I’ve written about separately.