Install
Upload it under Plugins → Add New Plugin → Upload Plugin, then activate.
Install straight from GitHub with WP-CLI:
wp plugin install https://github.com/nilovelez/cute-wp-badges/releases/download/v1.0.0/cute-wp-badges-1.0.0.zipRemember the colorful badges on the old WordPress.org profiles? This WordPress plugin brings them back as images: the badges of your own profile, or any other badge, one by one or in a grid, ready for your website, your slides or your next WordCamp talk.
What it does
- Reads the badges of any WordPress.org profile: you only type the username.
- Draws them in the classic profile style: a colored ring around a white circle, or a tinted one for team badges, with the icon in the badge color.
- Puts them in the order you want, one badge alone or a grid with as many columns as you like.
- Gives you a PNG of the size you need, or an SVG that scales to any size, always on a transparent background.
- Downloads the image or saves it to your Media Library.
- Remembers your design, so next time it is right where you left it, and tells you when you get a new badge.
Installing it
The plugin is not in the WordPress.org plugin directory, only here on GitHub. It needs WordPress 6.6 or later.
- Go to the latest release and download
cute-wp-badges-<version>.zip. - In your WordPress, go to Plugins → Add New Plugin → Upload Plugin, choose the zip and click Install Now.
- Activate it. The plugin lives in Tools → WordPress.org Badges.
To update it, download the zip of the new release and upload it the same way: WordPress offers to replace the installed version.
Using it
Your badges
In the My badges tab, type your WordPress.org username, as in your profile URL (https://profiles.wordpress.org/username/), and click Load badges. The first time, every badge of your profile is picked. Click a badge to leave it out of the image, or to add it back.
The plugin keeps the profile for 12 hours, so it does not ask WordPress.org every time. If you have just earned a badge, click Read the profile again from WordPress.org.
When you come back, your picks and your order are still there. A badge that is new on your profile shows up marked as New and not picked yet, so you choose whether it goes into your image; pick it and it goes at the end. A badge that is gone from your profile is taken out, with a notice.
Order and image
Drag the badges in the Order list, or use the arrows, to put them in the order you want, or sort them by profile order, by name or by team. On the right, choose the number of columns, the badge size and the gap between badges, and the format:
- PNG: an image of exactly the size shown under the preview, for most uses.
- SVG: an image that scales to any size without losing quality, for print or for designers.

Then click Download, or Save to Media Library to use the image in your posts and pages right away.
WordPress does not accept SVG files in the Media Library, as a safety measure. An administrator can turn on Allow saving SVG images to the Media Library on this site: the plugin then saves the SVG images it builds itself from its own badge files, and every other SVG upload stays blocked.
Any badge
The Any badge tab has every badge, not just yours: for example, the badge of a team for a Contributor Day, or the badges of the teams taking part in an event. Search by name or team, or show only the team badges, and pick the ones you want. It works the same way as My badges, and keeps its own design.
Saving a design
Export settings saves your design (the badges, their order and the image options) to a small file, cute-wp-badges-<date>.json. Import settings loads it again, on the same site or on another one: handy to keep the design of an event, or to make the same image again with a new badge. In My badges, the badges of the file that are not on the loaded profile are left out.
Questions
A badge is missing. The plugin knows the badges that existed when it was released. If your profile has a newer one, the page says so: install the latest release, or update the badge list yourself (see Updating the badge catalog).
Who can use it? Any user who can upload files to the Media Library (authors, editors and administrators). Each user has their own designs.
What does it store? Each user's designs, the profiles it read in the last 12 hours and the SVG option. Deleting the plugin removes all of that. The images saved to the Media Library stay.
Does it send my data anywhere? No. It only reads the public profile page on profiles.wordpress.org, from your server.
For developers
How it works
WordPress.org has no public API for badges, so the plugin reads the groups tab of the profile (https://profiles.wordpress.org/<username>/groups/) on the server, through its REST route GET /wp-json/cute-wp-badges/v1/badges/<username>, and keeps the result for 12 hours in a transient. Add ?refresh=true to read the profile again. Details in docs/wporg-profile-api.md.
The page saves each tab's state per user through POST /wp-json/cute-wp-badges/v1/state/<tab>, into user meta. PNG images go to the Media Library through the core route POST /wp-json/wp/v2/media, and SVG images through POST /wp-json/cute-wp-badges/v1/media, only while the site option cute_wp_badges_allow_svg is on: that route takes badge ids and the layout, never markup, and builds the SVG on the server the same way the badge library does. The plugin routes need the upload_files capability, and the option can only be changed by users who can manage options.
The page is plain script modules with no build step (resources/js/), which is why it needs WordPress 6.6 or later. The settings file is JSON: { "plugin": "cute-wp-badges", "version": 1, "badges": [...], "columns", "size", "gap", "format" }.
The badges
Every badge ships as a finished SVG file in resources/badges/<id>.svg: the ring, the white border, the tinted circle of team badges (a solid color, no transparency) and the icon, all in the badge color, with a transparent background outside the ring. The files are scale-free (a viewBox, no fixed size) and clean: no ids, classes, styles, metadata, comments, embedded data or external references.
They are built from the catalog and the icons in resources/icons/ by composer build-badges (scripts/build-badges.mjs), which sanitizes each icon with an allowlist on the way in. composer validate-badges checks that every badge has its file, up to date and clean. The icons themselves are only a source for the build and stay out of the plugin zip.
The badge library
resources/js/cute-wp-badges.js gives you any badge of the catalog, or a grid of them, as SVG or PNG. It is a plain ES module with no build step, and works in the browser and in Node 18 or later:
import { renderBadge, renderGrid } from './resources/js/cute-wp-badges.js';
const svg = await renderBadge( 'translation-contributor' ); // the badge file as it is
const png = await renderBadge( 'translation-contributor', { format: 'png', size: 500 } ); // 500 × 500 PNG
const grid = await renderGrid( [ 'core-contributor', 'polyglots-team', 'photos-team' ], { format: 'png', columns: 5 } );
renderBadge( id, { format, size } ):idis the badge id (the WordPress.org association slug) or one of its aliases;formatis'svg'(default) or'png'. As SVG it returns the badge file as it is. As PNG it draws itsizepixels wide and high, from 1 to 4096 (default 128).renderGrid( ids, { columns, size, gap, format } ): lays the badges out left to right and top to bottom,columnsper row (default 5, fewer if there are fewer badges), eachsizewide (default 128) withgapbetween them (default 32), on a transparent background. As SVG, it nests each badge file as it is inside one scale-free SVG, wheresizeandgaponly set the proportions. As PNG, the whole grid is rasterized at once, up to 8192 pixels on each side.- Both return SVG markup as a string, or the PNG as a
Blobin the browser and aBufferin Node, and throw on an unknown badge, format or out-of-range number. getBadges(): every badge in the catalog.getBadge( id ): one badge, ornull.
The library reads the catalog and the badge files relative to its own file, so it has to stay in the plugin folder structure. In the browser, PNG output is drawn with a canvas. In Node it needs @resvg/resvg-js: run npm install in the repo.
To check it by eye, npm run samples renders into samples/ (not committed) one SVG and one PNG per badge, a sheet with all of them, and reference-grid.svg and .png, the badges of docs/reference-badges.png in the same order to compare with it. preview.html shows each badge drawn with plain CSS next to its composed SVG file.
Updating the badge catalog
The plugin ships with the list of WordPress.org badges that existed when it was released. Badges change rarely, but when a WordPress.org team adds or renames one, the catalog has to be updated and the plugin packaged again.
You need Git, Node.js 18 or later and Composer.
-
Clone the repository and go into it:
git clone https://github.com/nilovelez/cute-wp-badges.git cd cute-wp-badges -
Update the catalog from WordPress.org:
composer update-badgesIt reads the official list of badges (https://profiles.wordpress.org/associations/) and the WordPress.org profile CSS, updates
data/badges.jsonand the team icons inresources/icons/custom/, composes the badge files inresources/badges/, validates the catalog and rebuildspreview.html. It prints what changed:NEW: a badge that was not in the catalog. It is added with what can be worked out automatically. The fields it could not work out are left empty (null).RENAMED: a badge whose name changed on WordPress.org. The new name is applied.GONE: a badge that is no longer on WordPress.org. It is not removed; remove it by hand if it is really gone.COLOR: the catalog and the profile CSS disagree on a color. Nothing is changed. Check the profile badges handbook (https://make.wordpress.org/meta/handbook/tutorials-guides/profile-badges/) and decide.CLASS: a badge class in the profile CSS that no badge uses, usually a sign of a new badge.
-
Complete the new badges by hand in
data/badges.json. Usually that meansteamUrl(the team's page) and, for Dashicons,icon, which the handbook lists for each team. Every field is described in docs/badges.md. -
Compose the badges again and validate the catalog:
composer build-badges composer validate-badgesbuild-badgesrewrites the badge files inresources/badges/with your changes.validate-badgeschecks every field, that each badge's icon file exists inresources/icons/, and that each badge file is up to date and clean. If it reports errors, go back to step 3 and run both again until it reports none. Then openpreview.htmlin a browser to check the new badges by eye. -
Raise the plugin version in the
Version:header ofcute-wp-badges.phpand commit everything, saying that the badge catalog was updated:git add -A git commit -m "Update the badge catalog"Commit before building the zip:
git archiveonly packs committed files, and reads the.gitattributesof the commit to decide what to leave out. -
Build the plugin zip:
git archive --format=zip --prefix=cute-wp-badges/ -o cute-wp-badges-<version>.zip HEADDevelopment files are left out (see
.gitattributes).
License
GPL-2.0-or-later. See LICENSE.
Releases
1 release. Each count is every asset in that release; expand a row for the breakdown.