@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/chatbotRequires: 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:allLocal 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 publishRequires an npm account and Organization
@docimalat 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 publishProject 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)