Publishing

Share a plugin in three ways:

Who can use itNeeds review
Send the fileAnyone you send the .zip / .json toNo
Publish to the marketplaceEveryone on PopCraftYes
Install for a workspaceEveryone in your team workspaceThe version must be approved

Publishing needs a PopCraft account. Open main menu → Manage plugins… while signed in.

Publish a version

Publish a plugin from the plugin manager · 0:05
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 .zip or .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:

FieldRule
iconAn https:// URL, or a data:image/… URL. Not a path in the package (a panel's icon may be one: see manifest)
categoryOne of productivity, design-systems, ui-kits, icons, themes, ai, import-export, prototyping, motion, widgets, accessibility, data, fun
tagsAt 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, homepagehttps:// 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.

  1. Create a personal access token (Account → Personal access tokens) with the marketplace:publish scope. 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.
  2. Store it as the repository secret POPCRAFT_TOKEN.
  3. POST each item to the REST API: POST /api/v1/plugins (the same .zip or .json bundle as above), POST /api/v1/packs and POST /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

VersionStatus after publishing
The plugin's first versionIn review
A version asking for a permission no approved version hadIn review
Any other updateApproved 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 network use 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 fieldWhat it does
iconSquare image URL (https:, or a small data: image). Shown on the card and the detail page.
screenshotsUp to 6 https: image URLs for the detail page.
categoryOne of productivity, design-systems, ui-kits, icons, themes, ai, import-export, prototyping, accessibility, data, fun.
tagsUp to 10 lowercase tags (a-z, digits, dashes).
homepageProject 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

  • id uses a prefix you own and will never change
  • version is higher than your last published version
  • description says what the plugin does in one or two sentences
  • permissions lists 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