Development Guide
Mirrored from
iblai/osΒ·docs/development.md. This page is generated β edit it in the repository, not here.
Prerequisites
- Node.js 25.3.0+ (we recommend using nvm)
- pnpm 10+ β
npm install -g pnpm
Quick Start
1. Clone the repository
git clone https://github.com/iblai/os.git
cd os
2. Install dependencies
pnpm install
3. Configure environment
cp .env.example .env.local
Edit .env.local with your ibl.ai platform credentials:
# Required β your ibl.ai platform URLs
NEXT_PUBLIC_AUTH_URL=https://login.iblai.app
NEXT_PUBLIC_API_BASE_URL=https://api.iblai.app
NEXT_PUBLIC_LEGACY_LMS_URL=https://learn.iblai.app
# Required β your tenant key
NEXT_PUBLIC_MAIN_TENANT_KEY=main
# Required β WebSocket and voice servers
NEXT_PUBLIC_BASE_WS_URL=wss://asgi.data.iblai.app
NEXT_PUBLIC_IBL_LIVE_KIT_SERVER_URL=wss://livekit.call.iblai.app
# App URLs
NEXT_PUBLIC_MENTOR_URL=http://localhost:3000
NEXT_PUBLIC_MENTOR_IFRAME_URL=http://localhost:3000
# Feature flags
NEXT_PUBLIC_IBL_PLATFORM=mentor
NEXT_PUBLIC_IBL_TEMPLATE_MENTOR=ai-mentor
NEXT_PUBLIC_IBL_ALLOW_FREE_TRIAL_BANNER=true
NEXT_PUBLIC_STRIPE_ENABLED=false
NEXT_PUBLIC_ENABLE_ADVERTISING=false
NEXT_PUBLIC_API_BASE_URLpoints at the consolidated ibl.ai API gateway β the SDK derives/lms,/dm, and/axdpath prefixes from it, so you don't need to setNEXT_PUBLIC_LMS_URL,NEXT_PUBLIC_DM_URL, orNEXT_PUBLIC_AXD_URLseparately unless you're targeting a self-hosted stack with distinct subdomains.
4. Start the dev server
pnpm dev
Open http://localhost:3000 in your browser.
Node.js 25+ note: The
devscript already includes--no-experimental-webstorageto prevent conflicts with the SDK's browser storage guards. If you customize your scripts, make sure to includeNODE_OPTIONS='--no-experimental-webstorage'.
Scripts
| Script | Description |
|---|---|
pnpm dev | Start development server (port 3000) |
pnpm build | Production build (standalone output) |
pnpm start | Start production server via server-wrapper.js |
pnpm lint | Run ESLint with --fix, then typecheck |
pnpm lint:check | Lint without auto-fix (CI mode) |
pnpm typecheck | TypeScript type checking (tsc --noEmit) |
pnpm format | Format code with Prettier |
pnpm format:check | Prettier check without writing (CI mode) |
pnpm format-lint | Run format then lint |
pnpm test | Run unit tests (Vitest) |
pnpm test:watch | Run tests in watch mode |
pnpm test:coverage | Generate test coverage report |
pnpm test:ui | Vitest UI runner |
pnpm test:e2e | Playwright end-to-end (seeds empty .auth fixtures) |
pnpm test:e2e:ui | Playwright UI runner |
pnpm test:e2e:headed | Playwright in a visible browser |
pnpm tauri:dev | Start Tauri desktop dev mode |
pnpm tauri:build | Build Tauri desktop app |
pnpm tauri:build:debug | Tauri debug build (sourcemaps, faster) |
pnpm release | Cut a release via release-it |
pnpm prepare | Install husky hooks (runs on pnpm install) |
Testing
pnpm test # unit tests (Vitest)
pnpm test:watch # watch mode
pnpm test:coverage # coverage report
pnpm test:e2e # Playwright end-to-end
pnpm test:e2e:ui # Playwright UI runner
pnpm test:e2e:headed # run in a visible browser
pnpm test:e2eauto-seeds empty Playwright auth fixtures underplaywright/.auth/before running β no manual setup needed.
Architecture
os/
βββ app/ # Next.js App Router
β βββ platform/ # Main authenticated routes
β β βββ [tenantKey]/ # Multi-tenant routing (agent pages nest below)
β βββ create-mentor/ # Agent creation wizard
β βββ share/ # Public shared chats
β βββ reports/ # Analytics report export
β βββ provider-association/ # Stripe / OAuth provider linking
β βββ google-oauth-callback/ # Google OAuth return
β βββ sso-login/ # SSO entry
β βββ sso-login-complete/ # SSO callback
β βββ mobile-sso-login/ # Mobile-specific SSO entry
β βββ mobile/ # Touch-optimized mobile routes
β βββ uploads/ # File upload preview
β βββ error/ # Branded error pages (404, 500, β¦)
β βββ version/ # Build info endpoint
β βββ api/ # API routes (auth-redirect, health)
β
βββ components/ # React components
β βββ ui/ # 54 shadcn/ui primitives
β βββ chat/ # Chat message rendering
β βββ advanced-chat/ # Advanced chat builder + tabs
β βββ chat-input-form/ # Input controls (voice, search, upload)
β βββ canvas/ # Document canvas (artifacts)
β βββ header/ # Top app bar
β βββ sidebar/ # Nav + project switcher
β βββ mentors/ # Agent cards, lists, picker
β βββ modals/ # All modal dialogs
β β βββ edit-mentor-modal/ # Agent settings (LLM, datasets, access, β¦)
β βββ projects/ # Project management
β βββ welcome-chat/ # Landing / welcome screen
β βββ workflows/ # Workflow builder UI
β βββ markdown/ # Markdown + code renderers
β βββ model-download/ # Local LLM download UI (Tauri)
β βββ top-trial-banner/ # Free-trial / billing banners
β βββ icons/ # Custom icons
β βββ accessibility/ # A11y helpers
β
βββ features/ # Feature modules (state + logic) β 13 modules
β βββ analytics/ # Analytics logic
β βββ auth/ # Auth slice
β βββ chat/ # Chat state machine
β βββ chat-input/ # Input model
β βββ mentors/ # Agent CRUD
β βββ messages/ # Message normalization
β βββ navigation/ # Sidebar + route state
β βββ provider-association/ # Stripe / OAuth flow
β βββ rbac/ # Role-based access control
β βββ subscription/ # Billing & subscription
β βββ tenants/ # Multi-tenant routing helpers
β βββ top-banner/ # Banner copy + visibility rules
β βββ users/ # User CRUD + invites
β
βββ hooks/ # 151 custom React hooks
β βββ use-voice-chat.ts # LiveKit voice integration
β βββ use-mentors.ts # Agent CRUD operations
β βββ use-history.ts # Chat history management
β βββ use-datasets.ts # Training data management
β βββ subscription/ # Subscription hooks
β βββ ...
β
βββ lib/ # Utilities and configuration
βββ providers/ # React context providers
βββ store/ # Redux store setup
βββ styles/ # Global CSS
βββ public/ # Static assets (LLM provider logos, fonts, env.js)
βββ src-tauri/ # Tauri desktop app (Rust)
βββ url-routes/ # Centralized route constants used by app + tauri shell
βββ scripts/ # Build / release helpers (post-build, etc.)
βββ docs/ # Internal documentation
Data Flow
User β React Components β Custom Hooks β Redux (RTK Query) β ibl.ai API
β
@iblai/iblai-js SDK
βββ /data-layer (API slices, reducers)
βββ /web-utils (auth, providers, chat hooks)
βββ /web-containers (shared UI components)
The app uses @iblai/iblai-js as its unified SDK, which bundles the data layer, authentication utilities, and shared components under a single package.
Configuration
Environment Variables
| Variable | Required | Description |
|---|---|---|
NEXT_PUBLIC_AUTH_URL | Yes | Authentication service URL (e.g. https://login.iblai.app) |
NEXT_PUBLIC_API_BASE_URL | Yes | Consolidated API gateway base (e.g. https://api.iblai.app) β the SDK appends /lms, /dm, /axd |
NEXT_PUBLIC_LEGACY_LMS_URL | No | Direct LMS host for asset URLs that can't be proxied (e.g. https://learn.iblai.app) |
NEXT_PUBLIC_LMS_URL | No | Override LMS path; defaults to ${API_BASE}/lms |
NEXT_PUBLIC_DM_URL | No | Override DM path; defaults to ${API_BASE}/dm |
NEXT_PUBLIC_AXD_URL | No | Override AXD path; defaults to ${API_BASE}/axd |
NEXT_PUBLIC_MAIN_TENANT_KEY | Yes | Primary tenant identifier |
NEXT_PUBLIC_BASE_WS_URL | Yes | WebSocket server URL |
NEXT_PUBLIC_IBL_LIVE_KIT_SERVER_URL | Yes | LiveKit voice server URL |
NEXT_PUBLIC_MENTOR_URL | Yes | This app's public URL |
NEXT_PUBLIC_IBL_PLATFORM | Yes | Platform type (mentor) |
NEXT_PUBLIC_IBL_TEMPLATE_MENTOR | Yes | Default agent template slug |
NEXT_PUBLIC_STRIPE_ENABLED | No | Enable Stripe billing (true/false) |
NEXT_PUBLIC_IBL_ALLOW_FREE_TRIAL_BANNER | No | Show free trial banner |
NEXT_PUBLIC_ENABLE_ADVERTISING | No | Enable advertising features |
NEXT_PUBLIC_ENABLE_RBAC | No | Enable RBAC permission checks |
NEXT_PUBLIC_EXTERNAL_PRICING_PAGE_URL | No | External pricing page URL |
NEXT_PUBLIC_HIDE_ANALYTICS | No | Hide the analytics surface entirely |
NEXT_PUBLIC_DISABLED_DATASETS | No | Pipe-separated dataset types to hide (e.g. zip|courses) |
NEXT_PUBLIC_DISABLED_ANALYTICS_REPORTS | No | Pipe-separated analytics reports to hide |
NEXT_PUBLIC_MENTOR_TRAINING_MAXIMUM_FILE_SIZE | No | Max dataset upload size in MB |
NEXT_PUBLIC_MAXIMUM_CHARACTER_SIZE_TO_COPY | No | Max pasted characters before text becomes a .txt upload |
NEXT_PUBLIC_SHOW_BASE_MENTOR | No | Show the base/template agent in the picker |
NEXT_PUBLIC_MENTOR_SETTINGS_DISCLAIMER | No | Disclaimer line shown under agent settings |
NEXT_PUBLIC_ENABLE_GRAVATAR_ON_PROFILE_PIC | No | Fall back to Gravatar when no profile pic |
NEXT_PUBLIC_DEFAULT_EMBED_CSS_URL | No | CSS injected into iframe embeds |
NEXT_PUBLIC_IBL_ENABLE_SPECIAL_LOGO_WHEN_IFRAMED | No | Swap the logo when running inside an iframe |
NEXT_PUBLIC_IFRAME_FROM_OLD_MENTOR | No | Legacy agent URL allowed to iframe this app |
NEXT_PUBLIC_HELP_CENTER_URL | No | Help center link in the UI |
NEXT_PUBLIC_SUPPORT_EMAIL | No | Support email shown in dialogs |
NEXT_PUBLIC_APP_BANNER_TEXT | No | Top app banner copy |
NEXT_PUBLIC_APP_BANNER_LINK | No | Banner click-through URL |
NEXT_PUBLIC_APP_BANNER_LINK_TEXT | No | Banner CTA text |
NEXT_PUBLIC_APP_BANNER_BADGE | No | Small badge label next to the banner |
NEXT_PUBLIC_SHOW_APP_BANNER | No | Toggle the top banner |
NEXT_PUBLIC_PLATFORM_BASE_DOMAIN | No | Brand domain (defaults to iblai.app) |
NEXT_PUBLIC_BASE_PATH | No | URL base path for subdirectory deployments |
NEXT_IMAGE_PATTERNS | No | Comma-separated allowed image hosts |
NEXT_PUBLIC_IBL_SENTRY_DSN | No | Sentry DSN for client-side error reporting |
SENTRY_AUTH_TOKEN | No | Sentry auth token (build-time only) |
Feature Flags
Feature flags are set via environment variables prefixed with NEXT_PUBLIC_. They control which features are visible and active in the application:
- Stripe billing β
NEXT_PUBLIC_STRIPE_ENABLED=true - Free trial banner β
NEXT_PUBLIC_IBL_ALLOW_FREE_TRIAL_BANNER=true - Advertising β
NEXT_PUBLIC_ENABLE_ADVERTISING=true - RBAC β
NEXT_PUBLIC_ENABLE_RBAC=true - Iframe logo β
NEXT_PUBLIC_IBL_ENABLE_SPECIAL_LOGO_WHEN_IFRAMED=true
Sentry
OS wires Sentry via sentry.client.config.ts, sentry.server.config.ts, and sentry.edge.config.ts at the repo root. Two env vars control it:
NEXT_PUBLIC_IBL_SENTRY_DSNβ runtime DSN for client/server error reporting. Leave empty to disable.SENTRY_AUTH_TOKENβ build-time only; letsnext buildupload source maps so stack traces stay readable in production. Without it the build still succeeds, just with minified frames in Sentry.
SDK version pin
The exact @iblai/iblai-js version this app is tested against lives in .iblai-js-version. The pre-push hook checks package.json against it; bump both when you intentionally move SDK versions, otherwise leave it alone.
Tech Stack
| Layer | Technology |
|---|---|
| Framework | Next.js 15, React 19, TypeScript |
| Styling | Tailwind CSS 4, Radix UI, shadcn/ui |
| State | Redux Toolkit, React-Redux |
| Forms | React Hook Form, Zod |
| Editor | Tiptap (rich text), Markdown (react-markdown, remark, rehype) |
| Voice/Video | LiveKit (WebRTC) |
| Charts | Recharts |
| Desktop | Tauri 2 (Rust + WebView) |
| Testing | Vitest, Testing Library, Playwright |
| Monitoring | Sentry |
| SDK | @iblai/iblai-js (version pinned in .iblai-js-version) |
AGENTS.md
AGENTS.md at the repo root documents the formatting, lint, and push-protocol rules that automated agents (Claude Code, OpenCode, etc.) follow when editing this codebase. Read it before you start contributing β it's also what the husky hooks enforce. CLAUDE.md is a symlink to it for tools that still look for that filename.
The skills it references live under .claude/skills/:
.claude/skills/prettier-format.mdβ formatter rules and the pre-commit hook.claude/skills/safe-push.mdβ push protocol; never bypass the pre-push hook.claude/skills/e2e-coverage.mdβ whene2e/coverage.jsonneeds an update
Built With
- Next.js β App Router
- @iblai/iblai-js β SDK for auth, UI components, and data
- @iblai/data-layer β RTK Query data layer
- @iblai/web-containers β framework-agnostic SDK components
- LiveKit β WebRTC transport for real-time voice and video sessions
- Tailwind CSS β utility-first styling with ibl.ai design tokens
- shadcn/ui β accessible UI primitives
- Tauri 2 β desktop and mobile shell (Rust + WebView)
- Sentry β error monitoring and source maps
- iblai.app β production backend for auth, AI agents, billing, and analytics