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

@docimal/chatbot

v1.0.2

Published

Docimal embeddable chatbot widget

Downloads

402

Readme

@docimal/chatbot

Embeddable AI chatbot widget for Docimal. Supports 3 integration methods:

| Method | Best for | Setup | |---|---|---| | Script Tag | Static sites, WordPress, any platform | One <script> tag | | NPM SDK | React apps, Next.js | npm install @docimal/chatbot | | Iframe | Isolated embed on a specific page | <iframe> or React component |


1. Script Tag

No installation required. Paste before </body>:

<script
  src="https://cdn.docimal.site/latest/docimal-chatbot.js"
  data-api-key="dcml_pk_..."
  data-chatbot-id="your-chatbot-id"
  async
></script>

All data attributes

<script
  src="https://cdn.docimal.site/latest/docimal-chatbot.js"

  <!-- Required -->
  data-api-key="dcml_pk_..."

  <!-- Chatbot -->
  data-chatbot-id="your-chatbot-uuid"
  data-api-base-url="https://api.docimal.site"

  <!-- Position & behavior -->
  data-position="bottom-right"       <!-- bottom-right | bottom-left | inline -->
  data-start-open="false"            <!-- true | false -->

  <!-- Theme -->
  data-primary-color="#6366f1"       <!-- hex color -->

  <!-- User identity (optional) -->
  data-user-id="user_123"
  data-user-name="John Doe"
  data-user-email="[email protected]"
  data-user-phone="+1234567890"

  <!-- Custom metadata (prefix data-metadata-) -->
  data-metadata-plan="pro"
  data-metadata-company="Acme Inc"

  async
></script>

Manual mount (without auto-init)

<script src="https://cdn.docimal.site/latest/docimal-chatbot.js"></script>
<script>
  const chatbot = DocimalChatbot.mountChatbot('#container', {
    apiKey: 'dcml_pk_...',
    chatbotId: 'your-chatbot-id',
    apiBaseUrl: 'https://api.docimal.site',
    options: { position: 'bottom-right' },
    onReady: () => console.log('Ready'),
  });

  // Later: unmount
  chatbot.unmount();

  // Or update props on the fly
  chatbot.updateProps({ theme: { primaryColor: '#10b981' } });
</script>

2. NPM SDK — React/Next.js

Installation

npm install @docimal/chatbot
# or
pnpm add @docimal/chatbot
# or
yarn add @docimal/chatbot

Requires: React >= 17, React DOM >= 17 (peer dependencies — uses the React version already in your project)


React (CRA, Vite)

import { DocimalChatbot } from '@docimal/chatbot';

export default function App() {
  return (
    <>
      <YourApp />

      <DocimalChatbot
        apiKey="dcml_pk_..."
        chatbotId="your-chatbot-id"
        apiBaseUrl="https://api.docimal.site"
        options={{ position: 'bottom-right', persistSession: true }}
        theme={{ primaryColor: '#6366f1', mode: 'light' }}
        onReady={() => console.log('ready')}
        onMessage={(msg) => console.log('New message:', msg)}
      />
    </>
  );
}

Next.js App Router

The widget uses window, localStorage, and socket.io — client-only. Use dynamic with ssr: false:

// app/layout.tsx
import dynamic from 'next/dynamic';

const DocimalChatbot = dynamic(
  () => import('@docimal/chatbot').then((m) => m.DocimalChatbot),
  { ssr: false }
);

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        {children}
        <DocimalChatbot
          apiKey="dcml_pk_..."
          chatbotId="your-chatbot-id"
          apiBaseUrl="https://api.docimal.site"
          options={{ position: 'bottom-right' }}
        />
      </body>
    </html>
  );
}

Next.js Pages Router

// pages/_app.tsx
import dynamic from 'next/dynamic';
import type { AppProps } from 'next/app';

const DocimalChatbot = dynamic(
  () => import('@docimal/chatbot').then((m) => m.DocimalChatbot),
  { ssr: false }
);

export default function MyApp({ Component, pageProps }: AppProps) {
  return (
    <>
      <Component {...pageProps} />
      <DocimalChatbot
        apiKey="dcml_pk_..."
        apiBaseUrl="https://api.docimal.site"
        options={{ position: 'bottom-right' }}
      />
    </>
  );
}

useChatbot hook — open/close from any component

// components/Header.tsx
import { useChatbot } from '@docimal/chatbot';

export function Header() {
  const { open, close } = useChatbot();

  return (
    <header>
      <nav>...</nav>
      <button onClick={open}>Contact Support</button>
    </header>
  );
}

useChatbot() works as long as <DocimalChatbot /> is mounted anywhere in the component tree. The hook dispatches custom window events that the widget listens for internally.


Full props — DocimalChatbot

<DocimalChatbot
  // Authentication (required)
  apiKey="dcml_pk_..."

  // Chatbot (optional — omit if the API key has only one chatbot)
  chatbotId="uuid"

  // API
  apiBaseUrl="https://api.docimal.site"  // default: http://localhost:3000

  // User identity
  user={{
    id: 'user_123',
    name: 'John Doe',
    email: '[email protected]',
    phone: '+1234567890',
    customAttributes: {
      plan: 'pro',
      company: 'Acme Inc',
    },
  }}

  // Session metadata
  metadata={{
    source: 'pricing-page',
    campaign: 'summer-sale',
  }}

  // Widget options
  options={{
    position: 'bottom-right',    // 'bottom-right' | 'bottom-left' | 'inline'
    startOpen: false,            // open on load
    persistSession: true,        // save session to localStorage
    showBranding: true,          // show "Powered by Docimal"
  }}

  // Theme
  theme={{
    mode: 'light',               // 'light' | 'dark' | 'auto'
    primaryColor: '#6366f1',     // primary color (hex)
    fontFamily: 'Inter',         // Google Fonts name
    borderRadius: '12px',        // border radius
    headerStyle: 'colored',      // 'light' | 'colored'
    messageStyle: 'plain',       // 'plain' | 'colored'
    inputStyle: 'default',       // 'default' | 'rounded' | 'inside' | 'inside-rounded' | 'minimal'
  }}

  // Callbacks
  onReady={() => {}}
  onOpen={() => {}}
  onClose={() => {}}
  onMessage={(message) => {}}    // ChatMessage object
  onError={(error) => {}}        // Error object
/>

3. Iframe Embed

Renders the chatbot inside an <iframe>zero bundle impact, fully isolated CSS/JS.

Plain HTML (no npm)

<iframe
  src="https://app.docimal.site/embed/YOUR_CHATBOT_ID?key=dcml_pk_...&baseUrl=https://api.docimal.site&color=6366f1"
  width="400"
  height="600"
  frameborder="0"
  allow="microphone; camera"
></iframe>

URL params:

| Param | Required | Description | |---|---|---| | key | ✅ | API key dcml_pk_... | | baseUrl | | REST API base URL | | color | | Primary color hex (without #) |


React component (from npm)

import { DocimalChatbotIframe } from '@docimal/chatbot/iframe';

export default function SupportPage() {
  return (
    <DocimalChatbotIframe
      apiKey="dcml_pk_..."
      chatbotId="your-chatbot-id"
      apiBaseUrl="https://api.docimal.site"
      embedOrigin="https://app.docimal.site"
      primaryColor="#6366f1"
      width={400}
      height={600}
      onReady={() => console.log('Iframe ready')}
      onMessage={(msg) => console.log('Message:', msg)}
      onError={(err) => console.error('Error:', err)}
    />
  );
}

Two-way communication via PostMessage

// Parent → iframe: open/close the widget
const iframe = document.querySelector('iframe');
iframe.contentWindow.postMessage({ type: 'docimal:open' }, 'https://app.docimal.site');
iframe.contentWindow.postMessage({ type: 'docimal:close' }, 'https://app.docimal.site');

// Iframe → parent: receive events
window.addEventListener('message', (event) => {
  if (event.origin !== 'https://app.docimal.site') return;
  const { type, payload } = event.data;
  // type: 'docimal:ready' | 'docimal:message' | 'docimal:error'
});

Or via window.__docimalIframe (when using the React component):

window.__docimalIframe.open();
window.__docimalIframe.close();

Full props — DocimalChatbotIframe

<DocimalChatbotIframe
  apiKey="dcml_pk_..."            // required
  chatbotId="uuid"                // required
  baseUrl="https://api.docimal.site"
  embedOrigin="https://app.docimal.site"
  primaryColor="#6366f1"          // hex, with or without #
  width={400}                     // number (px) or string ('400px', '100%')
  height={600}
  className="my-iframe"
  style={{ borderRadius: '12px' }}
  onReady={() => {}}
  onMessage={(message) => {}}
  onError={(errorMessage) => {}}  // string
/>

TypeScript

All types are exported from @docimal/chatbot:

import type {
  ChatbotEmbedProps,
  ChatbotTheme,
  ChatbotOptions,
  ChatMessage,
  ChatbotConfig,
  ChatSession,
} from '@docimal/chatbot';

import type { DocimalChatbotIframeProps } from '@docimal/chatbot/iframe';

Comparison

| | Script Tag | NPM SDK | Iframe | |---|---|---|---| | Setup | One <script> tag | npm install | <iframe> or React component | | React required | No | Yes (>=17) | No | | SSR / Next.js | N/A | ssr: false | Native | | App bundle size | No impact | +~300KB (gzip ~110KB) | No impact | | CSS isolation | No | No | Full | | Programmatic control | window.DocimalChatbot | useChatbot() hook | PostMessage | | TypeScript types | No | Full .d.ts | Full .d.ts | | Best for | Any website, CMS | React/Next.js apps | Specific page embed |


Local Development

# Install dependencies
npm install

# Dev server
npm run dev
# Open http://localhost:5173

# Build IIFE (script tag)
npm run build
# Output: dist/docimal-chatbot.js, dist/docimal-chatbot.mjs

# Build NPM SDK (React + Iframe + type declarations)
npm run build:sdk
# Output: dist/react.mjs, dist/react.cjs, dist/iframe.mjs, dist/iframe.cjs, dist/types/

# Build everything
npm run build:all

Local test files

| File | Purpose | |---|---| | index.html | Test widget via Vite dev server | | test.html | Test script tag with local build | | test-iframe.html | Test iframe embed |


Publishing

First time

# 1. Log in to npm
npm login

# 2. Build
npm run build:all

# 3. Preview what will be published
npm pack --dry-run

# 4. Publish (publishConfig.access = "public" is already configured)
npm publish

Requires an npm account and Organization @docimal at npmjs.com/org/create.

If 2FA is enabled on your account, generate an Automation token at npmjs.com/settings/tokens and run:

npm set //registry.npmjs.org/:_authToken YOUR_TOKEN

Updating the version

npm version patch   # 1.0.0 → 1.0.1  (bug fix)
npm version minor   # 1.0.0 → 1.1.0  (new feature, backward compatible)
npm version major   # 1.0.0 → 2.0.0  (breaking change)

npm run build:all
npm publish

Project Structure

docimal-embed/
├── src/
│   ├── index.ts                  ← Script tag entry (auto-init + mountChatbot)
│   ├── react.tsx                 ← NPM SDK entry (DocimalChatbot + useChatbot)
│   ├── iframe.tsx                ← Iframe component entry
│   ├── components/
│   │   ├── ChatbotEmbed.tsx      ← Main component
│   │   ├── ChatWindow.tsx        ← Chat window UI
│   │   ├── ChatButton.tsx        ← Floating button
│   │   ├── MessageList.tsx       ← Message list renderer
│   │   ├── MessageInput.tsx      ← Input field
│   │   ├── SessionHistory.tsx    ← Session history panel
│   │   ├── RichComponents.tsx    ← 15 rich message component types
│   │   ├── Icons.tsx
│   │   └── ErrorBoundary.tsx
│   └── lib/
│       ├── types.ts              ← TypeScript types
│       ├── api.ts                ← EmbedApiClient (REST + SSE streaming)
│       ├── socket.ts             ← SupportSocketClient (WebSocket)
│       ├── styles.ts             ← CSS-in-JS styles
│       ├── fonts.ts              ← Google Fonts dynamic loader
│       └── component-detector.ts ← Auto-detect rich components from plain text
│
├── dist/                         ← Build output (not committed)
│   ├── docimal-chatbot.js        ← IIFE bundle (script tag)
│   ├── docimal-chatbot.mjs       ← ESM bundle (script tag)
│   ├── react.mjs / react.cjs     ← NPM SDK
│   ├── iframe.mjs / iframe.cjs   ← Iframe component
│   └── types/                    ← TypeScript declarations
│
├── vite.config.ts                ← IIFE build config
├── vite.sdk.config.ts            ← NPM SDK build config
├── tsconfig.json                 ← TS config for development (noEmit: true)
└── tsconfig.build.json           ← TS config for build (generates .d.ts)