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

@smooai/chat-widget

v0.15.0

Published

Embeddable AI chat as a framework-light web component — the Aurora Glass design, streaming replies, grounded sources, and per-brand theming. Speaks the smooth-operator WebSocket protocol.

Readme


A self-contained, streaming chat surface you drop into any site with one tag. No React on the host page, no CSS to import, ~19 kB gzipped, with the smooth-operator protocol client built in.

<smooth-agent-chat> is a self-contained chat web component for the smooth-operator protocol. Drop in one <script> tag (or import the ESM module) and you get a polished, streaming, shadow-DOM-isolated chat experience — the "Aurora Glass" design — that adapts to any host brand from a single accent color.

No React on the host page. No CSS to import. ~19 kB gzipped, protocol client included.

<script src="https://unpkg.com/@smooai/chat-widget/dist/chat-widget.global.js"></script>
<smooth-agent-chat endpoint="wss://your-host/ws" agent-id="…" agent-name="Support"></smooth-agent-chat>

Live demo: open index.html (it runs entirely in the browser against an in-page mock of the protocol — no backend needed).

Why this widget

  • Aurora Glass design — a spring launcher with a live presence pulse, a glass-depth panel, gradient brand avatar + status dot, an animated typing indicator, message rise-in, refined source cards, and an icon composer.
  • Brand-adaptive — pass one primary color and the gradients, bubbles, glow, and depth shades derive themselves. Works light or dark.
  • Streaming + sources — token-by-token replies with a typing indicator and a collapsible "Sources" disclosure for knowledge-grounded answers.
  • Popover or full-page — a floating launcher, or a full-bleed /chat surface. Same component, one attribute.
  • Framework-light & isolated — a standard custom element with Shadow-DOM style isolation. Use it with React, Vue, Svelte, Astro, or no framework at all.
  • Secure by construction — message + citation text is rendered via textContent, and citation links are restricted to http(s) (no javascript:/data: XSS).

Install

pnpm add @smooai/chat-widget
# or: npm i @smooai/chat-widget  ·  yarn add @smooai/chat-widget

@smooai/smooth-operator (the protocol client) is a runtime dependency and is installed automatically.

Quick start

1. Recommended — the deferred loader (best Core Web Vitals)

Include the tiny loader (~2 KB gzipped) eagerly. It does nothing expensive on load — it waits until the page is past its critical render (requestIdleCallback after load, or the visitor's first pointer/keydown/scroll, or an 8 s fallback), and only then injects the full widget module. The widget never competes with your page's LCP/TBT, but it's instantly there the moment a visitor shows intent.

<script>
    window.SmoothAgentChatConfig = {
        endpoint: 'wss://your-host/ws',
        agentId: '11111111-1111-4111-8111-111111111111',
        agentName: 'Support',
        greeting: 'Hi! How can I help?',
    };
</script>
<script src="https://unpkg.com/@smooai/chat-widget/dist/chat-widget-loader.global.js" async></script>

The loader resolves the widget module as a sibling of its own URL (override with data-src), so a single CDN path is all you need. For the simplest installs you can skip the config global and use data-* attributes on the loader tag (data-endpoint, data-agent-id, data-primary, data-mode).

2. Declarative — eager <script> + the element

Simplest, but the module evaluates during page load — prefer the loader above on performance-sensitive (especially marketing) pages.

<script src="https://unpkg.com/@smooai/chat-widget/dist/chat-widget.global.js"></script>

<smooth-agent-chat
    endpoint="wss://your-host/ws"
    agent-id="11111111-1111-4111-8111-111111111111"
    agent-name="Support"
    greeting="Hi! How can I help?"
></smooth-agent-chat>

The IIFE bundle auto-registers the element on load.

3. Programmatic — bundler / ESM

import { mountChatWidget } from '@smooai/chat-widget';

const widget = mountChatWidget({
    endpoint: 'wss://your-host/ws',
    agentId: '11111111-1111-4111-8111-111111111111',
    agentName: 'Support',
    theme: { primary: '#8b5cf6' },
});

// Drive it imperatively:
widget.openChat();
widget.closeChat();

Or register the element and place it yourself:

import { defineChatWidget } from '@smooai/chat-widget';
defineChatWidget(); // now <smooth-agent-chat> works anywhere in your markup

Theming

Every color is a CSS custom property under the hood, so the simplest possible theme is a single primary — the launcher gradient, send button, user bubbles, ambient glow, and derived depth shades all follow from it.

mountChatWidget({
    endpoint, agentId,
    theme: {
        primary: '#ff5d6e',        // the one color most brands need to set
        background: '#ffffff',     // light panel
        text: '#1f2430',
    },
});

| Token | Drives | Default | | ---------------------- | --------------------------------------------------- | ------------------ | | primary | Launcher, send button, user bubble, glow, avatar | #00a6a6 | | primaryText | Text/icon on top of primary | #f8fafc | | background | Panel background | #040d30 | | text | Foreground text + derived inset surfaces | #f8fafc | | assistantBubble | Inbound (assistant) bubble background | #06134b | | assistantBubbleText | Inbound bubble text | #f8fafc | | userBubble | Outbound (user) bubble background | primary | | userBubbleText | Outbound bubble text | primaryText | | border | Panel + input hairline | rgba(255,255,255,.1) |

Two further tokens — a darker primary-2 (gradient depth) and a surface-2 inset wash — are derived in CSS from primary/text, so you never have to supply them and they adapt automatically to light or dark themes.

Dashboard parity: the theme also accepts the SmooAI agent dashboard's 10-color model — secondary plus chatBubbleInbound / chatBubbleInboundText / chatBubbleOutbound / chatBubbleOutboundText (aliases that win over the canonical keys) — so a config exported from the dashboard themes the widget directly.

Visitor identity & starter prompts

mountChatWidget({
    endpoint, agentId,
    examplePrompts: ['How do I get started?', 'Do you integrate with HubSpot?'],
    requireName: true,
    requireEmail: true,   // gate the chat behind a pre-chat form…
    // allowAnonymous: true, // …or let visitors skip it entirely
});
  • examplePrompts render as clickable chips in the empty state (max 5).
  • showSuggestedReplies (default true) shows mid-conversation suggested-reply chips under the latest assistant message when the agent returns follow-up suggestions; tapping one sends it. Set false to hide them.
  • requireName / requireEmail / requirePhone show a styled pre-chat form; the collected name/email are attached to the conversation session (phone rides session metadata). Set allowAnonymous: true to skip the form.

OTP & tool confirmation (HITL)

When a turn pauses for OTP verification or a tool-write approval, the widget shows an inline overlay above the composer — an OTP code prompt (with masked destination + retry state) or an Approve/Decline confirmation — and resumes the turn automatically. Under the hood the ConversationController surfaces otp_verification_required / write_confirmation_required via an onInterrupt callback and resumes with verifyOtp(code) / confirmTool(approved), so you can also drive it programmatically.

Full-page mode

Render the chat as a full-bleed surface (a /chat route, a docs sidebar, an iframe) instead of a floating launcher:

<smooth-agent-chat mode="fullpage" endpoint="wss://…/ws" agent-id="…"></smooth-agent-chat>
import { mountFullPageChat } from '@smooai/chat-widget';
mountFullPageChat({ endpoint, agentId, agentName: 'Support' }, document.getElementById('chat'));

Configuration

Declarative attributes mirror the programmatic ChatWidgetConfig:

| Attribute | Config key | Notes | | --------------- | ---------------- | -------------------------------------------------- | | endpoint | endpoint | Required. smooth-operator WebSocket URL. | | agent-id | agentId | Required. UUID of the agent. | | agent-name | agentName | Header label + monogram. Default Assistant. | | logo-url | logoUrl | Brand logo in the full-page header tile (http(s) only). Falls back to the Smooth icon. | | placeholder | placeholder | Composer placeholder. | | greeting | greeting | Shown before the first message. | | mode | mode | popover (default) or fullpage. | | start-open | startOpen | Open the panel immediately (no launcher click). | | hide-branding | hideBranding | Hide the "powered by smooth-operator" tag + footer link. Default shown. | | show-tool-activity | showToolActivity | Show the agent's tool activity as inline chips interleaved with its prose. Default off (end-users normally shouldn't see raw tool calls). | | — | theme | Brand colors (see Theming). | | — | userName / userEmail | Optional participant identity. |

Programmatic API

mountChatWidget(config, target?) and mountFullPageChat(config, target?) return the element, which exposes:

  • configure(partialConfig) — merge overrides (e.g. live theme tweaks) and re-render.
  • openChat() / closeChat() — toggle the popover panel.

How it works

The widget is pure view + a thin ConversationController that speaks the smooth-operator protocol via @smooai/smooth-operator:

connect()  →  WebSocket + create_conversation_session
send(text) →  send_message  →  stream_token … (live) …  →  eventual_response (+ citations)

The wire protocol is owned by smooth-operator; this package only renders it. That keeps one source of truth for the protocol and lets the widget stay tiny.

Browser support

Evergreen browsers (Chrome/Edge 111+, Safari 16.4+, Firefox 113+). The design uses color-mix() to derive brand shades and ::part() for host-side customization.

Local development

pnpm install
pnpm build          # tsdown → dist/ (ESM + IIFE)
pnpm typecheck      # tsc --noEmit
pnpm test           # vitest (jsdom) unit + render smoke tests
pnpm check          # typecheck + test + build
pnpm test:e2e       # Playwright live e2e (gated — see e2e/)

Open index.html (e.g. pnpm dlx serve .) after a build for the interactive, backend-free showcase.

Part of Smoo AI

@smooai/chat-widget is built and open-sourced by Smoo AI — the AI-powered business platform with AI built into every product: CRM, customer support, campaigns, field service, observability, and developer tools.

Contributing

Issues and PRs welcome. Run pnpm check (typecheck + test + build) before opening a PR.

License

MIT © Smoo AI