@navsi.ai/sdk
v1.0.9
Published
React SDK for Navsi AI chatbot - Ask and Navigate modes
Readme
@navsi.ai/sdk - Navsi AI Chatbot SDK
AI-powered chatbot SDK for websites with Ask & Navigate modes.
⚠️ Note: This package is part of the
navsi-integratedmonorepo.
Installation (for external users)
npm install @navsi.ai/sdk
# or
yarn add @navsi.ai/sdk
# or
pnpm add @navsi.ai/sdkFor Next.js projects, ensure next is installed (optional peer dependency):pnpm add next (or use your existing Next.js app).
Quick Start
Zero-config styling — All widget styles are auto-injected at runtime. You do not need to import any CSS file.
import { ChatbotProvider, ChatbotWidget } from '@navsi.ai/sdk';
function App() {
return (
<ChatbotProvider
apiKey="YOUR_API_KEY"
serverUrl="wss://your-server.com/ws"
>
<YourApp />
<ChatbotWidget />
</ChatbotProvider>
);
}Overriding Default Styles
The SDK auto-injects its styles in a <style> tag at the top of <head>. Any CSS you add in your own stylesheet will automatically take precedence. All widget classes are prefixed navsi-chatbot-*.
/* Example: custom toggle button */
.navsi-chatbot-toggle {
background: #e11d48;
box-shadow: 0 4px 16px rgba(225, 29, 72, 0.4);
}
/* Example: custom chat window size */
.navsi-chatbot-window {
width: 420px;
height: 600px;
}Available CSS Classes
| Class Name | Element |
| ------------------------------------ | ------------------------------------ |
| .navsi-chatbot-container | Root fixed-position container |
| .navsi-chatbot-toggle | Floating open/close button |
| .navsi-chatbot-window | Chat window panel |
| .navsi-chatbot-header | Window header bar |
| .navsi-chatbot-header-left | Header left section (title + status) |
| .navsi-chatbot-title | Header title text |
| .navsi-chatbot-status | Connection status text |
| .navsi-chatbot-clear | "Clear" chat button |
| .navsi-chatbot-mode-toggle | Ask/Action mode toggle container |
| .navsi-chatbot-mode-button | Individual mode button |
| .navsi-chatbot-mode-active | Active mode button |
| .navsi-chatbot-lang-toggle | Language toggle container |
| .navsi-chatbot-lang-button | Individual language button |
| .navsi-chatbot-lang-active | Active language button |
| .navsi-chatbot-messages | Messages scroll area |
| .navsi-chatbot-message | Individual message wrapper |
| .navsi-chatbot-message-user | User message bubble |
| .navsi-chatbot-message-assistant | Assistant message bubble |
| .navsi-chatbot-message-content | Message content (markdown) |
| .navsi-chatbot-message-paragraph | Paragraph inside assistant message |
| .navsi-chatbot-message-list | Bullet list inside assistant message |
| .navsi-chatbot-message-list-item | List item inside assistant message |
| .navsi-chatbot-welcome | Welcome screen container |
| .navsi-chatbot-welcome-icon | Welcome emoji icon |
| .navsi-chatbot-welcome-text | Welcome message text |
| .navsi-chatbot-welcome-hint | Welcome hint/subtitle |
| .navsi-chatbot-input-area | Input area container |
| .navsi-chatbot-input | Text input field |
| .navsi-chatbot-send-button | Send button |
| .navsi-chatbot-voice-button | Voice input button |
| .navsi-chatbot-voice-button-active | Voice button while recording |
| .navsi-chatbot-stop-button | Stop execution button |
| .navsi-chatbot-error | Error banner |
| .navsi-chatbot-error-close | Error dismiss button |
| .navsi-chatbot-voice-error | Voice error message |
| .navsi-chatbot-voice-transcript | Live voice transcript |
| .navsi-chatbot-voice-indicator | Header voice indicator |
| .navsi-chatbot-banner | Execution status banner |
| .navsi-chatbot-pill | Progress step pill |
| .navsi-chatbot-progress-container | Progress bar wrapper |
| .navsi-chatbot-progress-bar | Progress bar track |
| .navsi-chatbot-progress-fill | Progress bar fill |
| .navsi-chatbot-typing | Typing dots indicator |
CSS Custom Properties
You can also set these CSS variables on .navsi-chatbot-container (or let the theme config set them automatically):
| Variable | Default | Description |
| ----------------------- | ----------------- | ------------------------------------- |
| --navsi-primary | #2563eb | Primary brand colour |
| --navsi-primary-hover | #1d4ed8 | Primary hover colour |
| --navsi-bg | #ffffff | Window background |
| --navsi-text | #1f2937 | Text colour |
| --navsi-font | System font stack | Font family |
| --navsi-radius | 12px | Border radius (window, bubbles) |
| --navsi-radius-sm | 6px | Small border radius (inputs, buttons) |
| --navsi-window-width | 360px | Chat window width |
| --navsi-window-height | 520px | Chat window height |
| --navsi-button-size | 56px | Toggle button size |
With Configuration Fetching
For a complete setup with widget configuration from your server:
import React, { useState, useEffect } from 'react';
import { ChatbotProvider, ChatbotWidget } from '@navsi.ai/sdk';
import type { FlatWidgetConfig } from '@navsi.ai/shared';
function App() {
const [widgetConfig, setWidgetConfig] = useState<FlatWidgetConfig | null>(null);
const [configError, setConfigError] = useState<string | null>(null);
const API_KEY = import.meta.env.VITE_NAVSI_API_KEY || process.env.REACT_APP_NAVSI_API_KEY;
const API_BASE = import.meta.env.VITE_NAVSI_API_URL || process.env.REACT_APP_NAVSI_API_URL || 'https://api.example.com';
// Convert HTTP URL to WebSocket URL
const getWebSocketUrl = (httpUrl: string): string => {
const url = new URL(httpUrl);
const wsProtocol = url.protocol === 'https:' ? 'wss:' : 'ws:';
return `${wsProtocol}//${url.host}${url.pathname.replace(/\/$/, '')}/ws`;
};
const WS_URL = getWebSocketUrl(API_BASE);
useEffect(() => {
fetch(`${API_BASE}/api/sdk/config`, {
headers: { 'x-api-key': API_KEY },
})
.then((r) => {
if (!r.ok) throw new Error(`Failed to fetch config: ${r.status}`);
return r.json();
})
.then((data) => {
if (data?.config && typeof data.config === 'object') {
setWidgetConfig(data.config as FlatWidgetConfig);
}
})
.catch((err) => {
console.error('Failed to load widget config:', err);
setConfigError(err.message);
// Widget will still work with default config
});
}, []);
return (
<ChatbotProvider
apiKey={API_KEY}
serverUrl={WS_URL}
config={widgetConfig}
>
<YourApp />
<ChatbotWidget />
</ChatbotProvider>
);
}Next.js (App Router)
Use a Client Component to wrap your app with the chatbot and provide a Next.js navigation adapter so the AI can navigate between pages:
- Create a client component (e.g.
app/ClientProviders.tsx) with'use client'at the top. - Use
useRouter()andusePathname()fromnext/navigation, anduseNextRouterAdapter(router, pathname)from@navsi.ai/sdk. - Wrap your app in
ChatbotProvider(withnavigationAdapter) and renderChatbotWidget. - Set
NEXT_PUBLIC_NAVSI_API_KEYandNEXT_PUBLIC_NAVSI_API_URLin.env.local(WebSocket URL is derived from the API URL).
// app/ClientProviders.tsx
'use client';
import { useRouter, usePathname } from 'next/navigation';
import { ChatbotProvider, ChatbotWidget, useNextRouterAdapter } from '@navsi.ai/sdk';
function getWebSocketUrl(httpUrl: string): string {
const url = new URL(httpUrl);
const wsProtocol = url.protocol === 'https:' ? 'wss:' : 'ws:';
return `${wsProtocol}//${url.host}${url.pathname.replace(/\/$/, '')}/ws`;
}
export function ClientProviders({ children }: { children: React.ReactNode }) {
const router = useRouter();
const pathname = usePathname();
const adapter = useNextRouterAdapter(router, pathname);
const apiKey = process.env.NEXT_PUBLIC_NAVSI_API_KEY ?? '';
const apiUrl = process.env.NEXT_PUBLIC_NAVSI_API_URL ?? 'http://localhost:3001';
const serverUrl = getWebSocketUrl(apiUrl);
return (
<ChatbotProvider apiKey={apiKey} serverUrl={serverUrl} navigationAdapter={adapter} routes={['/', '/products', '/cart']}>
{children}
<ChatbotWidget />
</ChatbotProvider>
);
}In your root app/layout.tsx, wrap your app with <ClientProviders>{children}</ClientProviders> (or nest it inside your layout so the widget is available on all pages).
Features
Ask Mode
- Natural language Q&A about your website
- Context-aware responses based on current page
- Powered by Gemini AI
Navigate Mode
- AI-guided navigation through your website
- Automatic form filling
- Multi-step task completion
Configuration Options
interface ChatbotProviderProps {
// Required
apiKey: string; // Your API key from the admin dashboard
serverUrl: string; // WebSocket server URL (e.g., 'wss://api.example.com/ws')
// Optional
config?: FlatWidgetConfig | null; // Widget config fetched from /api/sdk/config
options?: Partial<WidgetConfig>; // Additional widget configuration (e.g. voiceLanguage: 'hi-IN')
navigationAdapter?: NavigationAdapter; // Custom navigation adapter (defaults to memory)
serverActions?: ServerAction[]; // Server-side actions the AI can execute
routes?: string[]; // List of available routes (for AI context)
debug?: boolean; // Enable debug logging
autoConnect?: boolean; // Auto-connect WebSocket on mount (default: true)
children: React.ReactNode; // Your app components
}Widget Configuration
The config prop accepts a flat widget configuration object fetched from your server:
interface FlatWidgetConfig {
headerTitle?: string;
welcomeMessage?: string;
inputPlaceholder?: string;
showModeToggle?: boolean;
defaultMode?: 'ask' | 'navigate';
defaultOpen?: boolean;
/** BCP-47 language for voice input, output, and AI responses (e.g. 'hi-IN' for Hindi) */
voiceLanguage?: string;
theme?: {
primaryColor?: string;
secondaryColor?: string;
backgroundColor?: string;
textColor?: string;
fontFamily?: string;
borderRadius?: number;
darkMode?: boolean;
position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
};
}Voice language (e.g. Hindi)
Set voiceLanguage to a BCP-47 locale (e.g. 'hi-IN' for Hindi) to:
- Use that language for speech recognition (mic input)
- Use that language for speech synthesis (AI reply read aloud)
- Have the AI respond in that language (e.g. Hindi in Devanagari)
Example:
<ChatbotProvider
apiKey={API_KEY}
serverUrl={WS_URL}
options={{ voiceLanguage: 'hi-IN' }}
>
<ChatbotWidget />
</ChatbotProvider>You can also pass voiceLanguage in the config object from your API. Browser support for Hindi (and other locales) depends on the client; Chrome supports hi-IN for both recognition and synthesis.
Server Actions
Register server-side actions that the AI can execute:
const serverActions = [
{
id: 'add-to-cart',
name: 'Add to Cart',
description: 'Add a product to the shopping cart',
parameters: [
{ name: 'productId', type: 'string', required: true },
{ name: 'quantity', type: 'number', required: false, defaultValue: 1 },
],
handler: async (params, context) => {
// Your logic here
return { success: true, data: { message: 'Added to cart!' } };
},
},
];
<ChatbotProvider
apiKey="YOUR_API_KEY"
serverUrl="wss://your-server.com/ws"
serverActions={serverActions}
>Hooks
useChatbot
Access chatbot state and controls:
import { useChatbot } from '@navsi.ai/sdk';
function MyComponent() {
const {
isConnected,
mode,
setMode,
sendMessage,
messages
} = useChatbot();
}useWebSocket
Access WebSocket connection state:
import { useWebSocket } from '@navsi.ai/sdk';
function ConnectionStatus() {
const { isConnected, isReconnecting } = useWebSocket();
return <div>Status: {isConnected ? 'Connected' : isReconnecting ? 'Reconnecting' : 'Disconnected'}</div>;
}useActionExecution
Track action execution progress:
import { useActionExecution } from '@navsi.ai/sdk';
function ProgressBar() {
const { progress } = useActionExecution();
return progress ? (
<div>Step {progress.current + 1} of {progress.total}</div>
) : null;
}Environment Variables
For production deployments, use environment variables:
# Vite (recommended)
VITE_NAVSI_API_KEY=your_api_key_here
VITE_NAVSI_API_URL=https://api.example.com
# Create React App
REACT_APP_NAVSI_API_KEY=your_api_key_here
REACT_APP_NAVSI_API_URL=https://api.example.com
# Next.js
NEXT_PUBLIC_NAVSI_API_KEY=your_api_key_here
NEXT_PUBLIC_NAVSI_API_URL=https://api.example.comImportant: Never commit API keys to version control. Use environment variables or secure configuration services.
Troubleshooting
Widget doesn't connect
- Check that
serverUrlis correct (usewss://for HTTPS,ws://for HTTP) - Verify your API key is valid
- Check browser console for WebSocket connection errors
- Ensure CORS is configured on your server
Configuration not loading
- Verify the
/api/sdk/configendpoint returns valid JSON - Check that the
x-api-keyheader is included in the request - Widget will fall back to default config if fetch fails
Actions not working
- Ensure
navigationAdapteris provided if using React Router or similar - Check that DOM elements have proper
data-chatbot-actionattributes - Enable
debug={true}to see detailed logs
Development
# From monorepo root
pnpm --filter @navsi.ai/sdk dev # Watch mode
pnpm --filter @navsi.ai/sdk build # Build
pnpm --filter @navsi.ai/sdk lint # LintLicense
MIT
