Skip to main content
Migrate Already selling? Move your customers to Keylight without re-issuing a single key.
Keylight

Use case · Electron

Licensing for cross-platform Electron apps

Add license keys to your Electron app across macOS, Windows, and Linux — signed keys your app verifies offline, with the JavaScript SDK running in the Node main process.

Start Free

For developers shipping cross-platform desktop apps built with Electron.

  • You ship the same app to macOS, Windows, and Linux and want one license layer for all three.
  • Rolling your own keys means crypto, a server, and a dashboard to maintain.
  • Desktop users expect the app to keep working offline.

Updated June 2026

Electron lets you ship one web codebase as a native binary for macOS, Windows, and Linux. That is also what makes licensing it awkward: the moment you want to sell the app, you need a license layer that behaves identically on three operating systems with three different filesystem and secure-storage conventions. This guide covers what licensing an Electron app actually requires and how to do it without building a backend.

Why Electron is an interesting licensing target

Most desktop licensing tooling was built for one ecosystem. Native macOS tooling assumes Swift and the Keychain. Windows tooling assumes Win32 or .NET. An Electron app is none of those cleanly — it is Chromium plus a Node.js main process, running on three platforms at once. So most licensing solutions either give up and validate everything against a live server, or they target one native platform and leave the others on a hardcoded “free” fallback.

Electron’s architecture actually answers this cleanly, the same way Tauri’s does. The app has a main process with full Node.js access and one or more renderer processes that draw the UI. A licensing layer built for Electron puts verification in the main process — where it has filesystem access and is out of reach of the renderer’s DevTools — and surfaces only the result to the UI over Electron’s IPC bridge. The platform differences stop mattering because the SDK runs in Node, which behaves the same everywhere Electron does.

What licensing an Electron app requires

Cross-platform desktop licensing has the same fundamental requirements everywhere; the challenge is meeting them uniformly.

Signed keys. A license key has to be unforgeable. That means cryptographic signing: the key resolves to an entitlement payload — who bought it, which product, what device limit, when it expires — signed with a private key your server holds and verified against a public key bundled in the app. An unsigned key is just a string anyone can copy.

Offline verification. Desktop users launch apps with no network regularly — on planes, behind corporate firewalls, on bad connections. A check that requires a live server call has no good failure mode. Ed25519 verification is a local operation: the app verifies a signed lease instantly with only the bundled public key.

Platform-neutral storage. The license has to persist across restarts, and the safe place to put it differs per OS. Running the SDK in the Node main process means one storage path handles all three platforms instead of three backends and a pile of platform-detection bugs.

Revocation. When a refund or chargeback lands, the key gets marked revoked server-side. The next time the app revalidates online, it learns the key is dead and gates accordingly. The lease itself does not encode revocation — that is server state the app picks up on periodic online checks.

A dashboard. Customers lose keys and get new machines. Without an admin surface to look up a license and reset activations, every one of those becomes a manual email.

Offline-first on the desktop

The constraint that breaks most DIY implementations is the one web developers hit the first time they ship a desktop app: the network is not always there, and that is fine and expected.

Electron apps run anywhere a binary runs, including air-gapped machines and laptops that have not been online in days. A licensing check that fails closed when it cannot reach a server produces real, user-facing errors for customers who paid correctly. Offline license validation avoids this by splitting the two jobs: the signature check is local, instant, and always works; the revalidation is online, periodic, and picks up revocations and entitlement changes in the background after launch. The customer never sees a network-dependent startup.

This protects you operationally too. If your licensing backend has an outage, your customers are unaffected until their leases expire — which you can set to days or weeks. The blast radius of an incident shrinks to nothing.

Integrating with Keylight

The JavaScript SDK runs in your Electron main process:

// main process (Node)
import { app } from "electron";
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-product",
  appVersion: app.getVersion(),
  trustedKeys: ks?.keys ?? {}, // enables offline lease verification
});
await kl.load();

const res = await kl.activate("USER-LICENSE-KEY");
if (kl.hasEntitlement("pro")) {
  // unlock pro features
}

Because the SDK lives in the main process, the renderer never imports it. Instead you expose a small surface — activate, read state, check an entitlement — over IPC with ipcMain.handle, and call it from the renderer through a contextBridge preload. The tenant configuration and the verified lease stay in Node, where the DevTools console cannot reach them.

When a customer purchases through Stripe, Keylight receives the webhook, mints a signed lease, and emails the key. Your app never needs its own webhook handler. The dashboard gives you license lookup, activation reset, and revocation for support requests.

Getting started

Setup takes under an hour. Create a Keylight account, connect Stripe, then wire the SDK into your main process:

  • Install @keylight-dev/js, call fetchKeyset at startup to cache the public keyset, then activate() on key entry.
  • Persist with the default Node store, or inject an FsStore pointed at Electron’s userData directory so the license file lives with your app’s other state.
  • Bridge activate, state, and hasEntitlement to the renderer over IPC and drive your UI from the result.

There is a full code walkthrough — main process, IPC bridge, and feature gating — in how to add license keys to an Electron app.

Keylight plans start at $19/month on the pricing page. The free tier supports up to five licenses, enough to run the full activation and offline verification flow end to end before you ship.

The cross-platform problem in Electron licensing is real, but it is mostly solved by picking the right process for the check. Verify in the Node main process, keep the renderer informed over IPC, and the platform differences stop mattering.

Frequently asked

Can I license an Electron app?+

Yes. Keylight issues signed Ed25519 keys your Electron app verifies offline. Run the JavaScript SDK in the Node main process and expose only the calls your UI needs to the renderer over IPC.

Should the SDK run in the main process or the renderer?+

The main process. It has Node filesystem access for persistence and keeps your tenant configuration out of the renderer, where a user can open DevTools. The renderer asks the main process through IPC and renders the answer.

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