IntegralLive demo.
Integral signs licenses with Ed25519 and checks them offline in your app. This page runs the same code as the npm package: it creates a key pair, issues licenses, verifies them and applies your plans.
Everything runs in this page. Keys and licenses never leave your browser.
Keys
One key pair per productThe private key signs, the public key only checks.
In a real project the private key stays on your server or in CI secrets. The public key ships with your app: it cannot create licenses, so it does not need to be secret.
Public key (ships with the app)
…Private key (stays on the server)
…Same with the CLI
npx integral keygenIssue
Issue a licenseWhat a payment webhook or the CLI does.
Pick a plan and optional extras. The license is a signed string you can email, store in a file or paste into a text field.
Verify
Check it offlineChange anything and the signature breaks.
Edit the license, tamper with the plan or sign it with a stranger's key. Move the date to see expiry and update periods at work.
Entitlements
What the app unlocksPlans, features and limits from one definition.
Without a valid license the app falls back to the free plan. With one, it applies the plan plus the extras signed into the license.
Current plan: Free
- Editorincluded
- Export to PDFin Pro
- Cloud syncin Pro
- Single sign-onin Team
- Beta featuresnot in any plan
Projects
1 of 1
Limit of your plan reached.
plans.ts
import { definePlans } from "@sweberdev/integral"
export const plans = definePlans({
free: {
label: "Free",
features: ["editor"],
limits: { projects: 1 },
},
pro: {
extends: "free",
label: "Pro",
features: ["export", "sync"],
limits: { projects: 10 },
},
team: {
extends: "pro",
label: "Team",
features: ["sso"],
limits: { projects: null }, // unlimited
},
})Pro
Integral Pro: licenses from Polar, automaticallySimulated subscription, real signatures.
The license server of Integral Pro listens to Polar webhooks and keeps one license per subscription. Play through a subscription below. Each step re-signs the license the way the server does: renewals extend the update period, a cancellation keeps the installed version working, a refund revokes the license.
Code
Three lines in your appOffline, no server, no dependencies.
import { createEntitlements, verifyLicense } from "@sweberdev/integral"
const result = await verifyLicense(license, { publicKey: INTEGRAL_PUBLIC_KEY, product: "my-app" })
const entitlements = createEntitlements({ plans, license: result.valid ? result.license : null })
entitlements.has("export")