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

devlock-client

v1.1.1

Published

DevLock Frontend SDK for React, Next.js, and Vanilla JS. Integrate license validation, remote kill-switch, feature flags, and domain locking into your web applications securely.

Readme

devlock-client

Frontend SDK for DevLock — License enforcement, remote management, and developer protection for web applications.

npm version License: MIT

🌐 Website & Dashboard: devlock.tashanto.com · 🖥️ Backend SDK: devlock-sdk

Fail-safe by design. If DevLock's servers are ever unreachable, this SDK never throws and never blocks your app — your website keeps running smoothly. See Fail-open behavior.

Features

  • 🔐 License Validation — Verify licenses with HMAC-signed requests
  • 🚀 Real-Time Updates — WebSocket-powered kill-switch, maintenance mode, feature flags
  • 🌐 Domain Locking — Prevent unauthorized redistribution
  • 🏴 Feature Flags — Toggle features instantly across all deployments
  • 📡 Offline Support — Cryptographically signed offline tokens with grace period
  • 🛡️ Tamper Detection — Detect SDK manipulation attempts
  • 💧 Watermark Injection — Show watermark for invalid licenses
  • 🔔 Remote Notifications — Push messages to deployed apps
  • Kill Switch — Instantly disable applications remotely
  • 🔧 Maintenance Mode — Show maintenance messages without redeploying

Framework Support

| Framework | Import Path | |-----------|-------------| | Vanilla JS/TS | devlock-client | | React | devlock-client/react | | Next.js | devlock-client/next | | Vue 3 | devlock-client/vue |

Installation

npm install devlock-client
# or
yarn add devlock-client
# or
pnpm add devlock-client

Setup & Dashboard

Before using the SDK, you need to create a project and obtain your keys from the DevLock Dashboard:

  1. Go to DevLock Dashboard.
  2. Sign in and navigate to the Projects section.
  3. Click Create Project and fill in your details.
  4. Copy your Project Public Key (pk_live_...). This is safe to expose in your frontend.
  5. (Optional) Generate a License Key for your users from the Licenses page.

Recommended .env setup (Vite)

VITE_DEVLOCK_PROJECT_KEY=pk_live_your_public_key_here
VITE_DEVLOCK_LICENSE_KEY=DLCK-XXXX-XXXX-XXXX-XXXX

For Next.js:

NEXT_PUBLIC_DEVLOCK_PROJECT_KEY=pk_live_your_public_key_here
NEXT_PUBLIC_DEVLOCK_LICENSE_KEY=DLCK-XXXX-XXXX-XXXX-XXXX

Quick Start

Vanilla TypeScript / JavaScript

import { DevLock } from 'devlock-client';

const devlock = new DevLock({
  projectKey: 'pk_live_your_project_key',
  licenseKey: 'DLCK-XXXX-XXXX-XXXX-XXXX',
  on: {
    onReady: (state) => console.log('DevLock ready:', state),
    onKillSwitch: (reason) => showBlockedUI(reason),
    onMaintenanceMode: (config) => showMaintenance(config.message),
    onLicenseSuspended: (reason) => showSuspendedUI(reason),
    onFeatureToggle: (flag, enabled) => updateFeature(flag, enabled),
    onNotification: (notif) => showToast(notif.message),
  },
});

await devlock.init();

// Check feature flags
if (devlock.isFeatureEnabled('premium-export')) {
  showPremiumFeature();
}

// Check license status
if (devlock.isLicenseValid()) {
  // Full access
}

// Track custom events
devlock.track('export_clicked', { format: 'pdf' });

React

import { DevLockProvider, useDevLock, useFeatureFlag } from 'devlock-client/react';

// Wrap your app in main.tsx or App.tsx
function App() {
  return (
    <DevLockProvider
      config={{
        projectKey: import.meta.env.VITE_DEVLOCK_PROJECT_KEY,
        licenseKey: import.meta.env.VITE_DEVLOCK_LICENSE_KEY,
      }}
    >
      <MyApp />
    </DevLockProvider>
  );
}

// Use in components
function Dashboard() {
  const { state, isReady } = useDevLock();
  const isPremium = useFeatureFlag('premium');

  if (state.maintenance.enabled) {
    return <MaintenancePage message={state.maintenance.message} />;
  }

  if (state.killSwitch.enabled) {
    return <BlockedPage reason={state.killSwitch.reason} />;
  }

  return (
    <div>
      <h1>Dashboard</h1>
      {isPremium && <PremiumWidget />}
    </div>
  );
}

Next.js

// app/providers.tsx
'use client';
import { DevLockProvider } from 'devlock-client/next';

export function Providers({ children }: { children: React.ReactNode }) {
  return (
    <DevLockProvider
      config={{
        projectKey: process.env.NEXT_PUBLIC_DEVLOCK_PROJECT_KEY!,
        licenseKey: process.env.NEXT_PUBLIC_DEVLOCK_LICENSE_KEY,
      }}
    >
      {children}
    </DevLockProvider>
  );
}

Vue 3

import { createApp } from 'vue';
import { DevLockPlugin } from 'devlock-client/vue';

const app = createApp(App);

app.use(DevLockPlugin, {
  projectKey: 'pk_live_your_project_key',
  licenseKey: 'DLCK-XXXX-XXXX-XXXX-XXXX',
});

// In components
import { useDevLock, useFeatureFlag } from 'devlock-client/vue';

const { state, isReady } = useDevLock();
const isPremium = useFeatureFlag('premium');

Configuration

const devlock = new DevLock({
  // Required
  projectKey: 'pk_live_xxx',                    // Public key from Dashboard

  // Optional
  licenseKey: 'DLCK-XXXX-XXXX-XXXX-XXXX',      // User or app license key
  apiUrl: 'https://dl-api.tashanto.com',         // Custom API URL (don't set unless self-hosting)
  wsUrl: 'wss://dl-ws.tashanto.com',             // Custom WebSocket URL
  environment: 'production',                     // 'production' | 'staging' | 'development'
  debug: false,                                  // Enable console logging (useful in development)
  offlineGraceHours: 72,                        // Hours to allow offline operation
  heartbeatInterval: 30000,                     // Heartbeat interval (ms)
  tamperDetection: true,                        // Enable tamper detection
  watermark: false,                             // Show watermark when license invalid
  watermarkText: 'UNLICENSED',                 // Custom watermark text
  failBehavior: 'open',                         // 'open' (default) | 'closed'
});

API Reference

DevLock Class

| Method | Returns | Description | |--------|---------|-------------| | init() | Promise<DevLockState> | Initialize SDK, validate license, connect WebSocket | | isFeatureEnabled(flag) | boolean | Check if a feature flag is enabled | | isLicenseValid() | boolean | Check if license is valid | | isMaintenanceMode() | boolean | Check if maintenance mode is active | | isKillSwitchActive() | boolean | Check if kill switch is active | | getState() | DevLockState | Get current SDK state | | getLicense() | LicenseInfo | Get license information | | getConfig(key, default) | T | Get remote config value | | track(event, metadata) | void | Track a telemetry event | | revalidate() | Promise<DevLockState> | Force re-validation | | on(event, handler) | () => void | Subscribe to events (returns unsubscribe) | | destroy() | void | Cleanup all resources |

Events

| Event | Payload | Description | |-------|---------|-------------| | ready | DevLockState | SDK initialized | | license:valid | LicenseInfo | License validated successfully | | license:invalid | string | License validation failed | | license:suspended | string | License suspended (reason) | | maintenance:enabled | MaintenanceConfig | Maintenance mode activated | | maintenance:disabled | — | Maintenance mode deactivated | | killswitch:activated | { reason } | Kill switch activated | | killswitch:deactivated | — | Kill switch deactivated | | feature:toggled | flag, enabled | Feature flag changed | | notification:push | Notification | New notification received | | connection:change | boolean | WebSocket connection state | | tamper:detected | string | Tampering detected |

Offline Support

The SDK automatically caches validation results and supports offline operation:

  1. On successful validation, response is cached locally
  2. If network is unavailable, cached result is used
  3. Grace period (default 72h) determines how long offline is allowed
  4. After grace period expires, license is considered invalid
  5. On reconnection, SDK automatically revalidates

Fail-open behavior

🔒 The safety guarantee

Your website locks ONLY when you explicitly lock it from the DevLock dashboard. A DevLock outage, a network/API error, a request timeout, a malformed response, or the SDK itself failing will never lock, block, or crash your site. Errors always resolve to unlocked. A lock is applied only when the server explicitly reports enabled: true for a kill-switch or maintenance state that you turned on.

DevLock is a safety layer for your app — it must never become a single point of failure. If DevLock's servers are unreachable and there is no usable cache, the SDK does not throw and does not block rendering. init() resolves in a permissive offline state and your application keeps running exactly as normal.

Concretely, the SDK guarantees:

  • init() never rejects when failBehavior is 'open' (the default).
  • Every server response is parsed defensively — missing or malformed fields can never crash your app and can never flip the app into a locked state.
  • A kill-switch / maintenance lock requires an explicit enabled === true from the server. Anything else (undefined, garbage, HTTP error, unreachable) is treated as unlocked.
const devlock = new DevLock({
  projectKey: 'pk_live_xxx',
  // failBehavior: 'open',  // default — never break the host app
  // failBehavior: 'closed', // opt in to hard-failing if you *want* to block
});

await devlock.init(); // never rejects when failBehavior is 'open'

Enforcement signals (kill-switch, suspension, maintenance) are still delivered and cached — once received they persist across reloads, so an offline period cannot be used to bypass a lock that was already issued.

Local Development & Testing

When you integrate the SDK into a local project (e.g., http://localhost:5173), you can test it directly against your production DevLock account.

  1. No URL changes needed: Do not set apiUrl or wsUrl locally. The SDK automatically connects to the production DevLock servers.
  2. Domain Lock: If you have enabled Domain Lock in your DevLock Dashboard, add localhost or 127.0.0.1 to the Allowed Domains list. An empty list allows all domains by default.
  3. Enable debug mode during development to see logs in the browser console:
    config={{ projectKey: '...', debug: true }}
  4. CORS: The DevLock API server (dl-api.tashanto.com) accepts requests from any origin by default. If you are self-hosting DevLock, ensure your server allows your frontend domain.

Links

License

MIT


Built by Md Tanvir Ahamed Shanto · devlock.tashanto.com