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

codiris-brainboard-sdk

v1.2.2

Published

Embed Codiris Brainboard whiteboard functionality into your applications

Readme

Codiris Brainboard SDK

Embed Codiris Brainboard whiteboard functionality into your applications. Build collaborative visual experiences with AI-powered features.

Installation

npm install codiris-brainboard-sdk
# or
yarn add codiris-brainboard-sdk
# or
pnpm add codiris-brainboard-sdk

Getting Your API Key

Before using the SDK, you need to generate an API key:

  1. Go to Codiris Settings
  2. Navigate to Settings & Members → API Keys
  3. Click Create Key in the "Brainboard SDK Keys" section
  4. Give your key a name (e.g., "Production", "Development")
  5. Optionally, configure allowed domains for security
  6. Copy the generated key - it will only be shown once!

Key Format

SDK keys have the format: brb_live_xxxxxxxxxxxxxxxxxxxx (or brb_test_ for test keys)

Domain Restrictions

For production, you can restrict which domains can use your API key:

  • Leave empty for development (allows all domains)
  • Add specific domains like app.example.com, localhost:3000
  • Supports wildcard subdomains: *.example.com

Quick Start

Basic Usage (Vanilla JS/TS)

import { BrainboardClient } from 'codiris-brainboard-sdk';

// Initialize the client
const client = new BrainboardClient({
  apiKey: 'brb_live_your-api-key-here',
  baseUrl: 'https://app.codiris.ai', // optional, defaults to production
});

// List boards
const { data: boards } = await client.listBoards();

// Create a board
const { data: board } = await client.createBoard({
  name: 'My Board',
  description: 'A collaborative whiteboard',
});

// Add objects to the board
await client.createObject(board.id, {
  type: 'sticky',
  x: 100,
  y: 100,
  width: 200,
  height: 200,
  text: 'Hello World!',
  fill: '#ffeb3b',
});

React Usage

import { BrainboardProvider, BrainboardEmbed, useBoards } from 'codiris-brainboard-sdk/react';

// Wrap your app with the provider
function App() {
  return (
    <BrainboardProvider
      apiKey={process.env.NEXT_PUBLIC_BRAINBOARD_API_KEY}
      baseUrl={process.env.NEXT_PUBLIC_BRAINBOARD_BASE_URL || "https://talk.codiris.build/api"}
    >
      <MyComponent />
    </BrainboardProvider>
  );
}

// Use the embed component
function MyComponent() {
  const { boards, createBoard } = useBoards();

  return (
    <div>
      <button onClick={() => createBoard({ name: 'New Board' })}>
        Create Board
      </button>

      {boards[0] && (
        <BrainboardEmbed
          boardId={boards[0].id}
          width="100%"
          height="600px"
          showToolbar
          onBoardChange={(board) => console.log('Board updated:', board)}
        />
      )}
    </div>
  );
}

Important: The BrainboardEmbed component automatically includes your API key in the iframe URL for authentication. This is necessary because iframes cannot send custom HTTP headers. To protect your API key:

  1. Use environment variables - Never hardcode your API key
  2. Set domain restrictions - Configure allowed domains in your API key settings
  3. Use HTTPS only - Always serve your app over HTTPS in production

Features

Board Management

// List boards with filtering
const { data } = await client.listBoards({
  status: 'active',
  search: 'project',
  page: 1,
  pageSize: 20,
});

// Get a specific board
const { data: board } = await client.getBoard('board-id');

// Update a board
await client.updateBoard('board-id', {
  name: 'Updated Name',
  isPublic: true,
});

// Delete a board
await client.deleteBoard('board-id');

// Duplicate a board
const { data: newBoard } = await client.duplicateBoard('board-id', 'Copy of Board');

Objects (Canvas Elements)

// Create various object types
await client.createObject(boardId, {
  type: 'text',
  x: 100, y: 100,
  text: 'Hello World',
  fontSize: 24,
});

await client.createObject(boardId, {
  type: 'shape',
  x: 200, y: 200,
  width: 150, height: 100,
  shapeType: 'rectangle',
  fill: '#3b82f6',
});

await client.createObject(boardId, {
  type: 'sticky',
  x: 400, y: 100,
  width: 200, height: 200,
  text: 'Idea #1',
  fill: '#fef08a',
});

// Batch create
await client.createObjects(boardId, [
  { type: 'sticky', x: 100, y: 100, text: 'Task 1' },
  { type: 'sticky', x: 320, y: 100, text: 'Task 2' },
  { type: 'sticky', x: 540, y: 100, text: 'Task 3' },
]);

// Update objects
await client.updateObject(boardId, objectId, {
  text: 'Updated text',
  fill: '#22c55e',
});

// Delete objects
await client.deleteObject(boardId, objectId);
await client.deleteObjects(boardId, [id1, id2, id3]);

Supported Object Types

| Type | Description | |------|-------------| | sticky | Sticky note with text | | text | Text block | | shape | Shapes (rectangle, circle, triangle, diamond, star, etc.) | | line | Connecting line | | arrow | Arrow connector | | image | Image element | | card | Card with title, description, tags | | table | Data table | | kanban | Kanban board | | code | Code block with syntax highlighting | | chart | Chart (line, bar, pie, etc.) | | embed | External embed (YouTube, Figma, etc.) | | frame | Presentation frame | | draw | Freehand drawing |

Collaboration

// Get board members
const { data: members } = await client.getMembers(boardId);

// Invite a member
await client.inviteMember(boardId, '[email protected]', 'editor');

// Update member role
await client.updateMemberRole(boardId, memberId, 'viewer');

// Remove a member
await client.removeMember(boardId, memberId);

// Generate share link
const { data } = await client.generateShareLink(boardId, {
  canEdit: false,
  expiresAt: '2024-12-31T23:59:59Z',
});
console.log(data.shareUrl);

Comments

// Get comments
const { data: comments } = await client.getComments(boardId);

// Add a comment
await client.addComment(boardId, 'Great idea!', objectId);

// Reply to a comment
await client.addComment(boardId, 'I agree!', objectId, parentCommentId);

// Resolve a comment
await client.resolveComment(boardId, commentId);

AI Features

// Generate content
const { data } = await client.generateContent({
  prompt: 'Create a user journey map for an e-commerce checkout flow',
  type: 'diagram',
});

// Chat with AI about board content
const { data: response } = await client.chat(boardId, [
  { role: 'user', content: 'What are the main themes on this board?' }
]);
console.log(response.content);
console.log(response.sources); // Cited sources from the board

// Execute natural language commands
await client.executeCommand(boardId, 'make all sticky notes blue');
await client.executeCommand(boardId, 'align selected items to the left', selectedIds);

// Generate audio overview
const { data: audio } = await client.generateAudioOverview(boardId, 'podcast');
console.log(audio.audioUrl, audio.script);

Templates

// List templates
const { data: templates } = await client.listTemplates('brainstorming');

// Create from template
const { data: board } = await client.createFromTemplate(
  'template-id',
  'My Brainstorm Session'
);

// Save board as template
await client.saveAsTemplate(boardId, 'My Template', 'Reusable board layout');

Import & Export

// Import from URL
await client.importFromUrl(boardId, 'https://example.com/article', { x: 100, y: 100 });

// Extract from PDF
await client.extractPdf(boardId, 'https://example.com/document.pdf');

// Create from interview data
await client.createFromInterview(interviewId, 'Interview Summary Board');

// Export
const { data: json } = await client.exportAsJson(boardId);
const { data: image } = await client.exportAsImage(boardId, 'png', { scale: 2 });
const { data: pdf } = await client.exportAsPdf(boardId, { includeFrames: true });

React Hooks

useBoard(boardId)

const { board, loading, error, updateBoard } = useBoard('board-id');

useBoards(options?)

const { boards, total, loading, createBoard, deleteBoard } = useBoards({
  status: 'active',
  page: 1,
});

useBoardObjects(boardId)

const {
  objects,
  selectedObjects,
  createObject,
  updateObject,
  deleteObject,
  selectObject,
  clearSelection,
} = useBoardObjects('board-id');

useBoardMembers(boardId)

const { members, inviteMember, removeMember } = useBoardMembers('board-id');

useBoardComments(boardId, objectId?)

const { comments, addComment, deleteComment } = useBoardComments('board-id');

useBrainboardChat(boardId)

const { messages, loading, sendMessage, clearMessages } = useBrainboardChat('board-id');

// Send message with source grounding
await sendMessage('What patterns do you see?', true);

useBrainboardGenerate()

const { loading, generate } = useBrainboardGenerate();

const result = await generate({
  prompt: 'Create a SWOT analysis template',
  type: 'diagram',
});

useBrainboardEvent(type, callback)

useBrainboardEvent('object:created', (event) => {
  console.log('New object:', event.data);
});

useTemplates(category?)

const { templates, createFromTemplate } = useTemplates('planning');

React Components

<BrainboardEmbed />

Full-featured embedded board editor.

<BrainboardEmbed
  boardId="board-id"
  width="100%"
  height="600px"
  readOnly={false}
  showToolbar={true}
  showSidebar={false}
  showComments={true}
  showMinimap={true}
  theme="light"
  onReady={() => console.log('Ready!')}
  onBoardChange={(board) => console.log(board)}
  onObjectSelect={(objects) => console.log(objects)}
/>

<BrainboardViewer />

Read-only board viewer.

<BrainboardViewer
  boardId="board-id"
  width="100%"
  height="400px"
  showNavigation={true}
  autoFit={true}
/>

<BrainboardThumbnail />

Board thumbnail preview.

<BrainboardThumbnail
  board={board}
  width={200}
  height={150}
  onClick={() => navigate(`/boards/${board.id}`)}
/>

<BrainboardList />

Grid view of boards.

<BrainboardList
  boards={boards}
  gridColumns={3}
  onSelect={(board) => setSelectedBoard(board)}
  emptyMessage="No boards yet"
/>

Events

Listen to real-time events:

import { globalEvents } from 'codiris-brainboard-sdk';

globalEvents.on('board:updated', (event) => {
  console.log('Board updated:', event.data);
});

globalEvents.on('object:created', (event) => {
  console.log('Object created:', event.data);
});

globalEvents.on('user:joined', (event) => {
  console.log('User joined:', event.data);
});

// Listen to all events
globalEvents.onAll((event) => {
  console.log(`${event.type}:`, event.data);
});

Event Types

| Event | Description | |-------|-------------| | board:loaded | Board finished loading | | board:updated | Board properties changed | | object:created | New object added | | object:updated | Object modified | | object:deleted | Object removed | | object:selected | Objects selected | | object:deselected | Selection cleared | | camera:moved | Viewport changed | | user:joined | User joined the board | | user:left | User left the board | | cursor:moved | User cursor moved | | comment:added | New comment added | | error | Error occurred |

Configuration

const client = new BrainboardClient({
  // Required
  apiKey: 'your-api-key',

  // Optional
  baseUrl: 'https://app.codiris.ai/api', // Custom API endpoint
  workspaceId: 'workspace-id',            // Default workspace
  userId: 'user-id',                      // Current user ID
  userEmail: '[email protected]',          // Current user email
  userName: 'User Name',                  // Current user name
  externalUserId: 'your-user-123',        // External user ID for board isolation
  debug: false,                           // Enable debug logging
});

User Isolation (Multi-tenancy)

When embedding Brainboard in your application, you can isolate boards per user using the externalUserId feature. This allows each user in your system to have their own private set of boards without seeing boards from other users.

How It Works

  1. Pass your user's unique ID as externalUserId when initializing the client
  2. When creating boards, they are automatically tagged with this external user ID
  3. When listing boards, only boards belonging to that user are returned

Example: Per-User Board Isolation

// Initialize client with your user's ID
const client = new BrainboardClient({
  apiKey: 'brb_live_your-api-key',
  externalUserId: currentUser.id, // Your application's user ID
});

// This user only sees their own boards
const { data: boards } = await client.listBoards();

// Boards created are tagged with this user's ID
const { data: board } = await client.createBoard({
  name: "Alice's Board",
});
// board.externalUserId === currentUser.id

Using Headers Directly

You can also pass the external user ID via HTTP headers:

// When making API requests directly
fetch('/api/brainboard/boards', {
  headers: {
    'Authorization': `Bearer ${apiKey}`,
    'X-External-User-Id': 'your-user-123',
  },
});

Switching Users

To demonstrate different user views (useful for admin/support scenarios):

function UserBoardView({ userId }: { userId: string }) {
  return (
    <BrainboardProvider
      apiKey={apiKey}
      externalUserId={userId} // Each user sees only their boards
    >
      <BoardList />
    </BrainboardProvider>
  );
}

Query Parameters

You can also filter boards by external user ID using query parameters:

GET /api/brainboard/boards?externalUserId=user_alice_123

Testing User Isolation

Visit /test/sdk in your Codiris dashboard to test user isolation. The test bench allows you to:

  1. Connect with your API key
  2. Switch between simulated users (Alice, Bob, Charlie)
  3. Create boards for each user
  4. See how boards are isolated per user

TypeScript Support

The SDK is fully typed. Import types as needed:

import type {
  Board,
  BoardObject,
  BoardMember,
  CreateBoardInput,
  CreateObjectInput,
  BrainboardConfig,
} from 'codiris-brainboard-sdk';

Error Handling

All API methods return a consistent response format:

const response = await client.getBoard('board-id');

if (response.success) {
  console.log(response.data);
} else {
  console.error(response.error);
}

With React hooks, errors are exposed via the error property:

const { board, loading, error } = useBoard('board-id');

if (error) {
  return <div>Error: {error.message}</div>;
}

Security Best Practices

Protect Your API Keys

  • Never commit API keys to version control - Use environment variables instead
  • Use domain restrictions in production - Limit which domains can use your key
  • Create separate keys for different environments - Use brb_test_ keys for development
  • Rotate keys periodically - Revoke and regenerate keys if compromised
  • Monitor usage - Check the API Keys dashboard for unusual activity

Environment Variables

# .env.local (DO NOT commit this file)
NEXT_PUBLIC_BRAINBOARD_API_KEY=brb_live_xxxxxxxxxxxxxxxxxxxx
NEXT_PUBLIC_BRAINBOARD_BASE_URL=https://app.codiris.ai
// Use environment variables
<BrainboardProvider
  apiKey={process.env.NEXT_PUBLIC_BRAINBOARD_API_KEY}
  baseUrl={process.env.NEXT_PUBLIC_BRAINBOARD_BASE_URL}
>
  <App />
</BrainboardProvider>

Managing Keys

You can manage your SDK keys at any time:

  • Create new keys: Settings → API Keys → Create Key
  • View usage: See request counts and last used date
  • Update domains: Modify allowed domains for existing keys
  • Revoke keys: Deactivate keys that are no longer needed

Troubleshooting

Having issues? Check our Troubleshooting Guide for common problems and solutions:

  • 401 Authentication Required - API key configuration issues
  • Environment Variables Not Loading - .env file setup
  • Board Not Loading - Access and permissions issues
  • CORS Errors - Domain and security configuration

Support

License

MIT