Dashboard & Analytics
LiveA 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
LiveThe 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
LivePhysical 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
LiveB2B 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
LiveThe 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
LiveEvery 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
LiveA 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
LiveThe 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)
LiveWorkspace-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
LiveStorefront 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
LiveTwo 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
LiveTwo 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
LiveEverything 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
LiveFull 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