Install
The JavaScript SDK is one fully-typed package that runs the same way in the browser, Node, Deno, Bun, and edge/Workers. It does online activation and offline Ed25519 lease verification — and verifies licenses identically to the Swift and Rust SDKs (proven by cross-SDK conformance vectors).
Install
Section titled “Install”npm install @keylight-dev/jsInitialise
Section titled “Initialise”Fetch the tenant’s trusted keyset once so leases verify offline, then construct the client:
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", sdkKey: "<your SDK key>", // from your Keylight dashboard appVersion: "1.0.0", maxOfflineDays: 7, // optional offline grace window trustedKeys: ks?.keys ?? {}, // enables offline lease verification});
// Hydrate the cache that backs the synchronous reads. Call once at startup.await kl.load();Activate and gate features
Section titled “Activate and gate features”const res = await kl.activate("USER-LICENSE-KEY");if (!res.activated) console.error(res.error);
// Synchronous, from the cached (signature-verified) lease:if (kl.hasEntitlement("pro")) { // unlock pro features}
// Release the seat when uninstalling / switching devices:await kl.deactivate();Dashboard-owned settings
Section titled “Dashboard-owned settings”The Trial length and Free tier set in the dashboard are the values that apply; what you pass in is the seed a fresh install uses first. Read what is in force with kl.effectiveTrialDurationDays() and kl.effectiveFreeTierEnabled(); kl.fetchConfig() asks the server now instead of waiting for the next validate or beacon.
To verify that those settings really came from your dashboard, pin your key and turn on the check (0.4.0+):
const kl = new Keylight({ tenantId: "your-tenant", productId: "your-product", sdkKey: "<your SDK key>", trustedKeys: { k1: "<raw ed25519 public key, base64>" }, // pinned, not fetched requireSignedConfig: true,});Leave it off until your app has a trial length set in the dashboard. That is what makes Keylight sign an app’s settings; with the switch on, an unsigned app rejects every legitimate response and stays on the value you compiled in. Once it is on, settings that do not verify against the keys you compiled in are never cached, on every route they arrive on. Pin the key in your build rather than fetching it: a keyset fetched over the same connection can be forged by the same attacker. See Verify the signature.
After a purchase
Section titled “After a purchase”Payment webhooks can lag the checkout redirect. refreshAfterUpgrade polls validate briefly and resolves true as soon as the entitlements or state change, false on timeout, abort, or when no license is stored:
// When the customer comes back from checkout. Milliseconds; defaults shown.const changed = await kl.refreshAfterUpgrade(30_000, 2_000, abortController.signal);In a plain browser <script> tag, the IIFE bundle exposes the namespace as window.KeylightSDK (new KeylightSDK.Keylight({ … })).
- Try the live demo — activate a real license key in your browser and watch entitlements flip.
- Offline verification — verify a signed lease with no network round-trip.
@keylight-dev/json npm · GitHub