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

bridgeapp-ai-chat-widget

v0.2.12

Published

Embeddable chat widget for communication with Bridge AI agent

Downloads

1,734

Readme

Bridge AI Chat Widget

Embeddable React + TypeScript chat widget for Bridge AI agents, with:

  • text chat
  • optional real-time voice mode (WebRTC)
  • optional animated 3D avatar (three.js)
  • WebSocket live message updates (AnyCable)
  • Shadow DOM isolation for host-page style safety

What This Project Is

bridgeapp-ai-chat-widget is a library bundle (ESM + UMD) that host applications instantiate via:

  • new ChatWidgetInstance(config)

The instance mounts a React app into a host element's Shadow DOM, fetches static asset mappings from a remote manifest, initializes chat/voice/avatar modules, and exposes a small integration API (setOpen, destroy, setCustomerInteractionSession, events).

Tech Stack

  • React 19
  • TypeScript
  • Vite (dev app + library build)
  • Tailwind CSS 4
  • Zustand (state stores)
  • three.js + FBX assets (avatar rendering/animation)
  • AnyCable Web client (live chat transport)
  • WebRTC + data channels (voice mode)

Repository Layout

High-level structure:

  • src/index.ts - public library entry (ChatWidgetInstance)
  • src/index.types.ts - public config/types surface
  • src/App.tsx - provider composition root
  • src/react/mount.tsx - React root mount helper
  • src/ui/components - UI components (chat widget, routes, controls)
  • src/domain/message - message store + websocket channel integration
  • src/domain/voice - voice lifecycle + WebRTC state
  • src/avatar - three.js avatar scene, animation manager, blend shapes
  • src/api - HTTP clients for messages/voice/session-related calls
  • src/context/ChatWidgetContext.tsx - widget-level UI state/context
  • src/dev - local/dev/demo stand bootstrap (non-library integration path)
  • src/assets - local assets used by the widget and avatar (not used directly, rather this whole folder is getting pushed to assets repo)
  • scripts - utility scripts (for example asset sync to remote static repo)

Runtime Architecture

1) Host Integration Layer

ChatWidgetInstance (src/index.ts) is the host-facing API:

  • validates mountElementId
  • creates shadowRoot on mount element
  • injects bundled CSS into shadow root
  • fetches ${ASSETS_URL}/manifest.json
  • resolves hashed asset paths via resolveAssetPath(path)
  • optionally merges remote config (remoteConfig)
  • mounts React app and wires AppApi callbacks/events

2) React App + Providers

App composes:

  • ChatWidgetContextProvider (widget open state, sizing, config, loading progress)
  • CableProvider (AnyCable websocket service + network status)
  • HashRouter (voice/text/list routes)

3) Messaging Domain

useMessageStore handles:

  • initial thread bootstrap (ListMessages, ListMessagesForThreads)
  • optimistic and server-driven message updates
  • thread map and per-thread message derivation
  • message send (CreateMessage)
  • agentic steps merge/update and rendering support

Live updates arrive via AnyCable channel events and are pushed into the store.

4) Voice Domain

useVoiceStore manages full voice call lifecycle:

  • starts voice session via API (StartVoiceSession)
  • builds RTCPeerConnection using TURN credentials from session payload
  • sends SDP offer / receives answer
  • buffers + sends ICE candidates
  • consumes voice data channels (voice-events, voice-input)
  • streams remote audio to an Audio element
  • handles mic enable/disable, device switching, and teardown (EndSession + EndVoiceSession)

5) Avatar Domain

Avatar + AnimationManager:

  • initializes three.js renderer/camera/lights/materials
  • loads model + texture + animation assets from resolved remote paths
  • emits loading_progress
  • starts animation mixer loops
  • maps viseme timeline to morph target animation during speech
  • exposes external animation actions (excited, fix_hair, spin, kiss)

When all assets load, widget emits avatar_ready through ChatWidgetInstance.

Public API

Import:

import { ChatWidgetInstance, type WidgetConfig } from "bridgeapp-ai-chat-widget";

ExternalWidgetConfig

  • mountElementId: string
    • configName: string - remote config, lives at the same place as other static assets
  • customerInteractionSession?: { accessToken; chatId; expiresAt } - if there's no session (separate case for dev/demo mode) - we look for customerId in remote config and create session ourselves.

RemoteWidgetConfig

Actual widget config

  • agentId: string
  • customerId?: string
  • wsUrl: string
  • apiUrl: string
  • AIAvatar?: boolean - is 3D avatar be used
  • voiceEnabled?: boolean - is voice mode enebled
  • background?: boolean - clear or visible background
  • footer?: boolean - is footer rendered
  • debug?: boolean (avatar debug GUI)
  • manualOpen?: boolean - is widget trigger rendered or should it be open only programatically

Instance Methods

  • setOpen(open: boolean): void - open/close widget
  • setCustomerInteractionSession(session): void - update session after initialization (on session expire)
  • playAnimation(name): void
  • destroy(): void

Events

  • avatar_ready - emitted once avatar assets are fully loaded
  • renew_session - emitted when session is expired or near expiry

Host Usage Example

import { ChatWidgetInstance } from "bridgeapp-ai-chat-widget";

const widget = new ChatWidgetInstance({
  mountElementId: "chat-widget-root",
  customerInteractionSession: CustomerInteractionSession,
  AIAvatar: true,
  background: false,
  voiceEnabled: true,
  footer: false,
  manualOpen: true,
});

widget.addEventListener("avatar_ready", () => {
  widget.setOpen(true);
});

widget.addEventListener("renew_session", async () => {
  const newSession = await fetchNewSessionSomehow();
  widget.setCustomerInteractionSession(newSession);
});

Teardown:

widget.destroy();

Local Development

Install:

npm install

Start dev server:

npm run dev

Notes:

  • Vite dev server runs on 5179 by default.
  • src/dev/main.tsx is the local bootstrap path (creates session and mounts widget directly).
  • vite.config.ts is for app/dev runtime.
  • vite.config.lib.ts is for distributable library build.

Build, Publish, and Deployment

Build local dev app

npm run build-dev

Build library artifacts

npm run build-lib

Outputs include:

  • dist/bridge-ai-chat-widget.es.js
  • dist/bridge-ai-chat-widget.umd.js
  • dist/index.types.d.ts

Publish flow

  • prepublishOnly runs build-lib
  • package exports are defined in package.json under "exports"

Other project scripts

  • npm run lint
  • npm run lint-fix
  • npm run format
  • npm run format:check
  • deployment scripts for S3 buckets (project-specific, to be reworked)
  • npm run push-assets-metamediastatic (sync src/assets into remote static assets repo)

Session Handling

Widget relies on customerInteractionSession:

  • used as Bearer token for HTTP APIs
  • used in websocket query for AnyCable auth
  • periodically checked by useSessionExpiryChecks

When session is near expiry or invalid, renew_session event is emitted; host app must provide a fresh session via setCustomerInteractionSession.

Asset Pipeline

Runtime asset resolution:

  1. fetch remote manifest from https://metamediastatic.com/manifest.json
  2. map logical path (for example animations/idle_1.fbx) to hashed URL
  3. load via resolveAssetPath

This allows cache-friendly hashed asset delivery without changing code references.

Troubleshooting

  • Widget does not mount:
    • verify mount element exists and mountElementId is correct
  • No messages or send failures:
    • verify apiUrl, accessToken, and chatId
  • No live updates:
    • verify wsUrl, websocket reachability, and token validity
  • Voice fails to start:
    • verify mic permission, TURN reachability, and voice API endpoints
  • Avatar never becomes ready:
    • verify manifest URL + asset availability under static host