Publishing
Share a plugin in three ways:
| Who can use it | Needs review | |
|---|---|---|
| Send the file | Anyone you send the .zip / .json to | No |
| Publish to the marketplace | Everyone on PopCraft | Yes |
| Install for a workspace | Everyone in your team workspace | The version must be approved |
Publishing needs a PopCraft account. Open main menu → Manage plugins… while signed in.
Publish a version
Description
Signed in, in the editor. ⋯ → Manage plugins… opens the plugin manager, and Publish from file… sends the Panel Checklist widget’s package to the marketplace. The first version of a new plugin waits for review before it is listed.
Either:
- Installed tab → Publish from file… and choose your
.zipor.json, or - Install the plugin from a file first, then click the publish (paper plane) button on it in the Installed tab.
The package is checked with the same rules as installing (valid manifest, every referenced file
present) and must be at most 5 MB. Importers that need a large WASM converter should keep the marketplace zip thin
(main + ui + manifest) and fetch the binary at runtime with the network permission — see Importers.
Plugin ids
The first account to publish an id owns it. Only that account can publish new versions of it. Choose an id with a
prefix that's clearly yours (acme.color-tools), because it can't be changed later — a different id is a different
plugin.
Ids starting with popcraft. or popcraft-examples. are reserved for PopCraft's own plugins: publishing a new one
is refused (403 reserved_namespace) unless your account is a marketplace reviewer. An id under them that an account
already owns stays that account's, and it keeps publishing its versions as usual.
Listing fields
The marketplace checks a manifest's listing fields when you publish, and refuses the version (400 invalid_package)
when one is wrong. It says one problem at a time, so check them all before the first publish:
| Field | Rule |
|---|---|
icon | An https:// URL, or a data:image/… URL. Not a path in the package (a panel's icon may be one: see manifest) |
category | One of productivity, design-systems, ui-kits, icons, themes, ai, import-export, prototyping, motion, widgets, accessibility, data, fun |
tags | At most 10. Each is lowercase letters, digits and dashes, starting with a letter or digit, up to 24 characters (next-commerce, not next.js commerce) |
screenshots, homepage | https:// URLs |
Your team's items
A plugin, theme pack, or brush or shader pack is published for the team you're working in (from the editor), and belongs to it: its owners and admins edit its listing, list or unlist it and publish its new versions, as you do. On Home, the Market tab lists everything a team has published (its websites, libraries, plugins, theme packs, templates, brushes and shaders), with Edit on each for those who manage it, and a rejected version's note from the reviewer.
Versions
Every publish must have a higher version than the last one; versions can't be replaced or deleted.
Versions compare as dotted numbers (1.10.0 > 1.9.3). A pre-release suffix sorts before its release
(2.0.0-beta < 2.0.0).
The marketplace listing (name, description, author) is updated from the manifest of each new version.
Publish from CI
Everything the marketplace carries except component libraries can be published from a repository: plugins, widgets and theme packs, brush and shader packs, and templates.
- Create a personal access token (Account → Personal access tokens) with the
marketplace:publishscope. Listings belong to the token's account: publish every version of a plugin with the same account's token, since a different account can't publish an id it doesn't own (403 owned_by_other). A new plugin or pack is the account's own; add?workspace=<team id>to publish it for a team the account owns or administers. - Store it as the repository secret
POPCRAFT_TOKEN. - POST each item to the REST API:
POST /api/v1/plugins(the same.zipor.jsonbundle as above),POST /api/v1/packsandPOST /api/v1/templates.
The examples repository does all three with
scripts/publish.mjs and a GitHub Actions workflow. It has one example of every kind, laid out one folder per
item, so copying its examples/, scripts/publish.mjs and .github/workflows/marketplace.yml is the quickest
start.
CI publishing follows the same rules as the editor. A new plugin version goes into review, and
publishing a version that already exists returns 409, so a re-run is harmless. Packs and templates are keyed
by their meta.localId and update in place. A token can't list them: a new pack or template starts private, and
you list it once from the editor. After that, updates stay listed.
Review
| Version | Status after publishing |
|---|---|
| The plugin's first version | In review |
| A version asking for a permission no approved version had | In review |
| Any other update | Approved immediately |
While a version is in review:
- It isn't shown to other people, and they keep getting the latest approved version.
- You can see it (marked In review) and install it yourself for testing.
Reviewers approve or reject. A rejected version is marked Rejected in your Marketplace tab; click the plugin's name to read the reviewer's note. Fix the issue and publish a new, higher version.
Reviewers check that a plugin:
- Does what its name and description say.
- Asks only for permissions it needs, and explains
networkuse in its description. - Doesn't collect data without saying so or send file contents to third parties unexpectedly.
- Doesn't imitate PopCraft UI to trick users, or include malicious or obfuscated code.
The public listing
Approved plugins appear on the public marketplace at /marketplace, where anyone can browse without signing in and
install with one click (they are sent to the app to sign in first). Your listing can carry more than the name and
description:
| Manifest field | What it does |
|---|---|
icon | Square image URL (https:, or a small data: image). Shown on the card and the detail page. |
screenshots | Up to 6 https: image URLs for the detail page. |
category | One of productivity, design-systems, ui-kits, icons, themes, ai, import-export, prototyping, accessibility, data, fun. |
tags | Up to 10 lowercase tags (a-z, digits, dashes). |
homepage | Project or documentation page, https:. |
Fields set in the manifest are copied to the listing on every publish. You can also edit them without republishing: open the plugin manager's Marketplace tab and choose Edit listing on a plugin you published. A theme pack is listed as a Theme; a plugin with code is listed as a Plugin.
Component libraries are listed too: in the Components panel's Libraries section, choose Listing… on a library published from your file and switch it to public. Anyone can then add it to their files from the marketplace.
Listing and unlisting
Your plugins appear in your own Marketplace tab, including unlisted ones. Click the plugin's name to open its details:
- Unlist hides the plugin from search. Anyone who already installed it keeps it, and workspace installs keep working.
- Relist makes it searchable again.
Installing from the marketplace
In the Marketplace tab, search by name, description or author, then:
- Install — adds the latest approved version for you.
- Update — appears when a newer approved version exists than the one you have.
- Click a plugin's name to see all versions and install a specific one.
Marketplace plugins are downloaded to your device and run offline like any other plugin. The permissions prompt appears the first time you run a plugin, and again after an update that asks for more.
Installing for a workspace
Workspace owners and admins see a button for each workspace they manage under every approved plugin in the Marketplace tab. Turning it on installs the plugin for everyone in that workspace:
- Members get it automatically the next time they sign in or open the plugin manager, and it's kept on the latest approved version.
- Members can disable it but not uninstall it; it's marked Workspace in their Installed list.
- Turning it off removes the plugin from members who didn't also install it themselves.
Checklist before publishing
-
iduses a prefix you own and will never change -
versionis higher than your last published version -
descriptionsays what the plugin does in one or two sentences -
permissionslists only what you use - Every command works on an empty selection, a large selection, and a page with no layers
- Errors are caught and shown with
notify(…, { error: true }) - The plugin calls
closePlugin()when it's done (unless it's meant to stay open) - Widgets register at the top level and handle state saved by older versions