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

@kernaq/verify-web

v2.0.2

Published

Drop-in KYC verification UI for web — customizable Web Component for document capture, selfie, and liveness.

Readme

@kernaq/verify

Drop-in KYC verification Web Component for Kernaq Identity. One HTML tag — handles document capture (front + back), auto selfie, and liveness challenges. Works with any framework or plain HTML.

Install

npm install @kernaq/verify

Or load from CDN (no install needed):

<script src="https://cdn.kernaq.com/verify@2/verify.js"></script>

Quick start

<kernaq-verify
  api-key="k_test_your_key"
  country="KEN"
  reference="user_abc123"
  document-type="national_id"
></kernaq-verify>

<script>
  document.querySelector('kernaq-verify')
    .addEventListener('kernaq:complete', e => {
      console.log(e.detail.verdict)    // 'pass' | 'fail' | 'review'
      console.log(e.detail.score)      // 0–100
      console.log(e.detail.faceMatch)  // boolean
      console.log(e.detail.isLive)     // boolean
    })
</script>

Or via JavaScript API:

import '@kernaq/verify'

const widget = document.querySelector('kernaq-verify')
widget.open({
  apiKey: 'k_test_your_key',
  country: 'KEN',
  reference: 'user_abc123',
  documentType: 'national_id',
})
widget.addEventListener('kernaq:complete', e => console.log(e.detail))

HTML attributes

| Attribute | Type | Default | Description | |---|---|---|---| | api-key | string | — | Your Kernaq API key (k_test_... or k_live_...) | | backend-url | string | — | Backend proxy URL — use this instead of api-key in production | | document-type | string | national_id | Document type the user will scan. One of: national_id, passport, driver_license, alien_card | | country | string | KEN | ISO 3166-1 alpha-3 country code | | reference | string | auto | Your internal user or session ID | | sandbox | boolean attr | false | Sandbox mode — no billing, test responses | | steps | string | document,selfie,liveness | Comma-separated subset of steps to run. Any combination of document, selfie, liveness | | liveness-tasks | number | 2 | Number of liveness challenges to present (1–5) | | blur-threshold | number | 35 | Minimum blur score to accept a capture (lower = more lenient) | | theme-mode | light | dark | light | Colour scheme | | accent-color | string | #111827 | Primary button and highlight colour |

JavaScript API

// Open with config override
widget.open({
  apiKey: 'k_test_...',
  country: 'KEN',
  reference: 'user_abc',
  documentType: 'passport',
  steps: ['selfie', 'liveness'],        // run only these steps
  livenessTaskCount: 3,
  blurThreshold: 40,
  theme: {
    mode: 'dark',
    accentColor: '#6366f1',
    backgroundColor: '#0f0f0f',
    borderRadius: '16px',
  },
  locale: {
    intro_title: 'Thibitisha utambulisho wako',
    intro_cta: 'Anza',
  },
})

// Close and reset
widget.close()

Steps — run only what you need

By default all three steps run. Pass steps to run a subset:

<!-- Document scan only -->
<kernaq-verify
  api-key="k_test_..."
  document-type="passport"
  steps="document"
></kernaq-verify>

<!-- Selfie + liveness only (no document) -->
<kernaq-verify
  api-key="k_test_..."
  steps="selfie,liveness"
></kernaq-verify>

<!-- Liveness only -->
<kernaq-verify
  api-key="k_test_..."
  steps="liveness"
></kernaq-verify>

Events

const widget = document.querySelector('kernaq-verify')

// Verification completed
widget.addEventListener('kernaq:complete', e => {
  const result = e.detail
  // result.verificationId — string
  // result.reference      — string (your reference)
  // result.verdict        — 'pass' | 'fail' | 'review'
  // result.score          — 0–100 risk score (0 = lowest risk)
  // result.faceMatch      — boolean
  // result.isLive         — boolean
  // result.documentFields — { name, date_of_birth, document_number, ... }
})

// User cancelled (only fires if developer calls widget.close() programmatically)
widget.addEventListener('kernaq:cancel', () => { ... })

// Step changed
widget.addEventListener('kernaq:step', e => {
  console.log(e.detail.step)
  // 'intro' | 'doc-front' | 'doc-back' | 'selfie' | 'liveness' | 'processing' | 'result'
})

Theming

All theme values are CSS custom properties set on the host element:

<kernaq-verify
  api-key="k_test_..."
  theme-mode="dark"
  accent-color="#6366f1"
  style="--kernaq-border-radius: 20px; --kernaq-font-family: 'Inter', sans-serif;"
></kernaq-verify>

| CSS variable | Description | |---|---| | --kernaq-accent-color | Primary colour (buttons, active oval) | | --kernaq-background-color | Modal background | | --kernaq-text-color | Primary text | | --kernaq-border-radius | Corner radius for modal and buttons | | --kernaq-font-family | Font family |

Localisation

Override any displayed string via the JavaScript API:

widget.open({
  apiKey: 'k_test_...',
  locale: {
    intro_title:         'Thibitisha utambulisho wako',
    intro_body:          'Hii itachukua sekunde 90.',
    intro_cta:           'Anza',
    doc_front_title:     'Hati — mbele',
    doc_back_title:      'Hati — nyuma',
    selfie_title:        'Picha ya uso',
    liveness_title:      'Uthibitisho wa uhai',
    result_pass_title:   'Umefaulu',
    result_fail_title:   'Imeshindwa',
  },
})

All locale keys

| Key | Default | |---|---| | intro_title | Verify your identity | | intro_body | This takes about 90 seconds… | | intro_cta | Get started | | doc_front_title | Document — front | | doc_front_instruction | Hold the front of your document… | | doc_back_title | Document — back | | doc_back_instruction | Flip your document over… | | doc_capture_btn | Capture | | doc_retake_btn | Retake | | selfie_title | Selfie | | selfie_instruction | Centre your face inside the oval… | | liveness_title | Liveness check | | liveness_ready | Follow the instructions as they appear | | liveness_complete | Hold still… | | processing_title | Verifying… | | result_pass_title | Identity verified | | result_pass_body | Your verification was successful | | result_fail_title | Verification failed | | result_fail_body | We could not verify your identity… | | result_review_title | Under review | | result_review_body | Your submission is being reviewed… | | error_camera_denied | Camera access denied… | | error_blur | Image is too blurry… | | error_network | Network error… |

Backend proxy (recommended for production)

Never expose a live key in frontend code. Route through your server instead:

<kernaq-verify
  backend-url="https://api.yourapp.com/kyc/verify"
  country="KEN"
  reference="user_abc"
></kernaq-verify>

Your endpoint receives multipart/form-data with:

| Field | Description | |---|---| | doc_front | Front of document (JPEG) | | doc_back | Back of document (JPEG) | | selfie | Selfie photo (JPEG) | | document_type | national_id | passport | driver_license | alien_card | | country | ISO 3166-1 alpha-3 | | reference | Your reference string |

Forward to POST https://api.identity.kernaq.com/v1/verify with your secret key in X-API-Key.

User flow

The widget walks users through these steps in order (configurable via steps):

  1. Intro — privacy notice and get started button
  2. Document front — camera with corner bracket guides, blur/brightness check before accepting
  3. Document back — same, shows thumbnail of front as confirmation
  4. Selfie — auto-captures when face is centred, well-lit, sharp, and no glasses glare. Live guidance pill shows actionable feedback
  5. Liveness — 2 randomised challenges (blink, turn left/right, nod, open mouth) shown as overlay on the camera feed
  6. Processing — submits to API
  7. Result — verdict, risk score, face match, liveness status. On fail: retry option

The user cannot dismiss the widget — the developer controls visibility. On pass/review the kernaq:complete event fires and the developer removes or hides the element.

Browser support

All modern browsers (Chrome 80+, Firefox 78+, Safari 14+, Edge 80+). Requires:

  • getUserMedia (camera access)
  • MediaRecorder (liveness video)
  • Shadow DOM (Web Components)

Links