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

@botuyo/chat-widget-standalone

v1.1.11

Published

BotUyo Chat Widget - Standalone CDN version with React/TypeScript support

Downloads

1,088

Readme

@botuyo/chat-widget

AI-powered chat widget with Shadow DOM isolation, dark mode, voice chat, and full white-labeling. Works as a CDN script tag or NPM React component.


Quick Start — CDN (Standalone)

Add a single script tag to any HTML page. No build step required.

<script src="https://cdn.botuyo.com/widget/botuyo-chat.js"></script>
<script>
  BotUyoChat.init({
    apiKey: 'YOUR_API_KEY'
  });
</script>

That's it. The widget connects to the BotUyo backend, receives the agent configuration (name, avatar, colors, voice settings), and renders itself in a Shadow DOM so it never conflicts with your site's CSS.

CDN — Custom Theme Override

You can override any server-sent value locally:

<script src="https://cdn.botuyo.com/widget/botuyo-chat.js"></script>
<script>
  BotUyoChat.init({
    apiKey: 'YOUR_API_KEY',
    theme: {
      botName: 'Soporte',
      position: 'bottom-left',
      welcomeMessage: '¡Hola! ¿En qué te puedo ayudar?',
      inputPlaceholder: 'Escribí tu mensaje...',
      cssVariables: {
        primary: '210 100% 50%',        // Blue
        primaryForeground: '0 0% 100%', // White text on blue
        background: '0 0% 100%',        // White background
        foreground: '210 20% 12%',      // Dark text
        radius: '0.75rem',
      },
      darkCssVariables: {
        background: '220 40% 3%',
        foreground: '210 20% 98%',
        card: '220 40% 5%',
        muted: '220 30% 10%',
        border: '220 30% 12%',
      },
    },
  });
</script>

CDN — Programmatic API

BotUyoChat.open();                    // Open the chat window
BotUyoChat.close();                   // Close the chat window
BotUyoChat.sendMessage('Hola!');      // Send a message
BotUyoChat.destroy();                 // Remove widget from page

// Update config at runtime
BotUyoChat.update({
  theme: { botName: 'New Name' }
});

NPM — React / Next.js

npm install @botuyo/chat-widget-standalone

Option 1: Drop-in Component (Shadow DOM)

The default ChatWidget export renders inside Shadow DOM for full CSS isolation:

import { ChatWidget } from '@botuyo/chat-widget-standalone';

export default function App() {
  return (
    <ChatWidget
      apiKey="YOUR_API_KEY"
      theme={{
        position: 'bottom-right',
        cssVariables: {
          primary: '210 100% 50%',
        },
      }}
    />
  );
}

Option 2: Provider + Hook (Programmatic Control)

Use ChatWidgetProvider to access the widget state from any component:

import { ChatWidgetProvider, useChatWidget } from '@botuyo/chat-widget-standalone';

function App() {
  return (
    <ChatWidgetProvider apiKey="YOUR_API_KEY">
      <MyPage />
    </ChatWidgetProvider>
  );
}

function MyPage() {
  const { open, close, isOpen, unreadCount, sendMessage } = useChatWidget();

  return (
    <button onClick={open}>
      Chat {unreadCount > 0 && `(${unreadCount})`}
    </button>
  );
}

Option 3: Unstyled Component (No Shadow DOM)

If you want the widget in your own DOM tree (useful inside existing design systems):

import { ChatWidgetUnstyled } from '@botuyo/chat-widget-standalone';
import '@botuyo/chat-widget-standalone/style.css';

export default function App() {
  return <ChatWidgetUnstyled apiKey="YOUR_API_KEY" />;
}

Configuration Reference

ChatWidgetProps

| Prop | Type | Default | Description | |------|------|---------|-------------| | apiKey | string | (required) | Your public API key | | apiBaseUrl | string | https://api.botuyo.com | Backend gateway URL | | agentId | string | — | Connect to a specific agent flow | | theme | ChatTheme | — | Visual configuration (see below) | | mediaConfig | MediaConfig | — | Toggle images, audio, files, location, voice | | userContext | { token?, metadata? } | — | Pass authenticated user info | | pageContext | PageContext | — | Page-level context sent with each message | | includeSEOMetadata | boolean | false | Auto-capture page SEO data | | onNavigate | (url) => void | — | Bot requests navigation | | onLogin | (userData) => void | — | Bot completes authentication | | onEvent | (name, data) => void | — | Widget lifecycle events | | onStateChange | (isOpen) => void | — | Window open/close callback |

ChatTheme

| Property | Type | Description | |----------|------|-------------| | botName | string | Bot display name | | logoUrl | string | Bot avatar URL | | headerText | string | Header bar text (overrides botName in header) | | position | 'bottom-right' \| 'bottom-left' | Launcher position | | welcomeMessage | string | First message shown to user | | inputPlaceholder | string | Input field placeholder | | starterPrompt | string | Prompt bubble shown when chat is closed | | defaultLocale | 'es' \| 'en' \| 'pt' \| 'fr' | Widget language | | avatarScale | number | Avatar zoom (e.g., 1.2 = 20% bigger) | | showPromptAvatar | boolean | Show mini avatar in prompt bubble | | isHidden | boolean | Hide widget (draft/paused agents) | | cssVariables | CSSVariables | Light mode colors and layout (see below) | | darkCssVariables | Partial<CSSVariables> | Dark mode color overrides | | animations | AnimationConfig | Animation toggles | | effects | EffectsConfig | Visual effect toggles | | avatars | EmotionAvatarMap | Per-emotion avatar URLs | | avatar3dUrl | string | URL to .vrm/.glb 3D model for voice calls | | bubbleStyles | BubbleStyles | Fine-grained bubble/card styling |

cssVariables — Design Tokens (HSL format)

All color values use HSL without the hsl() wrapper, e.g., "210 100% 50%".

| Variable | CSS Property | Default (Light) | Description | |----------|-------------|-----------------|-------------| | background | --background | 0 0% 100% | Page/widget background | | foreground | --foreground | 240 10% 3.9% | Main text color | | card | --card | 0 0% 100% | Card background | | cardForeground | --card-foreground | 240 10% 3.9% | Card text | | primary | --primary | 160 84% 39% | Brand/accent color | | primaryForeground | --primary-foreground | 0 0% 100% | Text on primary bg | | muted | --muted | 240 4.8% 95.9% | Muted backgrounds | | mutedForeground | --muted-foreground | 240 3.8% 46.1% | Muted text | | border | --border | 240 5.9% 90% | Border color | | destructive | --destructive | 0 84.2% 60.2% | Error/danger color | | radius | --radius | 0.5rem | Base border radius |

Layout variables:

| Variable | CSS Property | Default | Description | |----------|-------------|---------|-------------| | windowBorderRadius | --window-border-radius | 24px | Chat window corner radius | | launcherBorderRadius | --launcher-border-radius | 50% | Launcher button radius | | windowHeight | --window-height | 700px | Chat window height (desktop) | | windowBottom | --window-bottom | 24px | Distance from bottom edge |

Spacing variables:

| Variable | CSS Property | Default | |----------|-------------|---------| | spacing1 | --spacing-1 | 0.25rem (4px) | | spacing2 | --spacing-2 | 0.5rem (8px) | | spacing3 | --spacing-3 | 0.75rem (12px) | | spacing4 | --spacing-4 | 1rem (16px) | | spacing5 | --spacing-5 | 0.75rem (12px) | | spacing6 | --spacing-6 | 1.5rem (24px) | | spacing7 | --spacing-7 | 1.75rem (28px) | | spacing8 | --spacing-8 | 2rem (32px) |

darkCssVariables

Same keys as cssVariables. Only override surface colors — primary and primaryForeground are preserved from the light theme by default:

darkCssVariables: {
  background: '220 40% 3%',
  foreground: '210 20% 98%',
  card: '220 40% 5%',
  muted: '220 30% 10%',
  border: '220 30% 12%',
}

AnimationConfig

| Property | Type | Default | Description | |----------|------|---------|-------------| | enabled | boolean | true | Master toggle | | messageEntry | 'slide' \| 'fade' \| 'scale' \| 'spring' \| 'none' | 'spring' | Message entry style | | typingIndicator | 'dots' \| 'wave' \| 'pulse' \| 'none' | 'dots' | Typing animation | | buttonEffects | boolean | true | Hover/press effects | | smoothScroll | boolean | true | Smooth scroll in messages | | launcherPulse | boolean | true | Launcher pulse animation | | windowTransitions | boolean | true | Window open/close animation |

EffectsConfig

| Property | Type | Default | Description | |----------|------|---------|-------------| | glassmorphism | boolean | true | Blur effect on headers | | gradients | boolean | true | Gradient backgrounds | | softShadows | boolean | true | Soft shadow effects | | glowEffects | boolean | true | Hover/focus glow | | shimmerLoading | boolean | true | Shimmer loading skeleton | | hoverLift | boolean | true | Card hover lift effect |


Dark Mode

The widget auto-detects dark mode via:

  1. data-theme="dark" attribute on <html>
  2. prefers-color-scheme: dark media query

When dark mode is active, colors are applied in this priority:

  1. User-provided darkCssVariables (highest priority)
  2. Server-sent darkCssVariables (from agent config)
  3. Built-in dark defaults (fallback)

primary and primaryForeground are never overridden by dark defaults — they always come from your brand configuration.


Events

Listen to widget lifecycle events via onEvent:

| Event Name | Data | Description | |-----------|------|-------------| | backend_config | config | Agent config received from server | | history_loaded | { messages } | Chat history loaded | | message_sent | { id } | Message delivered successfully | | message_failed | { id, payload } | Message delivery failed | | queued_message | { id, payload } | Message queued (offline) |


Development

npm run dev          # Start dev server
npm run build        # Production build (ES + UMD + types)
npm run test:run     # Run all tests
npm run lint         # ESLint
npm run typecheck    # TypeScript check

License

MIT