All features

Every module, documented.

Detailed breakdown of every Obriym CRM module — capabilities, architecture notes, and the decisions behind each design. Use the anchors below to jump to any section.

Dashboard & Analytics

Live

A single view into the health and momentum of your workspace. Track every active lead, deal, activity, and team member from one screen — with real revenue forecasting, not just activity counts.

Capabilities

  • Lead metrics row: active, qualified, stale, overdue next steps
  • Pipeline metrics: pipeline value, weighted forecast, overdue activities, stale deals
  • Win rate card: won/lost count, revenue split, progress bar
  • Avg deal cycle card: average days from open to won
  • Revenue forecast chart grouped by expected close month
  • Conversion funnel: New → Contacted → Qualified → Open Deal → Won
  • Team activity chart: completed vs open per member this week
  • Leads needing attention list with stale/overdue badge
  • Lead status distribution with progress bars
  • Recent workspace activity audit feed
  • Widget lead analytics: submissions per widget config this week

Leads

Live

The entry point of every sales cycle. Leads capture the first contact before qualification. Stale detection surfaces at-risk records automatically, and conversion creates downstream CRM records in one atomic operation.

Architecture notes

  • Status flow: New → Contacted → Qualified → Unqualified / Converted
  • nextActionDate is mandatory for qualified leads — no deal can progress without a next step
  • Conversion uses db.batch() with a request-specific UUID marker to prevent concurrent duplicate creation
  • Server-to-server lead intake via POST /api/v1/leads with Bearer token scope leads:write
  • Browser lead capture via JS widget with origin allowlist and rate limiting

Capabilities

  • List with search (name, email, company), filters (status, source, assignee, stale), pagination via nuqs
  • Stale detection: overdue nextActionDate OR no update in 7 days
  • Lead score 0–100 with auto-decay (−3/day after 3 inactive days)
  • 360° detail page: next action block, contact info, notes, tags, timeline
  • Quick inline status and assignee change without leaving the detail page
  • 1-click conversion: creates Contact + Company + Deal atomically with duplicate detection
  • Built-in sources (website, referral, cold call, social, email, event, partner, other) + custom workspace sources
  • Owner-managed source settings: add custom slugs, archive unused sources

Contacts

Live

Physical persons — clients, partners, contacts within companies. Every contact has a complete interaction history, linked deals, and order context visible in one 360° card.

Capabilities

  • List with search (name, email, company), filters (company, owner, tags), pagination
  • Full 360° detail: company link, job title, contact details, tags, owner
  • Related deals island: open pipeline + won deals + lifetime value
  • Order history island: workspace-scoped orders linked to this contact
  • Activity timeline: all CRM activities, calls, meetings, notes in chronological order
  • Create and edit form with React Hook Form and sticky FormBar

Companies

Live

B2B clients and potential clients — the account-level context alongside individual contacts. Lifetime value, relationship status, and a full interaction timeline visible in one place.

Capabilities

  • List with search, industry and status filters, pagination
  • Detail: key contacts list, industry, size, website, status, owner
  • Open deals island: all non-terminal deals linked to this company
  • Lifetime value: sum of won deals + completed orders
  • Won deal purchases island: product snapshot from deal line items
  • Order history island: workspace-scoped orders linked to this company
  • Activity timeline across all team interactions

Deals & Pipeline

Live

The core of the sales pipeline. Deals move through configurable stages with validated transitions. The catalog integration lets managers see margin and deal total in real time — without a separate spreadsheet.

Architecture notes

  • deal_products junction stores price snapshot at time of addition — unit price can be overridden by manager
  • deals.amount is always = SUM(unit_price × qty × (1 - discount/100)) recalculated via SQL subquery on every product mutation
  • Pipeline stages are workspace-scoped; terminal behavior (won/lost) is stable in v1

Capabilities

  • Kanban board with nuqs-based filters and drag-and-drop via @dnd-kit/core
  • Stage transition validation: Closed Lost requires a lost reason
  • Weighted forecast = amount × probability on every deal card
  • Deal detail: title, amount, probability, expected close date, next action
  • Deal products editor: inline qty/price/discount, add from catalog, amount auto-recalculates
  • Lost reason tracking for post-mortem analysis
  • Owner-configurable pipeline stages: name and default probability
  • Stale deal detection: no update in 14 days

Activities & Tasks

Live

Every interaction type in one place. Tasks, calls, meetings, email follow-ups, and notes all share the same timeline — so the full communication history is visible on the entity card.

Architecture notes

  • Activities are append-only in v1 — no delete. Each activity is an audit record of a real interaction.
  • crm_activities.assignedTo triggers an in-app notification to the assignee if they are a different user

Capabilities

  • Types: task, call, meeting, email, note
  • Priorities: low, medium, high
  • Due date, completion flow (complete / reopen)
  • Assignment to workspace members with in-app notification
  • Overdue filter: activities past due date
  • EntityActivities island on Lead, Contact, Company, Deal detail pages
  • Quick-create from entity detail with pre-filled entity link
  • Daily digest email: overdue activities summarised per workspace

Customers & Retention

Live

A post-sale view of companies that have at least one won deal. Health is computed from the last CRM activity date — no extra schema needed. At-risk and churned customers surface automatically.

Architecture notes

  • No separate customers table — derived from crm_companies + crm_deals (kind=won) + crm_activities
  • Health state is computed on the fly in the server function, not stored in DB

Capabilities

  • Workspace-scoped customer list sorted by lifetime value
  • Health scoring: healthy (≤30 days), at_risk (31–90 days), churned (>90 days or no activity)
  • Churn-risk filter on the customers list
  • Lifetime value = sum of won deals + completed orders
  • Customer detail redirects to Company 360° view (deals, contacts, orders, timeline)

Catalog & Products

Live

The product catalog is the single source of truth for pricing and inventory — used in deal line items, order snapshots, and exposed via read-only public API for connected storefronts.

Architecture notes

  • SKU uniqueness is per-workspace (UNIQUE(organizationId, sku)) — same SKU can exist in different workspaces
  • Archiving a product that is in a bundle is blocked — the bundle must be updated first
  • Image pathnames use stable Blob paths: workspaces/{orgId}/products/{productId}/{imageId}.ext

Capabilities

  • Products: name, SKU (unique per workspace), type (simple/bundle), status (draft/active/archived)
  • Fields: price, compareAtPrice, currency, weight, dimensions, stock, trackInventory
  • Images: up to 10 per product, 2 MB max, drag-to-sort, Vercel Blob CDN delivery
  • Bundle editor: select simple products as components with quantities (no recursive bundles)
  • Categories: tree structure with parentId, up to 3 levels recommended
  • Brands: workspace-scoped, optional FK on product
  • API access: GET /api/v1/products, /products/:id, /products/sku/:sku with Bearer token
  • Used in deal products editor and order line items

Orders (E-commerce Vertical)

Live

Workspace-scoped orders for e-commerce operations. Orders are fully isolated between workspaces. Importable via public API with idempotency — designed for webhook-based storefront integrations.

Architecture notes

  • totalAmount is a validated snapshot computed from line items at import — never derived later
  • crm_order_items.productId is nullable — orders can reference catalog products or store a name-only snapshot for deleted products
  • All write paths use atomic db.batch() — Neon HTTP driver does not support callback transactions
  • Concurrent intake is serialized via advisory lock per workspace+operation+externalId

Capabilities

  • Status workflow: pending → confirmed → processing → shipped → delivered / cancelled / refunded
  • Line items: product name snapshot, SKU, unit price, quantity, discount
  • Optional link to Contact or Company CRM record
  • Source tracking: website, api, manual, portal
  • Idempotent import via POST /api/v1/orders with externalId
  • Status lookup via GET /api/v1/orders/:externalId
  • Audit trail: every status change leaves an activity log record
  • Lifetime value includes completed orders alongside won deals

Storefront Customer Sync

Live

Storefront customer sync lets connected e-commerce platforms push registered buyer profiles into the CRM workspace. The CRM does not own the storefront login — it is a projection of the buyer from the platform.

Architecture notes

  • The CRM never implicitly creates or merges CRM Contact records during intake — identity matching is a separate deliberate operation
  • Bearer token remains server-to-server only — browser bundles never receive it
  • storefront_customers.integrationSourceId scopes every query to a single platform integration

Capabilities

  • POST /api/v1/customers: upsert registered storefront customer profile
  • UNIQUE identity: organizationId + integrationSourceId + externalId
  • Optional customer snapshot on order: registered checkout links external customer ID
  • Guest checkout: no customer profile required — order stores buyer snapshot
  • Rate-limited, audited, workspace-isolated

Notifications

Live

Two delivery channels: in-app bell with popover list and daily email digest. Notifications are scoped per workspace and per user — each workspace member only sees their own alerts.

Architecture notes

  • workspace_notification_deliveries ensures at-most-once delivery per user per day even under Cron retries
  • workspace_notifications stores per-user in-app notification records with readAt timestamp
  • Notification bell uses Suspense streaming — it never blocks the sidebar render

Capabilities

  • In-app notifications: bell in sidebar, unread badge, click-to-navigate and mark-read
  • Daily digest email: overdue activities, stale leads, stale deals — per workspace preferences
  • Assignment notifications: lead assign, activity assign, deal owner change
  • Workspace notification preferences: toggle each signal type (owner/manager only)
  • Vercel Cron at 06:00 UTC — deduplication per organization + recipient + date

Team & Access

Live

Two levels of access control: workspace organization roles for CRM access, and Better Auth admin plugin for platform-level administration. Roles affect both UI visibility and server-function permissions.

Architecture notes

  • owner: full access including team management, API tokens, settings
  • manager: full CRM pipeline access — no team management, no API token access
  • viewer: read-only access to all CRM modules and dashboard
  • Workspace-local suspension is stored in workspace_suspension table — does not touch the global user account

Capabilities

  • Owner, Manager, Viewer workspace roles via Better Auth organization plugin
  • Email invitations with /invite/:id onboarding screen (email locked from invitation)
  • Workspace-local suspension: blocks access without global account ban
  • Member detail page: CRM summary (open activities, active leads, open deals)
  • Active workspace selector for users in multiple workspaces
  • Role-based navigation and permission checks in every server function

Settings

Live

Everything workspace-specific in one place. Pipeline configuration, source management, integration keys, notification preferences, and workspace profile.

Capabilities

  • Pipeline stage editor: rename stages, set default probability (owner only)
  • Lead source settings: built-in sources without seed rows, add custom slugs, archive unused
  • API tokens: generate with least-privilege scopes, one-time reveal, revoke
  • JS widget configurations: create, origin allowlist, one-time key reveal, revoke, key rotation
  • Workspace currency: ISO 4217, inherited by new products and orders
  • Notification preferences: per-signal toggle (overdue activities, stale leads, stale deals)
  • Workspace name editing (owner)
  • Theme: light / dark / system

API & Integrations

Live

Full REST API surface for e-commerce integration: read and write leads, customers, and orders. Status transitions with validation. Platform adapters for WooCommerce (live), Shopify and Telegram (planned). All endpoints are contract-first with OpenAPI 3.1 spec.

Architecture notes

  • Scopes: products:read, leads:read, leads:write, customers:read, customers:write, orders:read, orders:write
  • Every API request is workspace-isolated: Bearer token resolves the organization, all queries scope to it
  • Idempotent writes use a durable DB record — safe to replay under network failures
  • PATCH /orders/:externalId validates status transitions — terminal orders cannot be updated

Capabilities

  • JS Widget: <script> embed, origin allowlist, rate limit (10 req/min), honeypot anti-spam
  • REST API: 7 scopes, Bearer tokens, rate limits, OpenAPI 3.1 + interactive /api-docs
  • GET /api/v1/leads + GET /api/v1/leads/:id — read leads (leads:read)
  • POST /api/v1/leads — create lead (leads:write)
  • GET /api/v1/customers + GET /api/v1/customers/:externalId — read customers (customers:read)
  • POST /api/v1/customers — upsert storefront customer (customers:write)
  • GET /api/v1/orders + GET /api/v1/orders/:externalId — read orders (orders:read)
  • POST /api/v1/orders — import order (orders:write)
  • PATCH /api/v1/orders/:externalId — update order status (orders:write)
  • GET /api/v1/products + /products/:id + /products/sku/:sku — catalog (products:read)
  • WooCommerce adapter: POST /api/v1/adapters/woocommerce/:configId (HMAC-SHA256)
  • Platform adapters: Shopify, Telegram — planned next

Start your workspace

Sign up and your workspace is provisioned automatically. No onboarding wizard. No demo data.

Get started

Embed the JS widget

One script tag captures leads from any website into your workspace — with origin allowlist and spam protection.

View widget docs

Integrate via REST API

OpenAPI 3.1 spec, interactive reference, and scoped Bearer tokens for lead, order, and customer sync.

Open API docs