Features
CRM — The Revenue Engine
The CRM module is the commercial core of OpsDash. It manages the full sales lifecycle: capturing leads, converting them into contacts and deals, managing the pipeline, and logging every interaction. Because CRM data and project data share the same database, OpsDash can calculate revenue metrics no standalone CRM can.
Contacts
Contacts is the central record for every person the agency works with: prospects, clients, contractors, and stakeholders. A contact in OpsDash can be linked to a deal, a company, a project, and an activity — and all of those links are queryable from one place.
- Free: 250 contacts, basic CRUD, table view
- Pro: 10,000 contacts + bulk operations, saved views, CSV import, owner assignment
Key features:
- List page (
/crm/contacts): Sortable, server-side paginated table. Bulk actions on Pro. - Add Contact: Name, email, phone, company, job title, lead source, tags, owner, custom fields.
- Contact detail: Profile sidebar, quick actions (call, email, log activity, create task), linked deals, activities timeline, audit log.
- Saved views (Pro): Save any filter combination as a named view, max 10 per user per org.
- CSV import (Pro): Bulk-create contacts from a CSV upload.
- Tags: Max 30 per contact, enforced by DB trigger.
| Item | Detail |
|---|---|
| Routes | /crm/contacts, /crm/contacts/[id] |
| Server actions | getContactsPaginated, createContact, updateContact, deleteContact, importContactsFromCsv, bulkUpdateContacts |
| Feature flags | crm:contacts (usage-capped), crm:csv-import, crm:contact-fields |
| Audit actions | contact.created, contact.updated, contact.deleted, contact.merged |
Companies
Companies are organizations that contacts belong to and deals are associated with. Supports enrichment fields (renewal dates, upsell opportunity) and a flexible metadata JSONB column for org-specific data.
- Free: 50 companies, basic CRUD
- Pro: 2,000 companies + enrichment, metadata filters
Leads
Leads represent potential opportunities not yet qualified into contacts and deals. The purpose-built lead capture system lets any external tool (Zapier, Make, n8n, web forms) create a lead via API without manual data entry.
- Free: 100 leads, CRUD, lead scoring, conversion
- Pro: 5,000 leads + lead capture API, workflow triggers on conversion
Lead conversion: “Convert to Contact” creates a Contact and Deal atomically from the lead data. The lead is marked converted; the new contact and deal are linked back. Fires any lead_converted workflows.
Lead Capture API: External tools POST to /api/lead-capture with an API key. See API endpoints.
Deals
Deals are the commercial opportunities in the pipeline. The pipeline is a custom kanban board where org admins define the stages. Deal values feed directly into the Dashboard revenue KPIs and profitability calculations.
- Free: 50 deals, pipeline board, custom stages
- Pro: 2,000 deals + deal quotes, CSV import, at-risk detection, weighted forecasting
Key features:
- Kanban board with drag-and-drop stage changes (viewer role: read-only)
- Deal detail: Value, close date, probability, linked contact, company, project
- Deal quotes (Pro): Create, edit, and PDF-export quotes linked to deals
- At-risk detection: Automatically flags deals with no activity for over 7 days
- Workflow integration: Moving a deal to a stage fires
deal_stage_changeworkflows
| Item | Detail |
|---|---|
| Routes | /crm/deals, /crm/deals/[id] |
| Server actions | getDealsPaginated, createDeal, updateDeal, deleteDeal, updateDealStage, getDealQuotes, createDealQuote |
| Feature flags | crm:deals (usage-capped), crm:quotes (Pro), crm:csv-import (Pro) |
| Workflow trigger | deal_stage_change — fired on updateDealStage |
Activities
Activities are the CRM interaction log. Every phone call, email, meeting, and task completion is recorded as an activity linked to a contact, deal, or both.
- Activity types: call, email, meeting, note, task
- Gmail integration (Pro): Syncs sent/received Gmail emails to activities automatically
- Activity feed shows chronological history per contact and per deal
Data cleanup
The Data Cleanup module (/crm/data-cleanup) runs a go-live checklist, finds duplicate contacts (same email) and duplicate deals (same contact + title), and supports keep-first merge for those duplicate groups. Pro only (crm:data-cleanup). Implementation: data-cleanup-content.tsx, use-data-cleanup-content.ts, and siblings under crm/data-cleanup/ (see route README.md).
- Go-live checklist: missing email/name, won/lost reasons, duplicate flags (fix in UI)
- Duplicate groups: contacts by email, deals by contact + title
- Merge keeping first: reassigns relations, soft-deletes merged records