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

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-sdk
import { 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 shortcut
  • threadId: 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) or 0 when closed
  • --sidenet-open1 when open, 0 when closed
  • --sidenet-positionleft or right

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