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

@kindlyhuman/snippet

v0.4.1

Published

Embeddable Kindly Human floating snippet widget (framework-agnostic script + optional React)

Readme

@kindlyhuman/snippet

Embeddable Kindly Human floating snippet (launcher + modal). Configuration is loaded from the backend so copy and CTAs can be changed without redeploying the host site.

Plain HTML (no bundler)

Paste one script tag (hosted on your CDN after yarn build). Use data-snippet-id and data-api-base-url so the widget initializes automatically:

<script
  src="https://cdn.kindlyhuman.io/snippet/v1/kindly-snippet.iife.js"
  defer
  data-snippet-id="YOUR_SNIPPET_ID"
  data-api-base-url="https://api.example.com"
></script>

Alternatively, load the script and call init yourself:

<script src="https://cdn.kindlyhuman.io/snippet/v1/kindly-snippet.iife.js" defer></script>
<script>
  window.addEventListener("DOMContentLoaded", function () {
    window.KindlySnippet.init({
      snippetId: "YOUR_SNIPPET_ID",
      apiBaseUrl: "https://api.example.com",
    });
  });
</script>
  • apiBaseUrl must be the origin only (no trailing slash required); the client requests GET {apiBaseUrl}/api/v3/public/kindly-snippet/config?snippet_id=… with Accept: application/json.
  • Destroy a specific instance: handle.destroy(), or destroy all: window.KindlySnippet.destroy().

npm (React, Vite, Next.js, …)

yarn add @kindlyhuman/snippet
import { KindlySnippet } from "@kindlyhuman/snippet/react";

export function App() {
  return (
    <>
      <YourApp />
      <KindlySnippet snippetId="YOUR_SNIPPET_ID" apiBaseUrl={import.meta.env.VITE_API_BASE_URL} />
    </>
  );
}

Core API (any bundler):

import { init, destroy } from "@kindlyhuman/snippet";

const handle = init({ snippetId: "YOUR_SNIPPET_ID", apiBaseUrl: "https://api.example.com" });
// handle.destroy();

Local demo

Defaults in demo/.env target snippet_id christian_group_1 against http://127.0.0.1:5001 (local docker nginx → API).

Seed one or more snippets first from backend/:

./manage.py dev _upsert_kindly_snippet_embed --client-name "Christian Group" --snippet-id "christian_group_1" --video-filename "video_1.mp4"
./manage.py dev _upsert_kindly_snippet_embed --client-name "Christian Group" --snippet-id "christian_group_2" --video-filename "video_2.mp4"
# Optional modal placeholder (copy image into UPLOADED_IMAGES_DEST, e.g. build/assets/images):
./manage.py dev _upsert_kindly_snippet_embed --client-name "Christian Group" --snippet-id "christian_group_1" --video-filename "video_1.mp4" --modal-poster-filename "modal-poster.webp"

Generate a poster from the first frame of a modal video (requires ffmpeg):

cd kindly-snippet
chmod +x scripts/extract-video-frame.sh
./scripts/extract-video-frame.sh /path/to/modal.mp4 video_1-poster.webp
# or: yarn extract-poster /path/to/modal.mp4 video_1-poster.webp
cp video_1-poster.webp ../backend/build/assets/images/   # local UPLOADED_IMAGES_DEST

Then set VITE_SNIPPET_ID in demo/.env or demo/.env.local to whichever snippet you want to preview (for example christian_group_1 or christian_group_2).

Then:

cd kindly-snippet
yarn install
yarn dev

Use demo/.env.local to override (see demo/.env.local.example).

Example app consuming npm package

To verify the published package works end-to-end via npm install / yarn add, see examples/npm-react-vite.

CI and npm releases (maintainers)

The package is @kindlyhuman/snippet, published to the public npm registry (publishConfig.access: public), not the GitLab package registry.

  1. On npmjs.com, configure Trusted publishing for @kindlyhuman/snippet using GitLab CI/CD (OIDC). The CI file path must match .gitlab-ci.yml exactly.
  2. CI publishes on version tags (e.g. v0.1.0) by running yarn build then npm publish --access public.
  3. Ensure the npm org @kindlyhuman allows this package and the token’s user (or automation user) has publish access.

The component-library repo publishes to GitLab’s npm registry with CI_JOB_TOKEN and publishConfig.access: restricted; this repo intentionally differs so external client sites can npm install / yarn add without GitLab auth.

Build

From this directory:

yarn build

Outputs:

  • dist/kindly-snippet.iife.js — single file for <script src="…"> (includes React).
  • dist/index.mjs / dist/index.cjsinit / destroy (React as peer dependency).
  • dist/react/index.mjs / dist/react/index.cjs<KindlySnippet /> wrapper.

Backend: snippet_embeds

Snippet configs are stored per row in snippet_embeds (client_id FK to clients, unique public snippet_id, enabled, and JSON configuration). The public endpoint returns 404 unless:

  • the snippet exists and enabled is true
  • the owning client is active and non-archived
  • required fields are present in configuration

| Field | Required | Description | | --- | --- | --- | | tagline | yes | Modal subheadline | | tease_text | yes | Text on launcher hover (e.g. “I’ve been there.”) | | show_online_indicator | no | Default false; shows pulsing green dot on launcher | | teaser_video_url | yes | URL for small launcher video (muted, loop) | | teaser_poster_url | no | Poster for launcher video | | modal_video_url | yes | URL for modal video | | modal_poster_url | no | Poster for modal video | | primary_cta_label | yes | Primary button label | | primary_cta_url | yes | Primary button URL (https) | | secondary_cta_label | yes | Secondary button label | | secondary_cta_url | yes | Secondary button URL | | client_portal_base_url | yes | Client portal / benefits base URL (used for analytics or future links) | | logo_url | no | Absolute URL of a PNG/SVG/WebP wordmark for the modal header; omit or null for the default Kindly Human SVG |

The widget resolves the snippet with snippet_id.