Electron License Starter
Clone-and-run Electron app with Keymint license activation pre-configured. Machine binding, activation UI, and license health checks included.
Quick Start
bash
git clone https://github.com/keymint-dev/keymint-electron-starter.git
cd keymint-electron-starter
npm install
cp .env.example .env
# Fill in KEYMINT_CLIENT_API_KEY and KEYMINT_PRODUCT_ID
npm run devOpens an Electron window with an activation dialog. Enter a valid Keymint license key, and the main app unlocks.
What's Included
- License activation — calls
POST /key/activatewith a stable installation ID fromKeyMint.getOrCreateInstallationId()as thehostId - Activation UI — clean dialog with key entry and status feedback
- Persistent storage — license key and activation state saved via
electron-store(its encryption key is a fixed string in the source, so treat it as obfuscation, not a secret) - Health checks — re-validates the license on launch and every 24 hours. A rejected license (HTTP 401, 402, 403 or 404) returns the user to the activation dialog; if the server can't be reached, the app keeps working with the cached state
- Deactivation — a
license:deactivateIPC handler, exposed to the renderer aslicenseAPI.deactivate(), frees the seat and clears the stored license. The starter's main window has no button for it, so add one where it fits your app. Nothing is deactivated on quit - Offline licenses (optional) — set
KEYMINT_PUBLIC_KEYto let users import a signed.licfile (thelicense:importOfflineIPC handler), verified locally with the SDK'sverifyOfflineLicense() - Preload + IPC — secure bridge between renderer and main process (
contextIsolationon, nonodeIntegration)
Configuration
Create a .env file:
text
KEYMINT_CLIENT_API_KEY=km_live_your_client_key
KEYMINT_PRODUCT_ID=YOUR_PRODUCT_ID
# Optional: defaults to https://api.keymint.dev
# KEYMINT_BASE_URL=https://api.keymint.dev
# Optional: enables offline .lic files. PEM from Developer → Public Keys.
# KEYMINT_PUBLIC_KEY="-----BEGIN PUBLIC KEY-----..."The main process loads .env with dotenv at startup. If either required variable is missing, the activation dialog shows a configuration error instead of the app crashing.
| Variable | Where to Find It |
|---|---|
KEYMINT_CLIENT_API_KEY | Keymint Dashboard → Developer → API Keys (create a client scope key) |
KEYMINT_PRODUCT_ID | Keymint Dashboard → Products → your product |
Project Structure
text
src/
├── main/
│ ├── index.ts # Electron main process, gates app on license, schedules health checks
│ ├── license.ts # Keymint SDK wrapper (activate, deactivate, health check, installation ID)
│ ├── offline.ts # Offline .lic verification (optional)
│ ├── ipc.ts # IPC handlers (activate, importOffline, deactivate, getStatus)
│ ├── store.ts # License state in electron-store
│ └── events.ts # Activation event from IPC to the window manager
├── preload/
│ └── index.ts # contextBridge exposing licenseAPI to renderer
└── renderer/
├── activation.html # Activation dialog
└── app.html # Main app (shown after successful activation)SDK Methods Used
| Method | Where | Purpose |
|---|---|---|
client.activateKey() | license.ts | Validate and bind license to machine; also used for the health check |
client.deactivateKey() | license.ts | Free the activation seat when licenseAPI.deactivate() is called |
KeyMint.getOrCreateInstallationId() | license.ts | Stable installation ID used as the hostId |
Build & Package
bash
npm run build # Compile TypeScript
npm run package # Package with electron-builderThe client API key ships inside the packaged app, so anyone can extract it. Give it client scope only: it can activate, deactivate, and manage floating sessions. It cannot read customer data or modify other licenses.
Next Steps
- Add floating license support for concurrent seat licensing
- Add offline license verification for air-gapped deployments
- Wire up Stripe subscription licensing
- Customize the activation UI with your brand colors and logo