sidenetai-sdk
v2.0.93
Published
Embeddable AI chat sidebar for any web application. Uses Shadow DOM for complete CSS isolation — your styles won't affect the sidebar, and the sidebar won't affect your styles.
Readme
SideNetAI SDK
Embeddable AI chat sidebar for any web application. Uses Shadow DOM for complete CSS isolation — your styles won't affect the sidebar, and the sidebar won't affect your styles.
Features
- Shadow DOM Isolation — Complete CSS encapsulation
- Framework Agnostic — Works with React, Vue, Angular, or vanilla JS
- Two Layout Modes — Sidebar (slides from edge) or Modal (floating panel)
- Full TypeScript Support — Type definitions included
- Runtime Authentication — Pass user credentials for tools (GitHub, Slack, etc.)
- Theming — Light/dark mode with customizable design tokens
- Keyboard Shortcuts — Configurable Cmd/Ctrl+key shortcuts
- Content Push — Optionally push your page content when sidebar opens
- Events — Callbacks, CSS custom properties, and window events
Installation
NPM (React/Next.js/Vite)
npm install sidenetai-sdkimport { initSidenet } from 'sidenetai-sdk';
initSidenet({
orgId: 'your-org-id',
copilotId: 'your-copilot-id',
});CDN (Static sites, WordPress, vanilla JS)
<script src="https://unpkg.com/sidenetai-sdk@latest/dist/sidenetai-sdk.standalone.umd.js"></script>
<script>
Sidenet.initSidenet({
orgId: 'your-org-id',
copilotId: 'your-copilot-id',
});
</script>The standalone bundle (~13MB uncompressed, ~2.8MB gzipped) includes React and all dependencies. Use the NPM package if you already have React.
Quick Start
import { initSidenet, toggleSidenet, sendMessage } from 'sidenetai-sdk';
// Initialize
await initSidenet({
orgId: 'org-123',
copilotId: 'copilot-456',
position: 'right',
defaultOpen: false,
keyboardShortcut: 'k', // Cmd+k / Ctrl+k
});
// Toggle with a button
document.getElementById('chat-btn').onclick = toggleSidenet;
// Send a message programmatically
await sendMessage('Hello!');Configuration
All options for initSidenet():
await initSidenet({
// Required
orgId: string, // Organization ID (sent as X-Organization-Id header)
// Layout
position: 'left' | 'right', // Sidebar position (default: 'right')
width: string, // Panel width, e.g. '400px', '45vw' (default: '45vw')
height: string, // Panel height (modal default: '600px', sidebar: auto)
layout: 'sidebar' | 'modal',// Layout mode (default: 'sidebar')
offset: { // Positioning offsets
top?: string,
bottom?: string,
left?: string,
right?: string,
},
// Behavior
defaultOpen: boolean, // Start open or closed (default: false)
keyboardShortcut: string, // Key for Cmd/Ctrl shortcut, e.g. 'b'
contentElement: string, // CSS selector for content to push aside, e.g. '#app'
debug: boolean, // Enable verbose console logs (default: false)
// Identity
userId: string, // User identifier
copilotId: string, // Copilot identifier
apiKey: string, // API key for backend requests
// Agent & Threading
agentVersionId: string, // Use specific agent (skips agent selection)
groupName: string, // Group name for chat requests
lastThread: boolean, // Auto-select most recent thread on init
threadId: string, // Pin to specific thread
read_only: boolean, // Hide composer (requires threadId)
use_routing: boolean, // Enable backend message routing (default: true)
// Context & Messages
context: string[], // Context strings sent with requests
firstMessage: string, // Auto-send on first open
// Runtime Auth
runtimeAuth: [{
providerName: string,
credentials: Record<string, any>,
}],
// Theming
theme: 'light' | 'dark', // Color scheme (default: 'light')
customCSS: string, // Raw CSS injected into Shadow DOM
customStyles: Record<string, Record<string, string>>, // Structured CSS rules
// Callbacks
onOpen: (detail) => void,
onClose: (detail) => void,
onResize: (detail) => void,
onReady: (detail) => void,
});API Reference
Lifecycle
| Function | Description |
|----------|-------------|
| initSidenet(options) | Initialize the sidebar (async, call once) |
| destroySidenet() | Remove sidebar completely (async, returns Promise) |
Visibility
| Function | Description |
|----------|-------------|
| toggleSidenet() | Toggle sidebar visibility |
| openSidenet() | Open the sidebar |
| closeSidenet() | Close the sidebar |
| getSidenetState() | Returns { isOpen: boolean, isInitialized: boolean } |
| triggerKeyboardShortcut() | Programmatically trigger the shortcut action |
Messaging
| Function | Description |
|----------|-------------|
| sendMessage(text, options?) | Send a message programmatically (async) |
await sendMessage('Analyze this code', {
agentVersionId: 'agent-123', // Optional: use specific agent
openSidebar: true, // Optional: auto-open sidebar (default: true)
});Configuration Updates
| Function | Description |
|----------|-------------|
| updateSidenetConfig(options) | Update config without reinitializing |
| updateSidenetStyledConfig(styleConfig) | Update theme tokens at runtime |
| refreshSidenetConfig() | Re-fetch config from backend (async) |
| refreshSidenetStyles() | Re-apply container styles |
| getRuntimeConfig() | Get current merged config |
updateSidenetConfig() accepts all init options except orgId, plus:
keyboardShortcut: null— Disable shortcutthreadId: null— Clear pinned thread
Runtime Authentication
| Function | Description |
|----------|-------------|
| updateSidenetRuntimeAuth(credentials) | Update auth credentials dynamically |
| getSidenetRuntimeAuthProviders() | Get available auth providers (async) |
// Update credentials after init
updateSidenetRuntimeAuth([
{ providerName: 'github', credentials: { token: 'ghp_...' } },
{ providerName: 'slack', credentials: { token: 'xoxb-...' } },
]);
// Get available providers
const providers = await getSidenetRuntimeAuthProviders();
// [{ providerName: 'github', authType: 'oauth', authFields: ['token'] }, ...]Agents
| Function | Description |
|----------|-------------|
| getAgents(copilotId, apiKey, orgId) | Fetch available subagents (async) |
Events
Three ways to respond to sidebar state changes:
1. Callbacks (Simplest)
initSidenet({
orgId: 'org-123',
onOpen: (detail) => console.log('Opened', detail.width),
onClose: (detail) => console.log('Closed'),
onResize: (detail) => console.log('Resized to', detail.width),
onReady: (detail) => console.log('Ready'),
});2. CSS Custom Properties (Zero-code layout)
.my-content {
margin-right: var(--sidenet-width, 0);
transition: margin 0.3s ease;
}Available properties:
--sidenet-width— Current width (e.g.,400px) or0when closed--sidenet-open—1when open,0when closed--sidenet-position—leftorright
3. Window Events (Decoupled)
window.addEventListener('sidenet:open', (e) => {
console.log('Opened', e.detail.width, e.detail.position);
});
window.addEventListener('sidenet:close', (e) => {
console.log('Closed');
});
window.addEventListener('sidenet:resize', (e) => {
console.log('Resized', e.detail.width);
});
window.addEventListener('sidenet:ready', (e) => {
console.log('Ready');
});Event detail shape:
interface SidenetEventDetail {
width: string; // e.g., '400px'
position: 'left' | 'right';
layout: 'sidebar' | 'modal';
}Theming
Light/Dark Mode
initSidenet({
orgId: 'org-123',
theme: 'dark', // or 'light'
});
// Update at runtime
updateSidenetConfig({ theme: 'light' });Design Tokens
Use updateSidenetStyledConfig() to customize colors, radii, and fonts:
updateSidenetStyledConfig({
theme: {
// Single value applies to both modes
radius: '0.5rem',
fontFamily: '"Inter", sans-serif',
// Per-mode values
background: { light: '#ffffff', dark: '#09090b' },
foreground: { light: '#09090b', dark: '#fafafa' },
accentColor: { light: '#0ea5e9', dark: '#38bdf8' },
userMessageBackground: { light: '#eff6ff', dark: '#1e3a5f' },
},
});Available tokens:
| Token | Description |
|-------|-------------|
| radius | Base border radius |
| composerRadius | Input area radius |
| messageRadius | Message bubble radius |
| suggestionRadius | Suggestion card radius |
| sendButtonRadius | Send button radius (default: pill) |
| headerButtonRadius | Header icon button radius |
| selectRadius | Dropdown trigger radius |
| modalRadius | Modal container radius |
| threadMaxWidth | Max width of conversation area |
| fontFamily | Font family |
| accentColor | Interactive element color |
| background | Main background |
| foreground | Main text color |
| muted | Secondary surface background |
| mutedForeground | Secondary text color |
| border | Border color |
| userMessageBackground | User bubble background |
| userMessageForeground | User bubble text |
| userMessageBorder | User bubble border |
| assistantMessageBackground | Assistant bubble background |
| assistantMessageForeground | Assistant bubble text |
| assistantMessageBorder | Assistant bubble border |
| composerBackground | Input area background |
| suggestionBackground | Suggestion card background |
| suggestionBorder | Suggestion card border |
Custom CSS
initSidenet({
orgId: 'org-123',
customCSS: `
.aui-message-content { font-size: 14px; }
`,
// Or structured:
customStyles: {
'.aui-message-content': { 'font-size': '14px' },
},
});Content Push
Automatically push your page content when the sidebar opens:
initSidenet({
orgId: 'org-123',
position: 'right',
contentElement: '#app', // CSS selector for your main content
});The element will receive margin-right (or margin-left for left position) matching the sidebar width.
TypeScript
All types are exported:
import type {
SidenetOptions,
SidenetEventDetail,
SidenetCallbacks,
RuntimeAuthCredentials,
RuntimeAuthProvider,
Subagent,
SidebarSDKConfig,
SidebarRuntimeConfig,
ThemeTokens,
ThemeInput,
} from 'sidenetai-sdk';React Hook
For React apps, use the useSidebarConfig hook to access runtime config:
import { useSidebarConfig } from 'sidenetai-sdk';
function MyComponent() {
const config = useSidebarConfig();
return <div>Greeting: {config.text.greeting.title}</div>;
}Advanced: Direct Component Usage
For full control, use the Sidebar component directly:
import { Sidebar } from 'sidenetai-sdk';
<Sidebar
config={{
position: 'right',
width: '400px',
userId: 'user-123',
copilotId: 'copilot-456',
}}
onWidthChange={(width) => console.log(width)}
onAgentChange={(agentId) => console.log(agentId)}
/>License
MIT
