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

@grabba/chat-widget

v0.0.4

Published

A React component library for embedding Grabba knowledge base agents as customer support chat widgets on websites.

Readme

@grabba/chat-widget

A React component library for embedding Grabba knowledge base agents as customer support chat widgets on websites.

Installation

npm install @grabba/chat-widget

Basic Usage

import React from 'react';
import { ChatWidget } from '@grabba/chat-widget';

function App() {
  return (
    <div>
      <ChatWidget
        agentId="your-agent-id"
        apiKey="your-api-key"
      />
    </div>
  );
}

The widget talks to the Grabba production endpoints by default (https://api.grabba.dev/v1 and wss://chatbot.grabba.dev/ws/v1).

Features

  • Easy Integration: Simple React component that can be mounted anywhere
  • Agent Branding: Automatically applies agent's logo, colors, fonts, and styling
  • Authentication: Handles private agent authentication flow
  • Real-time Chat: WebSocket-based streaming responses
  • Conversation Persistence: Maintains conversation state during session
  • Responsive Design: Works seamlessly on mobile and desktop
  • Customizable: CSS variables and style props for customization
  • TypeScript Support: Full TypeScript definitions included

Configuration

Required Props

  • agentId (string): The ID of the knowledge base agent to render.
  • apiKey (string): A Grabba API key belonging to the user that owns the agent. Used to fetch agent configuration and verify ownership.

Optional Props

  • email (string): Pre-filled email for private agent authentication.
  • accessToken (string): Pre-issued access token for an authenticated session.
  • onAuthRequired (function): Custom authentication handler called when the agent is private and no accessToken has been provided. Should resolve with an access token string.
  • customStyles (CSSProperties): Additional CSS styles applied to the widget root.
  • className (string): Additional CSS class names for the widget root.

Example with Custom Authentication

import React from 'react';
import { ChatWidget } from '@grabba/chat-widget';

function App() {
  const handleAuth = async (email: string) => {
    // Custom authentication logic
    const token = await yourAuthService.getToken(email);
    return token;
  };

  return (
    <ChatWidget
      agentId="your-agent-id"
      apiKey="your-api-key"
      onAuthRequired={handleAuth}
      customStyles={{
        bottom: '100px',
        right: '100px',
      }}
    />
  );
}

Authentication Flow

Public Agents

Public agents only require a valid API key — no end-user auth is needed:

<ChatWidget agentId="public-agent-id" apiKey="your-api-key" />

Private Agents

Private agents require email-based authentication on top of the API key:

  1. The user enters their email address
  2. An authorization email is sent containing an access token
  3. The user enters the access token to authenticate
  4. The chat session begins

The widget handles this flow automatically, but you can customize it using the onAuthRequired prop.

Advanced Usage

Using Hooks Directly

For more control, you can use the hooks directly:

import { useAgentConfig, useChatWidget } from '@grabba/chat-widget';

function CustomChatComponent({ agentId, apiKey }) {
  const { config, loading } = useAgentConfig(agentId, apiKey);
  const {
    messages,
    sendMessage,
    isConnected,
  } = useChatWidget({
    agentId,
    agentConfig: config,
  });

  // Custom implementation...
}

Using Services

You can also use the services directly for custom implementations:

import {
  WebSocketClient,
  AuthService,
  AgentConfigService,
  ChatMessage,
  ConnectionStatus,
} from '@grabba/chat-widget';

// Fetch agent config (requires API key)
const configService = new AgentConfigService();
const config = await configService.fetchAgentConfig('agent-id', 'your-api-key');

// Authenticate end user for a private agent
const authService = new AuthService();
await authService.requestAuthorization('agent-id', '[email protected]');
const token = await authService.authenticate('agent-id', '[email protected]', 'access-token');

// Connect WebSocket
const wsClient = new WebSocketClient('wss://chatbot.grabba.dev/ws/v1', 'agent-id', token);

// Listen for incoming messages
const unsubscribeMessage = wsClient.onMessage((message: ChatMessage) => {
  if (message.role === 'assistant') {
    // Handle AI response
  } else if (message.role === 'tool') {
    // Handle tool output
  }
});

// Listen for connection status changes
const unsubscribeStatus = wsClient.onStatusChange((status: ConnectionStatus) => {
  // status: 'disconnected' | 'connecting' | 'connected' | 'reconnecting' | 'error'
});

await wsClient.connect();
wsClient.sendInitializeChat(config, conversationId);
wsClient.sendMessage('Hello!', conversationId);

WebSocket Message Schema

Incoming Messages (ChatMessage):

interface ChatMessage {
  id?: string;
  role: 'user' | 'assistant' | 'system' | 'tool';
  content: string;
  created_at?: string;
  relevant_sources?: RelevantSource[];
  conversation_id?: string;
  message_type?: string;
  tool_name?: string;
  tool_output?: any;
}

interface RelevantSource {
  source: string;
  source_type: string;
  source_id?: string;
  favicon?: string;
}

Message Types:

  • message_chunk: Streaming AI response chunks (content is appended incrementally)
  • done: Signals the end of a message stream
  • tool_output: Tool execution results
  • error: Error messages from the server

Streaming Behavior:

The client buffers message_chunk events into a single message keyed by id. Each update replaces the previous one for the same id, so handlers receive the latest accumulated content.

Connection Status:

The client automatically attempts to reconnect on failure (up to 5 attempts with exponential backoff). Statuses: disconnected, connecting, connected, reconnecting, error.

Customization

CSS Variables

The widget uses CSS variables that can be overridden:

.grabba-chat-widget {
  --grabba-primary-color: #your-color;
  --grabba-text-color: #your-text-color;
  --grabba-border-radius: 12px;
  --grabba-font-family: 'Your Font', sans-serif;
}

Style Props

You can also pass custom styles:

<ChatWidget
  agentId="agent-id"
  apiKey="your-api-key"
  customStyles={{
    bottom: '50px',
    right: '50px',
    width: '400px',
    height: '700px',
  }}
/>

Types

Full TypeScript definitions are included:

import type {
  ChatWidgetProps,
  ChatMessage,
  AgentConfig,
  ConnectionStatus,
} from '@grabba/chat-widget';

Bundler Requirements

The package imports its stylesheet from ./styles/chat-widget.css at the top of the entry module. Your bundler must be able to resolve .css imports from node_modules — this works out of the box with webpack (via css-loader/style-loader), Vite, Next.js, Docusaurus and most modern toolchains.

Browser Support

  • Chrome (latest)
  • Firefox (latest)
  • Safari (latest)
  • Edge (latest)

License

MIT

Support

For issues, questions, or contributions, please visit our GitHub repository.