Skip to content
iblaiPublic

About

Open-source CRM for organizations on the ibl.ai platform: people, organizations, deals, activities and tags, with ibl.ai single sign-on and roles. One Next.js codebase for web, macOS, Windows, Linux, iOS and Android through Tauri. MIT.

Topics

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

94 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ibl.ai

ibl.ai/crm

The open-source CRM for organizations on the ibl.ai platform.

People, organizations, deals, activities and tags — for every organization you belong to, with ibl.ai single sign-on and roles built in. One codebase. Every platform. Your data, your organization, your rules.

Join About Docs License: MIT SOC 2 Type II Next.js Tauri


⬇️ Get ibl.ai/crm

Web — crm.ibl.ai, coming soon   macOS — coming soon   Windows — coming soon

iOS — coming soon   Android — coming soon

Hosted web app and published builds coming soon · today: run it locally or deploy it yourself · how builds are made


Watch the intro video

▶︎ Watch the intro video  ·  Organizations, people, deals, activities and tags in under five minutes


Why ibl.ai/crm · Every platform · Features · Case studies · Screenshots · Quick Start · Deployment · Architecture


SOC 2 Type II  ·  Universities, enterprises, and governments run on ibl.ai — read the case studies →


Why ibl.ai/crm

🔓 Your code, your data MIT-licensed and self-hostable. The CRM records live in your ibl.ai organization, scoped by the platform's own multi-tenancy — no second database, no vendor lock-in.
🏢 Every organization you own Sign in once with ibl.ai SSO and switch between all of your organizations, exactly like os.ibl.ai. Each organization gets its own people, pipelines, deals and roles.
🧭 The Twenty way, on ibl.ai The information architecture of Twenty — objects in a sidebar, saved table & board views, favorites, record pages with a timeline and a history — built on the ibl.ai CRM API and SDK components.
🌍 Four languages English, Spanish, French and Chinese, following the language you chose in any other ibl.ai app.
📱 Truly everywhere One codebase for web, macOS, Windows, Linux, iOS and Android — native shells around the same app. The hosted web app and published builds are coming soon.
🔐 Enterprise-ready SSO (OAuth / OIDC / SAML via the platform), four seeded CRM roles (Viewer, User, Manager, Inviter), org-level notifications, invitations that turn leads into platform users.

Every platform, one codebase

ibl.ai/crm meets your team wherever they are — the same product, native everywhere.

Platform Status
Web 🌐 Coming soon at crm.ibl.ai — today, run it locally or deploy it yourself
macOS 🍎 Native app (universal .dmg, Intel + Apple Silicon) — built by the release workflow; downloads coming soon
Windows 🪟 Native app (x64 + ARM64 installer) — built by the release workflow; downloads coming soon
Linux 🐧 Native app (AppImage) — built by the desktop build workflow; downloads coming soon
iOS 📱 Native app — built by the iOS workflow; App Store listing coming soon
Android 🤖 Native app — built by the Android workflow; Google Play listing coming soon

The native apps are Tauri 2 WebView shells around the hosted app (src-tauri/), so they load crm.ibl.ai and work once it is live — or point them at your own deployment (docs/development.md). They are built the same way iblai/os and iblai/lms ship. Sign-in on mobile goes through the system browser and returns via the iblai-crm:// deep link. See docs/platform-deployment.md.


Features

👥 People & organizations

  • People — leads, contacts and customers with lifecycle stage, owner, job title, emails, phones, and tags; merged duplicates stay out of the way
  • Organizations — accounts with address, owner and tags; the people, deals and the timeline that belong to them
  • Invite · link · merge — turn a lead into a platform user by email invitation, link a person to an existing user, or merge duplicates
  • Tags — colored labels shared across people, organizations and deals
  • Search, sort, views — server-side search and sorting on every list; save a view with its filters, sort and columns (table or board); star anything into the sidebar's Favorites

💼 Deals & pipelines

  • Kanban board — drag deals between stages; columns show count, value and win probability; stale deals are flagged after the pipeline's rotten_days
  • Table view — filter by status, owner, source, tags; page through everything
  • Deal page — stage stepper, mark won / lost (with reason), reopen, value & currency, expected close, timeline, field-change history
  • Pipelines & stages — seeded default pipeline (New → Qualified → Proposal → Negotiation → Won / Lost); create your own, reorder stages, set probabilities and terminal flags; lead sources

🗓️ Activities

  • Timeline on every person, organization and deal — calls, meetings, emails, notes, tasks, lunches, deadlines
  • Schedule — scheduled work with an owner; overdue / today / upcoming views; mark done
  • Auto-recorded history — stage changes are logged for you

📊 Home

  • Dashboard — open deals, pipeline and weighted value, won this month, work due today; deals by stage; won vs lost over six months; what's up next — with a period picker (today, 7, 30, 90 days)

🏢 Operate & scale

  • Multi-organization — the organization is in the URL (/platform/<org>/…); switch between every organization you belong to from the profile menu
  • SSO & roles — ibl.ai sign-in; CRM Viewer / User / Manager / Inviter roles assigned in the sidebar's Management dialog (the SDK's Management surface)
  • Notifications — person created, deal stage changed, person linked to user — in the bell and the notifications center
  • ⌘K — one server-side search across people, organizations and deals; jump anywhere; create anything
  • Native shells — macOS, Windows, Linux, iOS and Android via Tauri 2; published builds coming soon

Case studies

Universities, enterprises, and government agencies build on ibl.ai — deploying agents on their own infrastructure, with their own models, at a fraction of the cost of closed platforms.

Read the case studies →


Screenshots

Screenshots of the seeded walkthrough organization are on their way — run pnpm screenshots to regenerate them into docs/images/ (see docs/development.md).


Quick Start

git clone https://github.com/iblai/crm.git
cd crm
pnpm install --ignore-scripts
pnpm dev

Open http://localhost:3000. It sends you to login.iblai.app, where Sign Up creates an organization at ibl.ai and brings you back signed in; you land on /platform/<your-org> — the CRM of the organization your session is scoped to. Use the switcher in the profile menu to move between organizations. A user whose only organization is the community one gets its trial-gated shell there, on a sample organization; an admin’s first visit opens the setup flow. See the full Development Guide for setup, scripts, architecture and configuration.

No configuration is required against hosted iblai.app: the service URLs default in lib/iblai/config.ts. Copy .env.example to .env.local only to point at a self-hosted platform or to change the community org (NEXT_PUBLIC_MAIN_TENANT_KEY, default main).

Using Claude Code? This repo ships with the iblai/vibe skills in mind — read AGENTS.md first.

Node.js 22+ and pnpm 12 (corepack enable picks the pinned version up from package.json).

Node.js 25+ note: the dev script sets NODE_OPTIONS='--no-experimental-webstorage' so the SDK's browser-storage guards do not collide with Node's experimental localStorage. Keep that flag if you customize the script.

Scripts

Command What it does
pnpm dev Dev server on port 3000
pnpm build Production build (standalone output)
pnpm start Serve the production build
pnpm typecheck TypeScript 7
pnpm lint oxlint, under a warning budget (--max-warnings)
pnpm format oxfmt (pnpm format:check in CI)
pnpm i18n:check Same keys in the four catalogs; no “tenant”, no “company”, no ASCII apostrophe
pnpm test Vitest unit tests (pnpm test:coverage in CI: 85 % lines on lib/)
pnpm test:e2e Playwright journeys, Chromium and a phone (pnpm test:e2e:all for every browser)
pnpm e2e:accounts Once: the two e2e test accounts in the throwaway organization iblai.env names
pnpm e2e:coverage The journey registry (e2e/coverage.json) against the specs and the app's pages
pnpm release release-it: version from the commits, CHANGELOG, tag, GitHub Release (CI runs it on every push to main)
pnpm tauri:dev / tauri:build Desktop shell (needs Rust); pnpm tauri:dev:ios / tauri:dev:android for a simulator or emulator
pnpm shell:smoke / shell:smoke:windows The shell headless against a local page: the navigation guard and both sign-in returns (CI runs the Linux one on every shell change)
pnpm shell:touch / shell:touch:windows / shell:touch:ios / shell:touch:android The built shell on this machine (Linux, macOS, Windows), on an iOS simulator or on an Android phone, with the touch-test checklist (docs)
pnpm shell:clear [android, ios] / shell:clear:windows Forgets the shell's cookies, localStorage and caches on this machine, the phone or the simulator, so the next touch test starts signed out

Deployment

ibl.ai/crm is a front end for the ibl.ai platform. The platform provides sign-in, organizations, roles, notifications and the CRM API; this repository provides the app.

Option A: Hosted ibl.ai platform

  1. Build and run with Node

    pnpm build
    cp -r public .next/standalone/ && cp -r .next/static .next/standalone/.next/
    PORT=3000 node .next/standalone/server.js

    The build is a standalone server, so next start does not apply; the two copies are what the Dockerfile does. On Vercel nothing of this is needed: the project builds the regular Next.js output (vercel.json pins the preset) and only wants ENABLE_EXPERIMENTAL_COREPACK=1 so pnpm 12 is used.

  2. Or run with Docker

    docker build -t iblai-crm .
    docker run -p 3000:3000 iblai-crm

    NEXT_PUBLIC_* values are inlined at build time and .env* files stay out of the image, so a self-hosted platform passes its URLs as build arguments: --build-arg NEXT_PUBLIC_API_BASE_URL=https://api.example.com --build-arg NEXT_PUBLIC_AUTH_URL=https://login.example.com --build-arg NEXT_PUBLIC_PLATFORM_BASE_DOMAIN=example.com (omit them for hosted iblai.app). The Dockerfile declares these three and NEXT_PUBLIC_MAIN_TENANT_KEY; any other NEXT_PUBLIC_* setting needs an ARG of its own there.

  3. Register the origin. Every origin the app runs on (http://localhost:3000, https://crm.example.com, the iblai-crm:// native scheme) must be an allowed redirect origin of the organizations that sign in, or the Auth SPA never returns. Ask your ibl.ai operator.

Option B: Self-hosted platform

Set the service URLs in .env.local for pnpm dev and pnpm build, or as Docker build arguments (above); see Configuration. If you need the full backend, reach out at ibl.ai/contact for an enterprise license and deploy it with iblai/iblai-infra-cli.

Every surface, on your own backend

Ship Web, macOS, Windows, Linux, iOS and Android pointed at your own deployment — one web codebase, with the native apps as WebView shells around it:

→ Platform deployment guide (per-surface build, backend config, release, store submission).

Build-time flags (native apps)

The Tauri shell reads two optional compile-time flags (Rust option_env!) and exposes them as commands; set them in the build shell before pnpm tauri build. The web app does not read these commands yet, so neither flag changes the app today — the organization lock and the in-app purchase UI are coming soon:

Env var Tauri command Default Effect
IBL_TENANT get_locked_tenant → string "" (unlocked) Organization lock (coming soon): the organization a build is meant for. Empty = multi-org.
IBL_ALLOW_IN_APP_PURCHASE allow_in_app_purchase → bool false In-app purchase UI (coming soon). Truthy: 1, true, yes, on.
IBL_TENANT=acme pnpm tauri build   # a build meant for the "acme" organization

Configuration

All app config is NEXT_PUBLIC_* and optional against hosted iblai.app. Defaults live in lib/iblai/config.ts.

Variable Default Description
NEXT_PUBLIC_API_BASE_URL https://api.iblai.app Consolidated API; /dm (CRM), /lms, /axd are derived from it
NEXT_PUBLIC_AUTH_URL https://login.iblai.app The hosted Auth SPA
NEXT_PUBLIC_PLATFORM_BASE_DOMAIN iblai.app Base domain; with no API base, services resolve to their own subdomains
NEXT_PUBLIC_MAIN_TENANT_KEY main The community organization — the trial-gated shell for a user who belongs to nothing else
NEXT_PUBLIC_IBL_PLATFORM crm app= sent to the Auth SPA (its crm app: CRM copy, Sign Up goes to registration)
NEXT_PUBLIC_TAURI_CUSTOM_SCHEME iblai-crm Deep-link scheme the native shells return through after SSO
NEXT_PUBLIC_DEFAULT_CURRENCY USD Currency preselected on new deals
NEXT_PUBLIC_ENABLE_RBAC false Gate SDK admin surfaces on RBAC policies as well as the admin flag

Architecture

crm/
├── app/
│   ├── page.tsx                          # `/` → /platform/<session org>
│   ├── platform/[tenantKey]/             # everything inside one organization
│   │   ├── layout.tsx                    # sidebar + top bar shell (admin gate)
│   │   ├── page.tsx                      # Home dashboard
│   │   ├── people/ · organizations/      # lists + record pages (timeline · history)
│   │   ├── deals/                        # kanban · table · deal page
│   │   ├── activities/ · tags/           # timeline work · labels
│   │   ├── settings/                     # pipelines · stages · lead sources
│   │   └── notifications/[[...id]]/      # SDK NotificationDisplay
│   ├── sso-login-complete/               # SSO landing (outside the providers)
│   ├── mobile-sso-login/                 # native deep-link landing
│   └── api/auth-redirect/                # same-origin hop to the Auth SPA
├── components/crm/                       # sidebar, top bar, ⌘K, record widgets
├── components/ui/                        # shadcn/ui (Base UI) primitives
├── hooks/                                # useSession, useMembers
├── lib/crm/                              # CRM types · RTK Query slice · formatting · saved-view helpers
├── i18n/ · messages/                     # next-intl config · en/es/fr/zh catalogs
├── lib/iblai/                            # config · tenant resolution · auth helpers
├── providers/iblai-providers.tsx         # Redux > AuthProvider > TenantProvider
├── store/iblai-store.ts                  # SDK slices + crmApi
├── src-tauri/                            # Tauri 2 shell (macOS · Windows · Linux · iOS · Android)
├── e2e/ · __tests__/                     # Playwright journeys · Vitest
└── docs/                                 # deployment, downloads, development

Data flow

User → React pages → RTK Query (lib/crm/api.ts) → https://api.iblai.app/dm/api/crm/…
                                    ↓                       Authorization: Token <dm_token>
                           @iblai/iblai-js SDK
                           ├── /web-utils        AuthProvider · TenantProvider · tenant switch
                           ├── /web-containers   profile dropdown · notifications · Account/Management
                           └── /data-layer       platform users · org metadata

Sign-in is the platform's hosted round trip (login.<domain>/login?app=crm&redirect-to=<origin>&tenant=<org> → /sso-login-complete?data=…). TenantProvider compares the organization in the URL with the one the session is scoped to and re-authenticates when they differ, handing back an org-scoped token pair. The CRM API infers the organization from that token — there is no ?platform_key= — so every record you see belongs to the organization in the URL. A route organization the user does not belong to is previewed — its name and logo, Join, Create Your Own Platform — while the app runs on their own organization underneath. On the community organization everyone browses the sample data. A signed-in user who holds no CRM role in the organization they entered is sent back to the one they came from, or to one they administer; with neither, to ibl.ai registration (the free plan ibl.ai/join resolves to), coming back signed in to the organization it created. Details: docs/development.md.

The CRM API

Ten Platform-scoped resources under /dm/api/crm/: persons, organizations, pipelines (with nested stages and stages/reorder/), lead-sources, deals (move-stage/, won/, lost/, the board/), activities (done/), tags (attach / detach on persons, organizations, deals), favorites and saved views — plus search/, overview/ and …/{id}/history/, and ?search= / ?ordering= / ?date_filter= on every list. Every organization is seeded with a default pipeline, six stages and four lead sources. The full contract lives in the iblai-api-crm and iblai-vibe-crm-overview skills of iblai/vibe. This release needs ibl-dm-pro 4.416.0 (ibl-dm-crm-app 1.3.0).


Testing

This project is covered by Vitest unit tests in __tests__/ and Playwright end-to-end journeys in e2e/. Run the journeys for any change so nothing regresses:

Command What it does
pnpm test Vitest — formatting, saved views, permissions, organization resolution, SSO landing, config, the house journeys
pnpm shell:smoke The Tauri shell headless (shell:smoke:windows on Windows): the navigation guard and both sign-in returns on a local page
pnpm i18n:check en / es / fr / zh catalogs carry the same keys and the house vocabulary
pnpm test:coverage The unit tests with the coverage gate CI runs
pnpm e2e:accounts Once: an admin and a CRM User member in the throwaway organization iblai.env names
pnpm test:e2e Playwright journeys, Chromium + a phone
pnpm test:e2e:all The same journeys in every browser
pnpm test:e2e:ui Interactive UI mode
pnpm test:e2e:headed Run with a visible browser
pnpm e2e:coverage The journey registry against the specs and the app’s pages

See e2e/COVERAGE.md for current coverage. Coverage must not regress — add or update a journey whenever you change user-facing behavior.

The Playwright suite has the OS's shape — numbered journeys in e2e/journeys/, page objects, a coverage registry (e2e/coverage.json, e2e/COVERAGE.md) with a checker — and signs in once per browser through the real Auth SPA (e2e/auth.setup.ts) as the two accounts pnpm e2e:accounts creates in a throwaway organization, never main. Get that organization's iblai.env from /iblai-vibe-connect run from an empty directory with --origin http://localhost:3000 and move it here. Every record the journeys create is E2E-prefixed and swept at the end of the run. See e2e/README.md.


Contributing

We welcome contributions! See CONTRIBUTING.md. If you use AI-assisted tooling, read AGENTS.md first — it explains the SDK-first component rule, the multi-organization model, and how to verify a change.


Resources


License

MIT License. See LICENSE for details.


ibl.ai · Your organization's AI, under your control.

About

Open-source CRM for organizations on the ibl.ai platform: people, organizations, deals, activities and tags, with ibl.ai single sign-on and roles. One Next.js codebase for web, macOS, Windows, Linux, iOS and Android through Tauri. MIT.

Topics

Resources

Contributing

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages