@iblai/iblai-js
v1.20.2
Published
Unified JavaScript SDK for IBL.ai — re-exports data-layer, web-containers, and web-utils under a single package
Readme
@iblai/iblai-js
Unified JavaScript/TypeScript SDK for building applications on the IBL.ai platform. This package bundles the core IBL frontend libraries under a single namespace with convenient subpath imports for data fetching, UI components, authentication, and utilities.
Installation
npm install @iblai/iblai-js
# or
pnpm add @iblai/iblai-js
# or
yarn add @iblai/iblai-jsPeer Dependencies
The following peer dependencies must be installed in your project:
npm install react react-dom @reduxjs/toolkit react-redux @iblai/iblai-api| Peer Dependency | Version |
| -------------------- | ----------- |
| react | >= 19.1.0 |
| react-dom | >= 19.1.0 |
| @reduxjs/toolkit | >= 2.7.0 |
| react-redux | >= 9.2.0 |
| @iblai/iblai-api | >= 4.166.0-ai |
next (>= 15) is an optional peer dependency, required only when using @iblai/iblai-js/web-containers/next.
@playwright/test and @axe-core/playwright are optional peer dependencies, required only when using @iblai/iblai-js/playwright.
Framework Configuration
Next.js
The SDK ships pre-compiled with 'use client' directives already applied to client components. Do not add @iblai/iblai-js or its sub-packages (@iblai/data-layer, @iblai/web-containers, @iblai/web-utils) to transpilePackages in your next.config.ts — they are ready to use as-is.
// next.config.ts
const nextConfig = {
// Do NOT add @iblai packages here — they ship pre-built dist files
// transpilePackages: ['@iblai/iblai-js'], // ← Don't do this
};Node.js 25+
If you're running Node.js 25 or later, you must disable the experimental Web Storage API in Node.js. Without this flag, Node.js provides a server-side localStorage that conflicts with the SDK's browser-only storage guards, causing hydration errors and runtime failures.
Add this to your package.json scripts:
{
"scripts": {
"dev": "NODE_OPTIONS='--no-experimental-webstorage' next dev",
"start": "NODE_OPTIONS='--no-experimental-webstorage' next start"
}
}Vite / CRA / Other React Frameworks
No special configuration required. Install and import directly.
Styling Setup (Tailwind CSS)
The SDK's React components use Tailwind CSS utility classes. To ensure these classes are included in your app's CSS output, you need two things in your global CSS file:
- Import the SDK's base styles (CSS variables for the IBL design system)
- Add a
@sourcedirective so your Tailwind instance scans the SDK's compiled components for class names
Tailwind CSS v4 (recommended)
In your global CSS file (e.g., app/globals.css):
@import 'tailwindcss';
/* SDK: custom base styles (CSS variables, no Tailwind utilities) */
@import '@iblai/iblai-js/web-containers/styles';
/* SDK: scan compiled components so Tailwind generates their utility classes */
@source "../node_modules/@iblai/iblai-js/dist/web-containers/source";The @source directive tells your Tailwind instance to scan the SDK's compiled JavaScript for class names like lg:grid-cols-2, md:flex, hidden, etc. Without this, responsive and utility classes used only in SDK components won't be generated.
Tailwind CSS v3
In your tailwind.config.js, add the SDK's compiled output to the content array:
module.exports = {
content: [
'./app/**/*.{js,ts,jsx,tsx}',
'./components/**/*.{js,ts,jsx,tsx}',
'./node_modules/@iblai/iblai-js/dist/web-containers/source/**/*.js',
],
};Then import the base styles in your CSS:
@import '@iblai/iblai-js/web-containers/styles';Why this is needed
The SDK does not ship pre-built Tailwind utility CSS. Instead, it ships:
- Base styles (
styles.css) — CSS variables and custom component classes that don't depend on Tailwind - Compiled component source (
source/index.esm.js) — the bundled JavaScript containing all Tailwind class name strings
Your app's single Tailwind instance scans both your own code and the SDK's compiled source, then generates one unified set of utility classes. This avoids CSS cascade conflicts that would occur if two separate Tailwind builds produced overlapping @layer utilities blocks.
Quick Start
1. Initialize the data layer
Call initializeDataLayer once at app startup, before any API calls or store creation. It configures the base URLs and a storage adapter that the SDK uses for token persistence.
import { initializeDataLayer } from '@iblai/iblai-js/data-layer';
import type { StorageService } from '@iblai/iblai-js/data-layer';
// Implement the StorageService interface for your environment.
// For web apps, wrap localStorage; for React Native, use AsyncStorage.
const storageService: StorageService = {
getItem: async (key) => localStorage.getItem(key),
setItem: async (key, value) => localStorage.setItem(key, value),
removeItem: async (key) => localStorage.removeItem(key),
};
initializeDataLayer(
'https://base.manager.iblai.app', // Platform manager URL (dmUrl)
'https://learn.iblai.app', // LMS URL (lmsUrl)
storageService,
// Optional: HTTP error handlers keyed by status code
// { 401: () => redirectToLogin(), 403: () => showForbidden() }
);2. Configure the Redux store
The SDK provides pre-bundled reducers and middleware for quick store setup. Choose the bundle that matches your app:
import { configureStore } from '@reduxjs/toolkit';
import { mentorReducer, mentorMiddleware } from '@iblai/iblai-js/data-layer';
// For Skills apps, use skillsReducer and skillsMiddleware instead
const store = configureStore({
reducer: mentorReducer,
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware().concat(mentorMiddleware),
});
export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;3. Wrap your app with providers
import { Provider } from 'react-redux';
import { AuthProvider, MentorProvider } from '@iblai/iblai-js/web-utils';
function App({ children }) {
return (
<Provider store={store}>
<AuthProvider>
<MentorProvider>
{children}
</MentorProvider>
</AuthProvider>
</Provider>
);
}4. Use hooks and components
import { useChatV2 } from '@iblai/iblai-js/web-utils';
import { Loader } from '@iblai/iblai-js/web-containers';
function ChatPage({ mentorSlug }: { mentorSlug: string }) {
const { messages, sendMessage, isLoading } = useChatV2({ mentor: mentorSlug });
if (isLoading) return <Loader />;
return (
<div>
{messages.map((msg) => (
<p key={msg.id}>{msg.content}</p>
))}
<button onClick={() => sendMessage('Hello!')}>Send</button>
</div>
);
}Subpath Exports
@iblai/iblai-js/data-layer
Redux-based data layer for all IBL.ai API interactions. Built on RTK Query.
Key exports:
| Export | Description |
| --- | --- |
| initializeDataLayer(dmUrl, lmsUrl, storageService, httpErrorHandler?) | One-time SDK initialization (must be called before API usage) |
| mentorReducer / mentorMiddleware | Pre-bundled Redux reducer and middleware for Mentor apps |
| skillsReducer / skillsMiddleware | Pre-bundled Redux reducer and middleware for Skills apps |
| IblDataLayer | Core singleton with storage and config access |
| StorageService | Interface for pluggable persistence (localStorage, AsyncStorage, etc.) |
| STORAGE_KEYS | Constants for token storage keys (DM_TOKEN_KEY, AXD_TOKEN_KEY, EDX_TOKEN_KEY) |
| mentorApiSlice | RTK Query slice for mentor CRUD operations |
| chatApiSlice | RTK Query slice for chat sessions and messages |
| tenantApiSlice | RTK Query slice for tenant management |
| userApiSlice | RTK Query slice for user profiles |
| platformApiSlice | RTK Query slice for platform configuration |
| notificationsApiSlice | RTK Query slice for notification management |
import {
initializeDataLayer,
mentorReducer,
mentorMiddleware,
skillsReducer,
skillsMiddleware,
IblDataLayer,
STORAGE_KEYS,
mentorApiSlice,
chatApiSlice,
} from '@iblai/iblai-js/data-layer';
import type { StorageService } from '@iblai/iblai-js/data-layer';@iblai/iblai-js/web-containers
Framework-agnostic React component library. These components work in any React app (Next.js, Vite, CRA, etc.).
Key exports:
| Export | Description |
| --- | --- |
| Loader | Loading spinner component |
| TenantSwitch | Tenant/organization switcher dropdown |
| useIframeMessageHandler | Hook for cross-iframe communication |
| useLocalStorage | Hook for reactive localStorage state |
| useTimeTracking | Hook for user activity time tracking |
| useTauri | Hook for Tauri desktop app integration |
| isTauriApp | Utility to detect Tauri runtime |
import {
Loader,
TenantSwitch,
useIframeMessageHandler,
useLocalStorage,
} from '@iblai/iblai-js/web-containers';@iblai/iblai-js/web-containers/next
Next.js-specific components and hooks. Requires next as a dependency.
Key exports:
| Export | Description |
| --- | --- |
| SsoLogin | Full SSO login page component |
| initializeLocalStorageWithObject | Populate localStorage from SSO data during login |
| ErrorPage | Server-side error page |
| ClientErrorPage | Client-side error boundary page |
| UserProfileDropdown | User avatar/menu dropdown |
| UserProfileModal | Full user profile editor modal |
| Account | Account settings component |
| OrganizationTab | Organization management tab |
| useTimeTracker | Hook for page-level time tracking (uses next/navigation) |
| useGetChatDetails | Hook for fetching chat session details |
import {
SsoLogin,
ErrorPage,
UserProfileDropdown,
useTimeTracker,
useGetChatDetails,
} from '@iblai/iblai-js/web-containers/next';@iblai/iblai-js/web-containers/sso
Framework-agnostic SSO utilities for handling authentication callbacks. Use these to build custom SSO login flows in any React framework.
Key exports:
| Export | Description |
| --- | --- |
| handleSsoCallback(options?) | Complete SSO callback handler — parses URL params, stores tokens, syncs cookies, and redirects |
| parseSsoData(queryParam) | Decode and parse the base64-encoded SSO data from the callback URL |
| initializeLocalStorageWithObject(data, keys) | Store parsed SSO data into localStorage using configurable keys |
| syncSsoDataToCookies(data) | Sync authentication data to cookies for cross-subdomain sharing |
| setCookie(name, value, days?) | Set a cookie with configurable expiry |
| getBaseDomain() | Extract the base domain for cookie sharing (e.g., example.com from app.example.com) |
| DEFAULT_SSO_STORAGE_KEYS | Default localStorage key names (CURRENT_TENANT, USER_DATA, TENANTS) |
import {
handleSsoCallback,
parseSsoData,
initializeLocalStorageWithObject,
DEFAULT_SSO_STORAGE_KEYS,
} from '@iblai/iblai-js/web-containers/sso';
import type { SsoStorageKeys, HandleSsoCallbackOptions } from '@iblai/iblai-js/web-containers/sso';Example — handling an SSO callback:
// In your SSO callback route (e.g., /sso/callback)
import { handleSsoCallback } from '@iblai/iblai-js/web-containers/sso';
// This parses the URL, stores tokens, syncs cookies, and redirects:
await handleSsoCallback({
redirectUrl: '/dashboard', // Where to go after login
});@iblai/iblai-js/web-utils
Authentication, state management, chat hooks, and general-purpose utilities.
Key exports:
| Export | Description |
| --- | --- |
| AuthProvider | React context provider for authentication state |
| MentorProvider | React context provider for active mentor state |
| TenantProvider | React context provider for tenant/organization state |
| useChatV2 | Primary hook for chat interactions (send messages, stream responses) |
| useAdvancedChat | Extended chat hook with tool use, file attachments, and advanced features |
| useSubscriptionHandler | Hook for managing Stripe subscription flows |
| isLoggedIn() | Check if the current user has a valid session |
| redirectToAuthSpa(options?) | Redirect to the IBL auth SPA for login |
| handleLogout() | Clear tokens and redirect to logout |
| WithPermissions | HOC for role-based access control (RBAC) |
| checkRbacPermission(permission, userPermissions) | Programmatic RBAC permission check |
| chatSlice | Redux slice for chat UI state (selected mentor, session, etc.) |
import {
AuthProvider,
MentorProvider,
TenantProvider,
useChatV2,
useAdvancedChat,
isLoggedIn,
redirectToAuthSpa,
handleLogout,
WithPermissions,
checkRbacPermission,
chatSlice,
} from '@iblai/iblai-js/web-utils';@iblai/iblai-js/playwright
Shared Playwright test utilities for E2E testing across IBL.ai apps. Unlike the other subpaths, this is not a re-export — it contains original source code for test infrastructure shared between standalone app repos (mentorai, skillsai).
Requires: @playwright/test and @axe-core/playwright as dev dependencies.
pnpm add -D @playwright/test @axe-core/playwright dotenv cross-envConfig Generation
Generate a complete Playwright config with per-browser auth setup projects:
// e2e/playwright.config.ts
import { createPlaywrightConfig } from '@iblai/iblai-js/playwright';
import dotenv from 'dotenv';
import path from 'path';
dotenv.config({ path: path.resolve(__dirname, '.env.development') });
export default createPlaywrightConfig({
platforms: [
{
name: 'skills',
dependencies: ['setup'],
otherTestMatch: ['**skills/*/*.spec.ts'],
},
],
});createPlaywrightConfig generates browser-specific setup projects (Chrome, Firefox, Safari, Edge) that each run auth.setup.ts, then creates test projects for each platform/browser combination. The devices option defaults to ['Desktop Chrome', 'Desktop Firefox', 'Desktop Safari', 'Desktop Edge'].
Auth Setup
Create an auth.setup.ts that authenticates once per browser and saves the storage state:
// e2e/auth.setup.ts
import { test as setup, createAuthSetup } from '@iblai/iblai-js/playwright';
setup(
'authenticate',
createAuthSetup({
hostUrl: process.env.SKILLS_HOST || '',
authHost: process.env.AUTH_HOST || '',
appName: 'skills',
postLoginUrlMatcher: (url) =>
url.href.includes('/home') || url.href.includes('/start'),
})
);createAuthSetup supports four auth flows via the authFlow option: 'username_password' (default), 'magic_link', 'sso', and 'direct_sso'. Credentials are read from PLAYWRIGHT_USERNAME and PLAYWRIGHT_PASSWORD env vars.
Custom Reporter
Re-export the SDK's custom reporter for Playwright:
// e2e/custom-reporter.ts
export { CustomReporter as default } from '@iblai/iblai-js/playwright';Test Helpers
import {
// Extended test fixture with step support (optional — most tests use @playwright/test directly)
test,
expect,
// Navigation
safeWaitForURL,
waitForPageLoad,
isFirefox,
// Page interaction
waitForPageReady,
checkAdminStatus,
reliableClick,
reliableFill,
waitForDialogReady,
selectDateFromCalendar,
// Accessibility
expectNoAccessibilityViolations,
expectNoAccessibilityViolationsOnDialogs,
// Auth helpers
loginWithEmailAndPassword,
signUpWithEmailAndPassword,
loginWithMicrosoftIdp,
AuthFlowBuilder,
createAuthSetup,
// Logging
logger,
// Email testing
MailsacClient,
// Config generation
createPlaywrightConfig,
createEnvConfig,
CustomReporter,
} from '@iblai/iblai-js/playwright';Environment Variables
Tests expect these env vars (set them in .env.development or CI):
| Variable | Description |
| --- | --- |
| SKILLS_HOST / MENTOR_NEXTJS_HOST | App host URL |
| AUTH_HOST | Auth service URL |
| PLAYWRIGHT_USERNAME | Login username |
| PLAYWRIGHT_PASSWORD | Login password |
| AUTH_FLOW | Auth flow type (username_password, magic_link, sso, direct_sso) |
| AUTH_IDP | SSO identity provider name (required for sso/direct_sso flows) |
Directory Structure
Both mentorai and skillsai follow this layout:
e2e/
├── playwright.config.ts # Uses createPlaywrightConfig()
├── auth.setup.ts # Uses createAuthSetup()
├── custom-reporter.ts # Re-exports CustomReporter
├── .env.development # Environment variables
├── tests/
│ ├── utils.ts # App-specific env var exports
│ ├── helpers.ts # App-specific auth/login helpers
│ ├── shared.ts # Shared test helper functions
│ └── <platform>/ # Test spec files by feature
└── utils/ # App-specific helper modulesMCP Server (AI-Assisted Development)
This package includes an MCP (Model Context Protocol) server (@iblai/mcp) that provides AI assistants like Claude with authoritative documentation about the IBL packages — components, hooks, API queries, provider setup patterns, and more.
Usage with Claude Code
Option 1 — npx (no install needed):
claude mcp add --transport stdio iblai-js-mcp -- npx @iblai/mcppnpm projects: If your project already has
@iblai/iblai-jsinstalled,npxmay detect the transitive@iblai/mcpdependency locally but fail to link its binary. Usepnpm dlxinstead:claude mcp add --transport stdio iblai-js-mcp -- pnpm dlx @iblai/mcp
Option 2 — after installing @iblai/iblai-js globally:
npm install -g @iblai/iblai-js
claude mcp add --transport stdio iblai-js-mcp -- ibl-mcp-serverOption 3 — project-level config (shared with team via git):
Create a .mcp.json file at your project root:
{
"mcpServers": {
"iblai-js-mcp": {
"command": "npx",
"args": ["@iblai/mcp"]
}
}
}For pnpm projects where @iblai/iblai-js is a dependency:
{
"mcpServers": {
"iblai-js-mcp": {
"command": "pnpm",
"args": ["dlx", "@iblai/mcp"]
}
}
}Claude Code will detect this file and prompt team members to approve the server on first use.
What the MCP Server Provides
| Category | Tool / Resource | Description |
| --- | --- | --- |
| Components | get_component_info | Detailed props, usage examples, and category for any UI component |
| Hooks | get_hook_info | Parameters, return types, and examples for React hooks |
| API Queries | get_api_query_info | RTK Query endpoint details and usage patterns |
| Providers | get_provider_setup | Correct provider hierarchy for each app type |
| Page Templates | create_page_template | Generate new pages following IBL patterns |
| Playwright | get_playwright_helper_info | E2E test helper documentation |
| Guides | ibl://guides/* | Layout rules, RBAC patterns, theming, Playwright setup |
| Package Docs | ibl://packages/* | Full package documentation for each subpath |
Usage with Other MCP Clients
The server uses stdio transport and follows the MCP specification. Any MCP-compatible client can use it:
# Run directly
npx @iblai/mcp
# Or if installed globally via @iblai/iblai-js
ibl-mcp-serverRelationship to Standalone Packages
@iblai/iblai-js is a convenience wrapper. Each subpath is a direct re-export from its standalone package:
| Subpath Import | Source Package |
| -------------------------------------- | ---------------------------- |
| @iblai/iblai-js/data-layer | @iblai/data-layer |
| @iblai/iblai-js/web-containers | @iblai/web-containers |
| @iblai/iblai-js/web-containers/next | @iblai/web-containers/next|
| @iblai/iblai-js/web-containers/sso | @iblai/web-containers/sso |
| @iblai/iblai-js/web-utils | @iblai/web-utils |
| @iblai/iblai-js/playwright | Original source (not a re-export) |
You can use the standalone packages directly if you only need one module. This unified package is useful when you need multiple IBL libraries and prefer a single dependency. The playwright subpath is unique — it contains original source code rather than re-exporting a standalone package.
TypeScript
All subpath exports include TypeScript declarations. Types are co-located with their runtime exports:
import type { StorageService } from '@iblai/iblai-js/data-layer';
import type { SsoStorageKeys, HandleSsoCallbackOptions } from '@iblai/iblai-js/web-containers/sso';
import type { UserProfileDropdownProps, UserMetadata } from '@iblai/iblai-js/web-containers/next';Build
pnpm buildProduces CommonJS, ESM, and TypeScript declaration files under dist/.
Publishing (Maintainers)
This package uses workspace:* references for its dependencies on @iblai/data-layer, @iblai/web-containers, and @iblai/web-utils. These are automatically converted to real version numbers during publish.
You must use pnpm publish (not npm publish) to publish this package. Only pnpm publish converts workspace: references to actual version numbers. Using npm publish will publish with raw workspace:* strings, which breaks installation for all external consumers.
# Correct — converts workspace:* to resolved versions
pnpm publish --no-git-checks
# Wrong — leaves workspace:* in published package.json
npm publish # ← Never use this for workspace packagesPublish the underlying packages first (in dependency order), then this package:
@iblai/data-layer— no internal deps@iblai/web-utils— depends on data-layer@iblai/web-containers— depends on data-layer and web-utils@iblai/iblai-js— depends on all three
Contributing
See CONTRIBUTING.md for the full development guide, including:
- How to make changes to the underlying packages (data-layer, web-utils, web-containers)
- How to test locally with
pnpm linkagainst consumer apps like skillsAI and mentorAI - How the CI publishing pipeline works (tag-based for iblai-js, changeset-based for underlying packages)
- Troubleshooting common issues
License
ISC
