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

@alternitis-corp/liveness

v0.6.1

Published

Embedded, browser-based liveness check — Face-ID-style guided head-turn via MediaPipe FaceLandmarker. Framework-agnostic core + React & Vue wrappers + a script-tag global build.

Readme

@alternitis-corp/liveness

Embedded, browser-based ACTIVE liveness check with a Face‑ID‑style scan ring. It guides the user through an ordered, one‑at‑a‑time sequence — turn left → turn right → look up → look down → blink → open mouth — where each head step lights only its own arc of the ring (left arc turning left, top arc looking up, …), captures the face from multiple angles, and hands you the frames.

Yaw (left/right) and pitch (up/down) are measured from translation‑invariant face landmarks (via Google MediaPipe FaceLandmarker), so panning or shaking the device does not advance it — only a real head turn does. Blink and mouth‑open come from MediaPipe face blendshapes (eyeBlinkLeft/Right, jawOpen), with a landmark EAR/MAR fallback. A photo, a static dummy head, or a naïve replay can’t satisfy the active challenges. Deliberate, smooth, and yields a detailed multi‑angle set you still verify server‑side.

  • 🛡️ Active liveness — ordered turn / look‑up‑down / blink / mouth challenges, each lighting its own ring arc, defeat photos & replays
  • 🎯 Framework‑agnostic core (plain DOM) — works in React, Vue, Svelte, Angular, vanilla, Expo Web…
  • ⚛️ First‑class wrappers for React and Vue, plus a <script> global build (no bundler needed)
  • 📦 Zero runtime dependencies — the MediaPipe model + WASM load lazily from a CDN (overridable)
  • 🔒 Runs entirely client‑side; you decide what to do with the captured frames
  • 🪶 Renders its own live video + animated ring; you supply the surrounding UI and instruction text

Install

npm install @alternitis-corp/liveness

Requires a secure context. getUserMedia only works over HTTPS (or localhost). On first use the browser downloads the MediaPipe face model (~13 MB) and caches it. Feature‑detect with isLivenessSupported().


Usage

React

import { LivenessCamera } from '@alternitis-corp/liveness/react';

export function Step() {
  return (
    <LivenessCamera
      size={260}
      turnThreshold={0.16}                       // higher = the user must turn further
      onPrompt={(p) => setHint(promptText[p])}   // 'center' | 'turn-left' | 'turn-right' | 'hold' | 'complete'
      onProgress={(p) => {}}                      // 0..1 ring fill
      onComplete={(frames) => upload(frames)}     // JPEG data URLs across the head angles
      onError={(e) => alert(e.message)}
    />
  );
}

Vue 3

<script setup lang="ts">
import { LivenessCamera } from '@alternitis-corp/liveness/vue';
function onFrames(frames: string[]) { upload(frames); }
</script>

<template>
  <LivenessCamera :turn-threshold="0.16" @prompt="setHint" @complete="onFrames" @error="onError" />
</template>

Vanilla / any framework (the core)

Use the core class directly on any square element — this is how you integrate with Svelte, Angular, Solid, Expo Web, or no framework at all:

import { LivenessCheck, isLivenessSupported } from '@alternitis-corp/liveness';

if (!isLivenessSupported()) {
  // show an "open over HTTPS / allow camera" message and bail
}

const check = new LivenessCheck(document.getElementById('camera')!, {
  turnThreshold: 0.16,
  onPrompt: (p) => (hint.textContent = p),
  onProgress: (p) => (bar.style.width = `${p * 100}%`),
  onComplete: (frames) => {
    fetch('/api/liveness', { method: 'POST', body: JSON.stringify({ frames }) });
  },
  onError: (e) => console.error(e),
});
check.start();
// later / on unmount:
check.stop();

Plain <script> tag (global build, no bundler)

<div id="camera" style="width:260px;height:260px"></div>
<script src="https://unpkg.com/@alternitis-corp/liveness/dist/liveness.global.js"></script>
<script>
  const check = new Liveness.LivenessCheck(document.getElementById('camera'), {
    onComplete: (frames) => console.log('captured', frames.length),
  });
  check.start();
</script>

React Native

  • Expo Web / React‑Native‑Web: supported — render a host View, grab its DOM node, and use the core (new LivenessCheck(node, …)). (That’s exactly how the Trufy app uses it.)
  • Native iOS/Android React Native: not supported — there’s no DOM or getUserMedia. Native apps need a native camera + on‑device ML (e.g. react-native-vision-camera + a face model). This package targets the web.

The guided flow

The check walks the user through the ordered sequence and reports each step via onPrompt:

| Prompt | Show your own copy | | --- | --- | | center | "Center your face in the circle" | | turn-left | "Slowly turn your head to the left" | | turn-right | "Now slowly turn to the right" | | look-up | "Now tilt your head up" | | look-down | "And tilt your head down" | | blink | "Blink your eyes" | | open-mouth | "Open your mouth" | | hold | "Hold still…" (finishing up) | | complete | done — onComplete(frames) fires |

The steps run in order, one at a time (set randomizeChallenges to shuffle them for anti‑replay), and each head step fills only its own ring arc. It completes once every step is cleared, with frames captured across the angles and a minimum duration elapsed — so it can’t be rushed.


Options

| Option | Default | Description | | --- | --- | --- | | size | 260 | Diameter of the camera circle, px | | turnThreshold | 0.16 | Yaw magnitude per side (~0–0.5) required for a full turn — higher = turn further | | pitchThreshold | 0.04 | Pitch deviation from neutral required for a clear look up / down | | invertPitch | false | Flip up/down if a camera reports pitch inverted | | challenges | ['turn-left','turn-right','look-up','look-down','blink','open-mouth'] | The ordered challenges, one at a time | | randomizeChallenges | false | Shuffle the challenge order each run (anti-replay) | | targetFrames | 9 | Frames captured across the flow (multi‑angle set) | | minDurationMs | 4000 | Minimum run time before completing — stops it finishing too fast | | ringColor | #5b4dff | Lit‑tick colour | | ringTrackColor | rgba(20,20,40,0.10) | Unlit‑tick colour | | ringWidth | 5 | Tick stroke width, px | | mirror | true | Mirror the video (selfie view) | | attribution | Powered by Alternitis Corp | Caption shown at the bottom of the camera; set "" to hide | | jpegQuality | 0.9 | Captured‑frame JPEG quality | | model | CDN | { esm, wasm, model } URL overrides (e.g. to self‑host the MediaPipe assets) |

Callbacks

  • onPhase(phase)'starting' → 'loading' → 'searching' → 'live' → 'complete' (or 'error')
  • onPrompt(prompt) — step guidance (see table above)
  • onProgress(0..1) — ring fill
  • onComplete(frames: string[]) — JPEG data URLs from centre/left/right angles once the check passes
  • onError(error) — no secure context, camera blocked, or model failed to load

What you get & verifying it

onComplete gives you a multi‑angle set of full‑resolution JPEG frames (data URLs). The active challenges (head sweep + randomised blink / mouth / up / down) make a photo, a static dummy head, or a naïve replay fail — but client‑side liveness still runs on an untrusted device and is not a substitute for server‑side verification or a dedicated PAD provider against a determined attacker. Pair the frames with a server‑side check — a vision model and/or a human reviewer (e.g. compare the straight‑on frame to a government‑ID photo), or a purpose‑built liveness vendor — for the actual decision.

Self‑hosting the model

To avoid the CDN at runtime, host the MediaPipe assets yourself and pass model:

new LivenessCheck(el, {
  model: {
    esm: '/vendor/tasks-vision/vision_bundle.mjs',
    wasm: '/vendor/tasks-vision/wasm',
    model: '/vendor/face_landmarker.task',
  },
});

Browser support

Any modern browser with getUserMedia over HTTPS and WebAssembly: Chrome/Edge, Safari (incl. iOS 16+), Firefox. MediaPipe runs via WASM (+ WebGL where available).


Develop / build

npm install
npm run build       # tsc → dist (ESM + .d.ts) plus the IIFE global (dist/liveness.global.js)
npm run typecheck

Publishing (maintainers)

Scoped public package. Own the alternitis-corp npm org, then from this repo:

npm version patch | minor | major
npm publish --access public          # or push a v* tag if NPM_TOKEN is set for the CI workflow