Build a full CRM system in Bubble with data types for Contacts, Companies, and Deals, a Kanban-style pipeline view using Repeating Groups, activity logging on every interaction, and a reporting dashboard. This tutorial covers the complete architecture from database design to sales workflow automation.
Overview: Building a CRM System in Bubble
A CRM (Customer Relationship Management) system tracks your contacts, companies, deals, and interactions in one place. This tutorial builds a complete CRM from scratch in Bubble — including a contact database, deal pipeline with drag-style stage progression, activity logging, and dashboards. It is designed for non-technical founders who want a custom CRM tailored to their sales process.
Prerequisites
- A Bubble account on Growth plan or higher (for database capacity)
- Basic understanding of Data Types, Workflows, and Repeating Groups
- Familiarity with privacy rules and user roles
- A clear picture of your sales pipeline stages
Step-by-step guide
Design the CRM data model
Design the CRM data model
Go to the Data tab and create these Data Types: 'Contact' with fields: first_name (text), last_name (text), email (text), phone (text), company (Company), status (Option Set: Lead/Prospect/Customer/Churned), owner (User), notes (text), created_by (User). Create 'Company' with fields: name (text), website (text), industry (text), size (text), contacts (list of Contact). Create 'Deal' with fields: title (text), value (number), stage (Option Set: Qualification/Proposal/Negotiation/Closed Won/Closed Lost), contact (Contact), company (Company), owner (User), close_date (date), probability (number). Create 'Activity' with fields: contact (Contact), deal (Deal), type (Option Set: Call/Email/Meeting/Note), description (text), logged_by (User).
Pro tip: Create the Option Sets first (Contact Status, Deal Stage, Activity Type) before creating the Data Types that reference them.
Expected result: Four Data Types and three Option Sets are set up in the Data tab ready for use.
Build the contact list and detail view
Build the contact list and detail view
Create a page called 'contacts.' Add a Repeating Group with data source: Do a search for Contact, sorted by Created Date descending. In each cell, display first_name, last_name, email, company's name, and status. Add a Search Input above the Repeating Group and use it as a constraint on the search (first_name contains Search Input's value or last_name contains Search Input's value). When a user clicks a row, navigate to a 'contact-detail' page passing the Contact's unique ID as a URL parameter. On the detail page, display all contact fields, a list of related Activities, and related Deals.
Expected result: A searchable contact list that links to individual contact detail pages with full history.
Create the deal pipeline Kanban view
Create the deal pipeline Kanban view
Create a page called 'pipeline.' Add a Row container. Inside it, add one Group for each Deal Stage option (Qualification, Proposal, Negotiation, Closed Won, Closed Lost). In each Group, add a header Text element with the stage name and a Repeating Group with data source: Do a search for Deal (constraint: stage = this stage's option). Display the deal title, value, and contact name in each cell. Add a dropdown or button set on each Deal card that lets users change the stage — the workflow: Make changes to Current cell's Deal → stage = selected stage.
Pro tip: Color-code each stage column header (blue for early, green for won, red for lost) for instant visual pipeline health.
Expected result: A Kanban-style board showing deals organized by stage with the ability to move deals between stages.
Set up activity logging on contacts and deals
Set up activity logging on contacts and deals
On the contact detail page, add a Group below the contact info with a form for logging activities. Include a Dropdown for Activity Type (data source: All Activity Types option set), a Multiline Input for description, and a Button labeled 'Log Activity.' The button workflow: Create a new thing → Activity, with type = Dropdown's value, description = Multiline Input's value, contact = Current page's Contact, logged_by = Current User. Below the form, add a Repeating Group showing all Activities for this contact, sorted by Created Date descending.
Expected result: Users can log calls, emails, meetings, and notes on any contact, and the activity history displays in reverse chronological order.
Build the reporting dashboard
Build the reporting dashboard
Create a page called 'reports.' Add summary metrics at the top: total deals value (Do a search for Deal where stage is not Closed Lost :each item's value :sum), deals won this month (search with stage = Closed Won and close_date > Current date/time :rounded down to month :count), and conversion rate. Below, add a Chart element (install the Chart.js plugin first from Plugins tab). Set the chart type to Bar and data source to Do a search for Deal :group by stage. Display deal count per stage. Add a second chart showing deal values over time grouped by close_date month.
Expected result: A dashboard showing pipeline value, win rates, and visual charts of deal distribution and trends.
Add privacy rules and team access controls
Add privacy rules and team access controls
Go to Data tab → Privacy. For Contact, Deal, and Activity: add a rule 'When Current User is logged in' → allow Find in searches and View all fields. For sensitive operations, add role-based conditions: 'When Current User's role is admin' → allow all API permissions. If you want sales reps to see only their own deals, add a rule: 'When This Deal's owner is Current User' → allow Find in searches. Remove the general logged-in rule for Deals to enforce ownership-based access.
Expected result: Privacy rules restrict data access by role — admins see everything, sales reps see only their assigned contacts and deals.
Complete working example
1CRM SYSTEM — ARCHITECTURE SUMMARY2===================================34DATA TYPES:5 Contact: first_name, last_name, email, phone, company (Company),6 status (Option Set), owner (User), notes, created_by (User)7 Company: name, website, industry, size, contacts (list of Contact)8 Deal: title, value (number), stage (Option Set), contact (Contact),9 company (Company), owner (User), close_date (date), probability10 Activity: contact (Contact), deal (Deal), type (Option Set),11 description, logged_by (User)1213OPTION SETS:14 ContactStatus: Lead, Prospect, Customer, Churned15 DealStage: Qualification, Proposal, Negotiation, Closed Won, Closed Lost16 ActivityType: Call, Email, Meeting, Note1718PAGES:19 contacts — Searchable contact list with Repeating Group20 contact-detail — Full contact view + activity log + related deals21 pipeline — Kanban board with one column per DealStage22 deals — Deal list view with filters23 reports — Dashboard with charts and summary metrics2425KEY WORKFLOWS:26 Log Activity: Create Activity → link to Contact + Deal + User27 Move Deal Stage: Make changes to Deal → stage = new stage28 Create Contact: Form → Create Contact → redirect to detail page29 Create Deal: Form → Create Deal → link to Contact + Company3031PRIVACY RULES:32 Admin: full access to all types33 Sales Rep: Find/View only own Contacts and Deals (owner = Current User)34 Activity: viewable by Contact owner and adminsCommon mistakes when building a CRM system in Bubble.io: Step-by-Step Guide
Why it's a problem: Not linking Deals to both Contact and Company
How to avoid: Always set both the contact and company fields when creating a Deal. Auto-fill company from the contact's company field.
Why it's a problem: Using text fields instead of Option Sets for status and stage
How to avoid: Create Option Sets for Contact Status, Deal Stage, and Activity Type, and use them as field types
Why it's a problem: Searching for Activities inside each Repeating Group cell on the pipeline
How to avoid: Pre-compute activity counts as a field on the Deal record, updated by a backend workflow whenever an Activity is created
Best practices
- Use Option Sets for all status and category fields to ensure data consistency
- Store computed values like deal count and total value as fields on Company to avoid repeated searches
- Implement activity logging from the start — it becomes your audit trail and sales history
- Use privacy rules based on the owner field to enforce team-based data access
- Add pagination to all Repeating Groups (10-20 items per page) to keep the pipeline view fast
- Create a reusable element for the contact card so it looks consistent across list and detail views
- Schedule a weekly backend workflow to flag deals that have been in the same stage for too long
- Back up your CRM data monthly via CSV export from the Data tab
Still stuck?
Copy one of these prompts to get a personalized, step-by-step explanation.
I want to build a CRM system in Bubble.io with contacts, companies, deals pipeline (Kanban view), activity logging, and a reporting dashboard. Can you design the complete data model with all Data Types, fields, and Option Sets, and outline the key workflows?
Build a CRM system for my app. Create Data Types for Contact, Company, Deal, and Activity with appropriate fields and Option Sets. Create a contacts list page, a deal pipeline page with Kanban columns for each stage, and a reporting dashboard with charts.
Frequently asked questions
Can I build a full CRM on Bubble's Free plan?
Technically yes, but the Free plan has limited workload units and 0.5GB storage. A CRM with active use will quickly exceed these limits. The Growth plan is recommended for any production CRM.
How many contacts can a Bubble CRM handle?
Bubble apps handle up to 30,000-50,000 records well with proper optimization. Beyond that, you may need to implement pagination, optimize searches with constraints instead of filters, and consider offloading to an external database.
Can I import my existing contacts from a spreadsheet?
Yes. Go to Data tab → App data → Contact → Upload (CSV). Map your spreadsheet columns to Contact fields. For large imports over 10,000 rows, use the Data API with a backend workflow for batching.
How do I add email integration to the CRM?
Use the SendGrid or Mailgun plugin to send emails from Bubble. Log each sent email as an Activity with type 'Email.' For receiving emails, use a service like Mailgun's inbound routing to forward emails to a Bubble API workflow.
Can I add a drag-and-drop Kanban board?
Bubble does not natively support drag-and-drop. Use dropdown buttons on each deal card to change stages, or install a drag-and-drop plugin from the marketplace for a more interactive experience.
Can RapidDev help build a custom CRM in Bubble?
Absolutely. RapidDev specializes in building production-grade CRM systems in Bubble with advanced features like email integration, automated follow-ups, and custom reporting dashboards.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation