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

chatify-core

v1.0.2

Published

Chatify.js - Framework-agnostic secure chatbot widget core with XSS protection, rate limiting, and file upload security

Readme

🛡️ chatify-core

A secure, framework-agnostic chatbot widget with built-in XSS protection, rate limiting, and file upload security

NPM Version License: MIT TypeScript Security: First

Chatify.js is a production-ready chatbot widget that works with React, Vue, Angular, Next.js, Nuxt.js, and vanilla JavaScript. Built with security-first principles and SSR compatibility.

🆕 What's New in v1.0.2

🐛 Major Bug Fix

  • Duplicate Response Issue Resolved: Fixed critical issue where chatbot sent both automatic and API responses
  • Users now receive exactly one response per message as expected

✨ Enhanced API Integration

  • Public Methods: addMessage() and showError() are now public for external API control
  • State Access: New isOpen getter to check chatbot state from external code
  • Better Control: External APIs now have complete control over bot responses

🔧 Improvements

  • Removed automatic mock responses that interfered with real API integration
  • Enhanced internal architecture for better API integration support
  • Zero Breaking Changes: All existing code continues to work unchanged

📋 Migration: No action required - existing integrations work perfectly!

✨ Features

  • 🛡️ Security First: XSS protection, rate limiting, input sanitization
  • 🔧 Framework Agnostic: Works with React, Vue, Angular, or vanilla JS
  • 🎨 Fully Customizable: Colors, themes, positioning, branding
  • 📱 Responsive Design: Works on desktop and mobile
  • � Secure File Upload: Type validation, size limits, sanitization
  • ⚡ TypeScript Ready: Full type safety and IntelliSense
  • 🌐 SSR Compatible: Next.js, Nuxt.js, Angular Universal support
  • 🚀 Modern: ES modules, tree-shaking support

🚀 Quick Start

Installation

npm install chatify-core

Basic Usage

import { ChatbotCore } from 'chatify-core';

const chatbot = new ChatbotCore({
  primaryColor: '#007bff',
  companyName: 'Your Company',
  greeting: 'Hello! How can I help you today?',
  position: 'bottom-right'
});

Advanced Usage with API Integration

import { ChatbotCore } from 'chatify-core';

const chatbot = new ChatbotCore({
  primaryColor: '#007bff',
  companyName: 'Your Company',
  greeting: 'Hello! How can I help you?'
});

// Listen for user messages
chatbot.on('message', async (message) => {
  if (message.sender === 'user') {
    try {
      // Call your API
      const response = await fetch('/api/chat', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ 
          message: message.text,
          sessionId: 'user-session-123'
        })
      });
      
      const data = await response.json();
      
      // Add bot response using new public method
      chatbot.addMessage({
        id: chatbot.generateId(),
        text: data.response,
        sender: 'bot',
        timestamp: new Date()
      });
      
    } catch (error) {
      // Show error using new public method
      chatbot.showError('Sorry, something went wrong. Please try again.');
    }
  }
});

// Check if chatbot is open using new getter
if (chatbot.isOpen) {
  console.log('Chatbot is currently open');
}

Advanced Usage with Security

import { AdvancedChatbotCore, SecurityUtils } from 'chatify-core';

const chatbot = new AdvancedChatbotCore({
  // Appearance
  primaryColor: '#007bff',
  companyName: 'Your Company',
  
  // API Integration (secure)
  apiUrl: 'https://your-server.com/api/chat',
  
  // Security settings
  enableFileUpload: true,
  messageRateLimit: 10,    // messages per minute
  uploadRateLimit: 3,      // uploads per minute
  
  // Features
  enableTypingIndicator: true,
  quickReplies: ['Help', 'Pricing', 'Contact'],
});

// Listen to events
chatbot.on('message', (msg) => {
  console.log('New message:', msg);
});

🔧 Framework Integration

React

import React, { useEffect, useRef } from 'react';
import { ChatbotCore } from 'chatify-core';

function App() {
  const chatbotRef = useRef(null);

  useEffect(() => {
    chatbotRef.current = new ChatbotCore({
      primaryColor: '#007bff',
      companyName: 'My React App',
      greeting: 'Hello from React!'
    });

    return () => chatbotRef.current?.destroy();
  }, []);

  return <div>Your React App</div>;
}

Vue 3 (Composition API)

<template>
  <div>Your Vue App</div>
</template>

<script setup>
import { onMounted, onUnmounted, ref } from 'vue';
import { ChatbotCore } from 'chatify-core';

const chatbot = ref(null);

onMounted(() => {
  chatbot.value = new ChatbotCore({
    primaryColor: '#42b883',
    companyName: 'My Vue App',
    greeting: 'Hello from Vue!'
  });
});

onUnmounted(() => {
  chatbot.value?.destroy();
});
</script>

Vue 2 (Options API)

<template>
  <div>Your Vue App</div>
</template>

<script>
import { ChatbotCore } from 'chatify-core';

export default {
  data() {
    return {
      chatbot: null
    };
  },
  mounted() {
    this.chatbot = new ChatbotCore({
      primaryColor: '#42b883',
      companyName: 'My Vue 2 App'
    });
  },
  beforeDestroy() {
    this.chatbot?.destroy();
  }
};
</script>

Angular

import { Component, OnInit, OnDestroy } from '@angular/core';
import { ChatbotCore } from 'chatify-core';
import type { ChatbotConfig } from 'chatify-core';

@Component({
  selector: 'app-chatbot',
  template: '<div>Your Angular App</div>'
})
export class ChatbotComponent implements OnInit, OnDestroy {
  private chatbot: ChatbotCore | null = null;

  ngOnInit(): void {
    this.chatbot = new ChatbotCore({
      primaryColor: '#dd0031',
      companyName: 'My Angular App',
      greeting: 'Hello from Angular!'
    });
  }

  ngOnDestroy(): void {
    this.chatbot?.destroy();
  }
}

Next.js (SSR-Safe)

// components/ChatbotWrapper.tsx
'use client';
import { useEffect, useRef } from 'react';
import { ChatbotCore } from 'chatify-core';

export default function ChatbotWrapper() {
  const chatbotRef = useRef<ChatbotCore | null>(null);

  useEffect(() => {
    // SSR-safe - package has built-in guards
    chatbotRef.current = new ChatbotCore({
      primaryColor: '#000000',
      companyName: 'My Next.js App'
    });

    return () => chatbotRef.current?.destroy();
  }, []);

  return null; // Chatbot renders itself
}

// pages/index.tsx or app/page.tsx
import dynamic from 'next/dynamic';

const ChatbotWrapper = dynamic(
  () => import('../components/ChatbotWrapper'),
  { ssr: false }
);

export default function Home() {
  return (
    <div>
      <h1>My Next.js App</h1>
      <ChatbotWrapper />
    </div>
  );
}

Nuxt.js

<template>
  <div>
    <h1>My Nuxt App</h1>
  </div>
</template>

<script setup>
import { ChatbotCore } from 'chatify-core';

let chatbot = null;

onMounted(() => {
  // SSR-safe - package has built-in guards
  chatbot = new ChatbotCore({
    primaryColor: '#00dc82',
    companyName: 'My Nuxt App'
  });
});

onUnmounted(() => {
  chatbot?.destroy();
});
</script>

Vanilla JavaScript

<!DOCTYPE html>
<html>
<head>
  <title>My Website</title>
</head>
<body>
  <h1>Welcome to my website!</h1>
  
  <script type="module">
    import { ChatbotCore } from 'chatify-core';
    
    const chatbot = new ChatbotCore({
      primaryColor: '#007bff',
      companyName: 'Your Company',
      greeting: 'Hello! How can I help you?',
      position: 'bottom-right'
    });
  </script>
</body>
</html>

TypeScript

import { ChatbotCore, AdvancedChatbotCore } from 'chatify-core';
import type { 
  ChatbotConfig, 
  AdvancedChatbotConfig, 
  Message,
  SecurityEvent 
} from 'chatify-core';

const config: ChatbotConfig = {
  primaryColor: '#007bff',
  companyName: 'TypeScript App',
  greeting: 'Hello from TypeScript!'
};

const chatbot = new ChatbotCore(config);

// Type-safe event handling
chatbot.on('message', (message: Message) => {
  console.log(`${message.sender}: ${message.text}`);
});

🔒 Security Features

Built-in Security Protections

  • XSS Prevention: All user inputs automatically sanitized
  • Rate Limiting: Configurable message and upload limits (10 msg/min, 3 uploads/min)
  • File Upload Security: MIME type validation, size limits, filename sanitization
  • Input Validation: Length limits, content filtering
  • Secure ID Generation: Cryptographically secure random IDs
  • URL Validation: Prevents malicious redirects
  • SSR Safe: Works in server-side rendering environments

Manual Security Utils

import { SecurityUtils } from 'chatify-core';

// Sanitize HTML content
const safe = SecurityUtils.sanitizeHTML('<script>alert("xss")</script>');
// Result: "&lt;script&gt;alert("xss")&lt;/script&gt;"

// Validate file uploads
const isValid = SecurityUtils.validateFileType(file, ['image/jpeg', 'image/png']);

// Generate secure IDs
const id = SecurityUtils.generateSecureId();
// Result: "a7B9cD2eF8gH1jK4"

// Validate URLs
const isSafeUrl = SecurityUtils.validateURL('https://example.com');

// Validate input length
const isValidLength = SecurityUtils.validateLength(input, 1000);

🎨 Customization Options

const chatbot = new ChatbotCore({
  // Colors
  primaryColor: '#007bff',
  secondaryColor: '#6c757d',
  backgroundColor: '#ffffff',
  textColor: '#212529',
  
  // Layout
  position: 'bottom-right', // bottom-left, top-right, top-left
  width: 350,
  height: 500,
  borderRadius: 12,
  zIndex: 9999,
  
  // Branding
  companyName: 'Your Company',
  logo: 'https://your-domain.com/logo.png',
  greeting: 'Hello! How can I help you?',
  placeholder: 'Type your message...',
  
  // Behavior
  autoOpen: false
});

🔌 API Integration

API Integration Best Practices

// ✅ RECOMMENDED: Modern approach using new public methods (v1.0.2+)
const chatbot = new ChatbotCore({
  primaryColor: '#007bff',
  companyName: 'Your Company'
});

chatbot.on('message', async (message) => {
  if (message.sender === 'user') {
    try {
      const response = await callYourAPI(message.text);
      
      // Use new public method to add bot response
      chatbot.addMessage({
        id: chatbot.generateId(),
        text: response,
        sender: 'bot',
        timestamp: new Date()
      });
    } catch (error) {
      // Use new public method to show errors
      chatbot.showError('Sorry, I encountered an error. Please try again.');
    }
  }
});

// ✅ ALSO GOOD: Using AdvancedChatbotCore for automatic API handling
const advancedChatbot = new AdvancedChatbotCore({
  apiUrl: 'https://your-server.com/api/chat', // Handles API calls automatically
  primaryColor: '#007bff'
});

Secure API Setup

Always keep API keys on your server:

// ✅ SECURE: Server-side API proxy
const chatbot = new AdvancedChatbotCore({
  apiUrl: 'https://your-server.com/api/chat-proxy'
});

// ❌ INSECURE: Never expose API keys in client code
const chatbot = new ChatbotCore({
  apiKey: 'sk-your-secret-key' // DON'T DO THIS!
});

API Endpoint Format

// POST /api/chat
{
  "message": "Hello",
  "sessionId": "session_123",
  "userId": "user_456"
}

// Response
{
  "response": "Hi there! How can I help you today?",
  "sessionId": "session_123"
}

Advanced Features

const chatbot = new AdvancedChatbotCore({
  // API Integration
  apiUrl: 'https://your-server.com/api/chat',
  
  // Security Configuration
  maxFileSize: 5 * 1024 * 1024, // 5MB limit
  allowedFileTypes: ['image/jpeg', 'image/png', 'application/pdf'],
  messageRateLimit: 10, // messages per minute
  uploadRateLimit: 3,   // uploads per minute
  
  // Advanced Features
  enableFileUpload: true,
  enableTypingIndicator: true,
  enableReadReceipts: false,
  quickReplies: ['Help', 'Pricing', 'Contact Sales'],
  
  // Analytics (privacy-focused)
  trackEvents: true,
  userId: 'anonymous_user_123', // Use hashed/anonymous IDs
  
  // UI Customization
  customCSS: '.chatbot-widget { border: 2px solid #007bff; }',
  offlineMessage: 'We are currently offline. Please try again later.'
});

📖 API Reference

ChatbotCore

Constructor Options

interface ChatbotConfig {
  // Appearance
  primaryColor?: string;
  secondaryColor?: string;
  backgroundColor?: string;
  textColor?: string;
  
  // Layout
  position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
  width?: number | string;
  height?: number | string;
  
  // Branding
  companyName?: string;
  logo?: string;
  greeting?: string;
  placeholder?: string;
  
  // Behavior
  autoOpen?: boolean;
}

Methods

  • open() - Open the chat widget
  • close() - Close the chat widget
  • addMessage(message: Message) - NEW in v1.0.2: Add a message to the chat (user or bot)
  • showError(message: string) - NEW in v1.0.2: Display an error message to the user
  • on(event, callback) - Listen to events
  • updateConfig(config) - Update configuration
  • destroy() - Remove the widget

Properties

  • isOpen: boolean - NEW in v1.0.2: Check if the chatbot is currently open (read-only)

Events

  • open - Widget opened
  • close - Widget closed
  • message - New message sent (user messages trigger this event)

AdvancedChatbotCore

Extends ChatbotCore with additional features:

interface AdvancedChatbotConfig extends ChatbotConfig {
  // API Integration
  apiUrl?: string;
  
  // Security
  messageRateLimit?: number;
  uploadRateLimit?: number;
  maxFileSize?: number;
  allowedFileTypes?: string[];
  
  // Features
  enableFileUpload?: boolean;
  enableTypingIndicator?: boolean;
  quickReplies?: string[];
  
  // Analytics
  trackEvents?: boolean;
  userId?: string;
}

🛠️ Development

Building from Source

git clone <repository>
cd chatbot-core
npm install
npm run build

Scripts

  • npm run build - Build the package
  • npm run dev - Watch mode development
  • npm run clean - Clean build directory

📦 Package Contents

dist/
├── index.js          # CommonJS build
├── index.esm.js      # ES modules build  
├── index.d.ts        # TypeScript definitions
└── *.map             # Source maps

🔗 Framework Integration

React

import { ChatbotCore } from 'chatify-core';
import { useEffect } from 'react';

function App() {
  useEffect(() => {
    const chatbot = new ChatbotCore({
      primaryColor: '#007bff',
      companyName: 'My App'
    });
    
    return () => chatbot.destroy();
  }, []);
  
  return <div>My App</div>;
}

Vue

<template>
  <div>My App</div>
</template>

<script>
import { ChatbotCore } from 'chatify-core';

export default {
  mounted() {
    this.chatbot = new ChatbotCore({
      primaryColor: '#007bff',
      companyName: 'My App'
    });
  },
  beforeDestroy() {
    this.chatbot?.destroy();
  }
};
</script>

🤝 Contributing

Contributions welcome! Please read our contributing guidelines.

📄 License

MIT License - see LICENSE file for details.

🆘 Support