Use case · Plugins
Licensing for Figma, Photoshop, and VS Code plugins
Add paid tiers to your JavaScript-based plugin — Keylight activates a license key and gates Pro features inside Figma, Photoshop (UXP), or VS Code, with no backend.
Start FreeFor developers selling paid plugins for Figma, Photoshop (UXP), or VS Code.
- Plugin marketplaces rarely handle paid licensing well.
- You want Pro tiers without a backend.
- Each host has a different JavaScript sandbox.
Updated June 2026
Plugin marketplaces were designed for distribution, not monetization. Figma’s community, the Adobe Exchange, and the VS Code Marketplace all make it easy for users to install your plugin — and all of them leave the question of how you actually charge for it largely unanswered. You get installs. You do not get a payment layer, a licensing system, or a way to distinguish free users from Pro users at runtime.
This guide covers how to add paid tiers to JavaScript-based plugins — Figma, Photoshop (UXP), and VS Code — using signed license keys and Keylight’s JS SDK, with no backend required.
Why plugin licensing is its own problem
Native app licensing has a clear model: you verify a key at launch, cache the result, and optionally revalidate periodically. Plugin licensing is messier, for a few reasons.
The sandbox is different in every host. Figma plugins run in a restricted web worker with no Node environment and constrained network access. Photoshop UXP plugins have their own module system and run against a different browser engine than Figma. VS Code extensions run in a Node.js context — closer to a normal runtime, but isolated from the user’s project environment. Each host imposes its own restrictions on what APIs are available, what can be stored, and how network requests work.
Marketplace policies constrain your options. The Figma community and Adobe Exchange do not offer paid-tier gating at the platform level. VS Code Marketplace has no built-in monetization at all. You cannot require a login before showing any UI, and you cannot phone home to an arbitrary server during every API call without affecting perceived performance. The pattern of “call your server for every action” that works fine in a SaaS app does not translate.
Users share plugins freely. Unlike a desktop app that is tied to an executable on a specific machine, a plugin is often a URL or a manifest a user can pass to a colleague. A licensing system that does nothing to differentiate free from paid behavior is trivially bypassed — not because users are adversarial, but because the plugin host has no built-in enforcement.
Keylight’s approach sidesteps most of this: a cryptographically signed key is verified locally against a public key your plugin bundles. No server call is required to check whether the key is valid. The key itself carries the entitlements, and the JS SDK does the verification inside the plugin’s sandbox.
What the JS SDK does inside a plugin
The @keylight-dev/js SDK is a small, dependency-light module you bundle into your plugin. When a user enters their license key, the SDK verifies the Ed25519 signature against a trusted public key fetched at startup — or bundled directly — and resolves the entitlements encoded in the key payload.
The verification happens entirely in JavaScript, with no native extensions and no platform-specific code. That means the same SDK works in a Figma plugin web worker, a UXP environment, and a VS Code extension host.
Once kl.hasEntitlement("pro") resolves to true, you gate whatever features belong to your Pro tier. The check is synchronous after the initial activate() call, so you do not need to restructure your plugin’s async flow around licensing.
Persistence works through each host’s storage API: figma.clientStorage in Figma, UXP’s localStorage equivalent in Photoshop, or VS Code’s globalState / secrets store. The SDK does not prescribe a storage mechanism — you pass it the cached key at startup and it re-verifies locally.
What you need to set up
A Keylight account and a product. You create a product (“my-plugin”), set up your Pro entitlement, and connect your Stripe account. Keylight receives Stripe webhooks and mints a signed license key when a customer completes checkout. The key arrives by email.
A checkout page. This lives outside the plugin — a standalone landing page, a Gumroad listing, or a Stripe Payment Link. The plugin shows a “Buy Pro” link that opens the checkout in the user’s browser. The plugin host environment is not the right place to embed a payment form, and none of the three hosts make that easy anyway.
A key entry UI inside the plugin. A small form where users paste the key they received. After activate() succeeds, you store the key in the host’s persistence API and recheck it on subsequent launches.
That is the full surface. There is no backend for you to run, no webhook endpoint to expose, and no server infrastructure to maintain.
Integrating with Keylight
import { Keylight, fetchKeyset, FetchTransport } from "@keylight-dev/js";
const ks = await fetchKeyset(new FetchTransport(), "https://api.keylight.dev", "your-tenant");
const kl = new Keylight({
tenantId: "your-tenant",
productId: "your-plugin",
sdkKey: "<your SDK key>",
trustedKeys: ks?.keys ?? {},
});
await kl.load();
await kl.activate("USER-LICENSE-KEY");
if (kl.hasEntitlement("pro")) {
// unlock pro features
}
fetchKeyset retrieves the current public keys from Keylight’s API at plugin startup — once, not on every action. You can also bundle a snapshot of the keyset directly if your host’s network sandbox makes outbound requests awkward; Keylight publishes the keyset at a stable URL for exactly this reason.
await kl.load() hydrates the SDK from cached state at startup so later entitlement checks are synchronous; the user’s key is passed to activate(), not to load(). kl.activate() verifies the signature and writes the entitlements. kl.hasEntitlement() is synchronous from that point on.
For Figma plugins specifically, run fetchKeyset and kl.load() in the plugin’s main thread before showing any UI. For VS Code extensions, do it in the activate() extension function. For UXP, do it during the panel’s init lifecycle. The pattern is the same; only the lifecycle hook differs.
Getting started
Create a Keylight account, add a product with a “pro” entitlement, and connect your Stripe account. Generate an SDK key for your plugin and note your tenant ID. Drop @keylight-dev/js into your plugin’s bundler config — it is a plain ESM package that tree-shakes well.
From there the integration is roughly an hour of work: fetchKeyset at startup, a small key entry form, activate() on submit, hasEntitlement() where you gate features, and a localStorage-equivalent write to persist the key between sessions.
Keylight plans start at $19/month. The free tier supports up to five licenses, which is enough to test the full activation and entitlement flow before you ship.
Plugin distribution is a solved problem. Monetizing that distribution is not — but it does not have to mean building a backend, wiring up webhook handlers, or managing cryptographic key material yourself. A signed key and a small SDK is all it takes.
Frequently asked
Can I license a Figma or VS Code plugin?+
Yes. These plugins run JavaScript, so the Keylight JS SDK activates a key and gates Pro features the same way it does in a web or Node app.
Does this cover audio (VST/AU) plugins?+
Not yet. Audio plugins are C++ and need the native C++ SDK, which is on the roadmap. This page covers JavaScript-based plugins — Figma, Photoshop (UXP), and VS Code.
Start licensing your app today
Drop in the Swift SDK, point it at your dashboard, and sell paid apps in under a minute. Free forever tier included.
Start Free