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

@liip/liipgpt

v3.19.1

Published

LiipGPT Chat and Library

Downloads

12,995

Readme

LiipGPT Chat & Library

This package provides the following:

  1. A web component for embedding the LiipGPT chat UI (<liipgpt-chat>)
  2. A web component for embedding the LiipGPT button as a link (<liipgpt-button>)
  3. A one-shot search summary web component (<liipgpt-search-summary>)
  4. A client library for interacting with the LiipGPT API

Embed

<!-- Chat -->
<script type="module" src="https://cdn.example.com/@liip/liipgpt/chat/liipgpt-chat.js"></script>
<liipgpt-chat api-url="https://your-api.example.com/org" lang="en"></liipgpt-chat>

<!-- Button -->
<script type="module" src="https://cdn.example.com/@liip/liipgpt/button/liipgpt-button.js"></script>
<liipgpt-button api-url="https://your-api.example.com/org" lang="en"></liipgpt-button>

<!-- Search summary -->
<script type="module" src="https://cdn.example.com/@liip/liipgpt/search-summary/liipgpt-search-summary.js"></script>
<h2 id="ai-overview">AI overview</h2>
<liipgpt-search-summary
    labelled-by="ai-overview"
    question="What can you tell me about your services?"
    api-url="https://your-api.example.com/org"
    lang="en"
    height="280"
></liipgpt-search-summary>

The module build is the recommended one, and the one to reach for unless something below rules it out. Only a module can load code on demand, and that is most of what a widget ships: a chat flyout that is never opened now downloads about a quarter of what it used to.

| gzipped, what a browser downloads before any interaction | IIFE | module | | -------------------------------------------------------- | -------- | -------------------- | | chat, flyout never opened | 202.0 kB | 52.4 kB | | button | 48.8 kB | 40.2 kB | | search summary, styled through host CSS | 88.0 kB | 69.0 kB |

The rest arrives when it is actually needed — the chat panel and engine on first open (prefetched on hover, so the click stays instant), a language when it is selected, an embed when the backend sends one. Only the language the visitor sees is ever downloaded, not all four.

Importing from npm resolves to the module build as well, so import "@liip/liipgpt/search-summary" registers the element and gives you the named exports (LiipGPTSearchSummary, PiiChecks) — with the IIFE the namespace came back empty. require() still resolves to the IIFE.

Three things to check:

  • Content-Security-Policy — a module can load additional files from the host it was served from, and that host is cdn.jsdelivr.net for both embed variants: the fixed CDN URL points there directly, and the backend's /cdn/npm route redirects there. The on-demand files are imported relative to the entry, so they resolve against jsdelivr in either case. Add https://cdn.jsdelivr.net to your script-src — also when the script tag points at your own domain — or the widget will fail to load.
  • Pin the version. Serve the module from a version-pinned URL. With a floating "latest" URL a release can land between the entry and its companion files being fetched, and the two no longer match.
  • Serve the whole directory if you self-host. The entry is no longer the only file: it ships alongside content-hashed companions (chat-panel-*.js, de-*.js, …) that it fetches at runtime. Copying only liipgpt-chat.js to your own server gives you a button that never opens a chat.

IIFE build (single file)

Every widget is also published as a single-file IIFE bundle, and it stays supported — existing embeds do not have to migrate. Drop type="module" and add .iife to the file name:

<script src="https://cdn.example.com/@liip/liipgpt/chat/liipgpt-chat.iife.js" crossorigin="anonymous"></script>

It cannot code-split, so it always downloads everything upfront, including all four languages. Use it when you need Subresource Integrity: SRI covers only the file you name in the tag, so with a module the on-demand companions are not integrity-checked, while the IIFE is the whole widget. It is also the simpler answer for a site that cannot add cdn.jsdelivr.net to its script-src.

Keep crossorigin="anonymous" on the IIFE tag. Without it, the browser hides every error of a script from another origin behind a bare "Script error.", and the widget cannot report its own errors to the backend. Module scripts are always loaded that way, so they need nothing extra. Either way, a script from another origin then runs only if its server sends Access-Control-Allow-Origin. jsDelivr and the API's /cdn/npm route do; a self-hosted copy on another origin needs that header too, or the widget does not load at all.

Error reporting

The widgets send errors in their own code — crashes, chat streams that end without an answer, server errors of the API — to <api-url>/frontend-errors, so they show up in the backend's monitoring. A report holds the error, the page's origin and path (never its query string or what the visitor typed) and the last few widget steps. The backend decides per site: until a site opts in (frontendErrors.widgets.enabled), its chat config says reportErrors: false and the widget sends nothing. On a site that opted in, an embed can opt out with reportErrors: false in window.CHAT_CONFIG_OVERRIDE; true there does not override the site, the API drops those reports. A widget that has not loaded the chat config by the time it has an error to report (a flyout nobody opened yet, a search summary without use-chat-config) fetches it once to check. When the API refuses a report or does not have the endpoint (an older version), the widget stops reporting for the rest of the page load.

On a developer's machine (localhost, 127.0.0.1, *.localhost) and in a dev build it reports nothing, so local work does not flood the backend it points at. To test the reporting there, set reportErrors: true explicitly and turn on frontendErrors.widgets.enabled for the site; only a local API accepts reports from local pages.

A self-hosted copy is recognized by its file names, so keep them (liipgpt-chat.js, liipgpt-chat.iife.js, …). Renamed, merged into one file by a CMS, or bundled into your own build, the widget cannot tell its uncaught errors from the page's and reports only what it catches itself: crashes of its own components and failed requests.

Note: The standalone @liip/liipgpt-search-summary package is superseded by @liip/liipgpt/search-summary from this package.

For more information please refer to: docs.liipgpt.ch