npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@velkin/license

v0.1.1

Published

Runtime license validation for Velkin Pro

Readme

@velkin/license

Runtime license validation for Velkin Pro. Invalid or missing keys show watermarks and console warnings only; components are not hard-blocked.

import { LicenseInfo } from "@velkin/license";

// Vite example. Use NEXT_PUBLIC_VELKIN_LICENSE_KEY in a Next.js client module.
LicenseInfo.setLicenseKey(import.meta.env.VITE_VELKIN_LICENSE_KEY ?? "");

The key must reach browser code and is therefore not a server secret. Keep it out of public source control and use a domain-scoped license where possible.

Plans

| Plan | Key required | Seats | |------|--------------|-------| | Free (MIT @velkin/ui) | No | — | | Pro | Yes | 1 | | Team | Yes | 5 | | Enterprise | Yes (contract) | Unlimited |

Key format

VLK2.<base64url(payload)>.<base64url(ed25519-signature)>

Payload: { v: 2, plan, seats, exp, org?, trial? } where exp is cover-until (subscription end).

New keys also contain kid, jti, and iat. Verification uses a public-key ring so signing keys can rotate without immediately breaking previously issued keys. Missing kid is rejected.

Clients also fetch live public keys from Official (GET /api/v1/license/keys) so Velkin can rotate the signing private key on the server without republishing this package. Baked keys remain as offline fallback; remote keys merge into the runtime ring (cached in localStorage).

// Default keysEndpoint is https://velkinui.com/api/v1/license/keys
LicenseInfo.configure({
  syncEndpoint: "https://velkinui.com/api/v1/license/check",
  keysEndpoint: "https://velkinui.com/api/v1/license/keys",
});

Version lock

When a Pro build release timestamp is registered (baked at publish via pro-release-at.generated.ts):

  • Build released on or before exp → remains valid for that build
  • Build released after exp → status package_too_new (watermark) until renewal
  • Trial keys always calendar-expire
  • Renewal mints a new key with a later exp — replace VELKIN_LICENSE_KEY / NEXT_PUBLIC_VELKIN_LICENSE_KEY. The previous key still unlocks builds released before its exp.

Revocation and domains (soft DRM)

Validation is offline-first via the embedded public key. After a valid key with a jti is loaded, the package makes a best-effort request to https://velkinui.com/api/v1/license/check (or your configured endpoint). It sends only the non-secret license identifier.

  • Same session: if the endpoint reports revoked, status flips to revoked immediately and Pro watermarks re-apply via LicenseInfo.subscribe (no reload required).
  • Recheck: throttled to about once per hour per tab; also rechecks when the document becomes visible again (long-lived SPAs).
  • Fail open: network, storage, timeout, and CSP failures never block rendering and leave a cryptographically valid offline key as valid.
  • Domains: optional signed domains use exact hostnames or *.example.com patterns. In the browser the current hostname is checked; during SSR, NEXT_PUBLIC_SITE_URL / VERCEL_URL are used when present.
// Optional: self-host the status endpoint or disable background checks.
LicenseInfo.configure({ syncEndpoint: "https://licenses.example.com/v1/check" });
LicenseInfo.configure({ syncEndpoint: "" });

// Optional: force-refresh public keys after a server-side rotation.
await LicenseInfo.refreshPublicKeys();

// Optional: react when status changes (guards do this automatically).
const stop = LicenseInfo.subscribe((status) => {
  console.log("license status", status);
});
stop();

Seats in the payload are contract metadata, not a runtime counter. See https://velkinui.com/license.