/ build-guides / How to Build a CRM as a Solo Developer
build-guides 11 min read

How to Build a CRM as a Solo Developer

Complete guide to building a CRM as a solo developer - tech stack, architecture, timeline, and tips.

Hero image for How to Build a CRM as a Solo Developer

What You're Building

A CRM (Customer Relationship Management) tool helps businesses track their interactions with customers and manage their sales pipeline. Salesforce dominates the enterprise space, HubSpot owns the mid-market, and there are dozens of smaller players. So why would a solo developer build a CRM?

Because Salesforce is a nightmare to use, HubSpot is expensive once you actually need it, and most small businesses just want a simple way to track leads and deals without a PhD in CRM configuration. I've seen solopreneurs and small agencies using spreadsheets because every CRM they tried was overkill. That's your market.

The "expensive once you need it" part is concrete. HubSpot's CRM is genuinely free, including unlimited users and up to a million contacts, which is why it pulls people in. But the moment you want real automation, custom reports, or to actually market to your contacts, the price jumps. The Starter Customer Platform is $20 per seat per month, Sales Hub Professional is $100 per seat per month, and the full Professional Customer Platform runs $1,300 per month for five seats. Enterprise tiers start around $1,500 per month per hub. That gap between "free trial energy" and "real money the day you grow" is exactly the wedge a focused, niche CRM exploits.

Difficulty & Timeline

Aspect Detail
Difficulty Medium to Hard
Time to MVP 8-10 weeks
Ongoing Maintenance Medium
Monetization Per-user subscriptions ($15-49/user/month)

Next.js for the frontend dashboard. CRMs are data-heavy applications with lots of tables, filters, and detail views. React's ecosystem handles this well. The current release is Next.js 16.2.6 on top of React 19.2.6, and next is pulling roughly 40 million npm downloads a week, so the patterns and answers you need are well documented. Use a component library like shadcn/ui for consistent, professional UI components. shadcn ships as a CLI you run on demand rather than a dependency you install, currently at version 4.8.3 with around 5 million weekly downloads, and it copies the component source into your repo so you own and can edit every table, dialog, and form.

Django or Node.js for the backend. Django's admin panel is actually useful here as an internal tool for managing data, and the current release is Django 6.0.5. If you go the Node route, build on the active LTS line, Node.js 24 (Krypton), rather than a current release like 26, so you get the longest support window without surprise breakages. PostgreSQL is the database, obviously. The current major version is PostgreSQL 18 (latest minor 18.4, released May 2026), and each major version gets at least five years of support under the official versioning policy, so you are not signing up for a forced migration any time soon. CRM data is inherently relational: contacts belong to companies, deals have stages, activities link to contacts.

For email integration, use the Gmail or Microsoft Graph (Outlook) APIs so users can see email threads alongside their contact records. This is a killer feature that separates a real CRM from a glorified spreadsheet. Both are free to call at the volumes a small CRM hits. The Gmail API has no per-call charge today, and Google has only added an 80,000,000 quota-unit daily billing threshold per project that does not trigger billing yet (full billing details are promised later in 2026 with at least 90 days notice). Microsoft Graph throttles Outlook mail at 10,000 requests per 10-minute window per mailbox per app, with a maximum of 4 concurrent requests, so design your sync to batch and back off rather than hammer.

Step-by-Step Plan

Phase 1: Contact & Deal Management (Week 1-4)

Build the contact database first. Name, email, phone, company, notes, custom fields. Add a company/organization layer so contacts can be grouped. Build a solid table view with search, filters, sorting, and pagination.

Then build the deal pipeline. A Kanban board where deals flow through stages (Lead, Qualified, Proposal, Negotiation, Closed Won, Closed Lost). Each deal links to a contact and has a value, close date, and probability. Users drag deals between stages.

This core loop (contacts + deals + pipeline) is the minimum viable CRM. Get it right before adding anything else.

Phase 2: Activities & Communication (Week 4-7)

Add activity tracking. Calls, emails, meetings, notes. Users log interactions with contacts and see a chronological activity timeline on each contact's profile page. This timeline is the most-used feature in any CRM because it answers the question "What happened with this client?"

Build email integration if possible. Connecting to Gmail or Outlook so emails automatically appear in the contact timeline is incredibly powerful. It turns your CRM from a manual data entry tool into something that actually stays up to date.

Add task reminders. "Follow up with John next Tuesday" type reminders that show in a daily view. Sales teams live and die by follow-ups, and automated reminders ensure nothing falls through the cracks.

Phase 3: Reporting & Polish (Week 7-10)

Build a dashboard with key metrics. Total deals in pipeline, total value, conversion rate by stage, deals won this month, average deal size. These numbers help users understand their sales performance at a glance.

Add basic reporting. Revenue forecast based on deal probability, sales activity report (calls made, emails sent), pipeline velocity (how fast deals move through stages). Don't build a complex BI tool. Simple charts and tables that answer common sales questions.

Set up billing, import/export (CSV is essential), and build a landing page that speaks directly to your target niche. For billing, Stripe is the default. Standard US online card pricing is 2.9 percent plus 30 cents per successful charge with no setup, monthly, or hidden fees, so on a $75 per month, five-seat plan you pay about $2.48 in processing. The current SDKs are stripe 22.2.0 for Node and stripe 15.2.0 for Python, and the Node package alone sees around 12 million npm downloads a week.

Key Features to Build First

Contact database with search and filters. The core data layer. Must be fast, searchable, and support custom fields.

Deal pipeline (Kanban). Visual pipeline where deals flow through stages. Drag and drop between stages.

Activity timeline. Chronological log of all interactions on each contact. Calls, emails, meetings, notes.

Task reminders. Follow-up reminders that keep deals moving. Daily task view showing what needs attention today.

CSV import/export. Users need to get their data in and out. Import from spreadsheets, export for reports or migration. This is table stakes.

Architecture Overview

Dashboard (Next.js)
  ├── Contact list & detail views
  ├── Deal pipeline (Kanban)
  ├── Activity timeline
  ├── Task/reminder management
  ├── Reports & dashboard
  └── Settings & team management

Backend (Django / Node.js)
  ├── Contact/Company CRUD
  ├── Deal pipeline management
  ├── Activity logging
  ├── Task & reminder scheduler
  ├── Email integration (Gmail/Outlook API)
  ├── CSV import/export
  ├── Reporting engine
  └── Billing (Stripe)

Storage
  ├── PostgreSQL (contacts, deals, activities)
  ├── Redis (caching, background jobs)
  └── S3/R2 (file attachments, email attachments)

Common Pitfalls

Building for enterprise. Enterprise CRM is Salesforce's game, and they have 73,000 employees working on it. You will not win there. Build for freelancers, solo consultants, small agencies, or a specific industry vertical. These users want simplicity and will pay for it.

Over-engineering custom fields. Users will want custom fields. That's fine. But don't build a full custom field engine with custom field types, validation rules, and calculated fields for v1. Start with a few text and dropdown custom fields. Expand based on actual demand.

Ignoring data import. The first thing any CRM user does is import their existing contacts. If your CSV import is buggy, slow, or confusing, you lose them immediately. Invest real time in a solid import flow with mapping, duplicate detection, and error handling.

No mobile access. Sales people work on their phones constantly. Before meetings, between meetings, at events. Your CRM needs to be usable on mobile. Not necessarily a native app, but a responsive web interface that works well on phones.

Trying to replace email. CRM tools that try to become your email client never work well. Instead, integrate with existing email (Gmail, Outlook) and pull relevant conversations into the contact timeline. Work with email, don't replace it.

Timeline Estimate

Phase Time What You're Doing
Contacts & deals 4 weeks Database, pipeline, table views, search
Activities & comms 3 weeks Timeline, email integration, reminders
Reports & launch 3 weeks Dashboard, reporting, billing, landing page
Total 8-10 weeks Ready for small teams

Is This Worth Building?

Yes, with a massive caveat: pick a niche. "CRM for everyone" is suicide. "CRM for freelance designers" or "CRM for real estate agents" or "CRM for recruiting agencies" is viable. Each niche has specific workflows, terminology, and pain points that generic CRMs handle poorly.

The revenue potential is strong. Per-user pricing means revenue grows with team size. Even at $15/user/month, a 5-person team pays $75/month. Get 200 teams and that's $180k/year. The stickiness is excellent too because migrating CRM data is painful, which means low churn once teams are set up and using it. Just make sure you're building for people who are currently frustrated with their existing solution, not trying to convince spreadsheet users that they need a CRM.

Common Errors and Fixes

These are the failures that actually eat your weekends once the email and billing integrations go in. The numbers below are pinned to the official quota and pricing docs current as of this writing.

Gmail API returns HTTP 429 "User-rate limit exceeded" during initial sync. The first time you backfill a user's inbox into the contact timeline, it is easy to blow past the per-minute-per-user limit because each operation costs quota units, not one unit per call. A messages.get costs 20 units, a threads.get costs 40, and a messages.send costs 100. Fix it by batching reads, fetching message metadata lists before full bodies, and implementing exponential backoff that honors the Retry-After header instead of retrying immediately. Watch the per-project 80,000,000 quota-unit daily threshold Google added, even though it does not bill yet.

Microsoft Graph returns 429 "Too Many Requests" against a single mailbox. Outlook mail is throttled at 10,000 requests per 10-minute window per mailbox per app, with at most 4 concurrent requests. A naive parallel sync that fans out 20 requests at once will trip the concurrency cap immediately. Fix it by capping your worker pool at 4, queueing the rest, and respecting the Retry-After value Graph sends back. These limits cannot be raised, so the design has to live within them.

Stripe webhook signature verification fails in production. This almost always means you parsed the request body as JSON before verifying it. Stripe signs the raw request payload, so you must pass the unparsed body to stripe.webhooks.constructEvent with your endpoint signing secret. In Next.js route handlers, disable body parsing and read the raw text. Use the current SDKs (stripe 22.2.0 for Node, stripe 15.2.0 for Python) and pin the API version in the dashboard so a Stripe-side upgrade does not silently change payload shapes under you.

npx shadcn cannot find your config or fails to add a component. shadcn is a CLI (current version 4.8.3), not a runtime dependency, and it expects a components.json at the project root plus a configured Tailwind and path-alias setup. Run npx shadcn@latest init once before adding components, and make sure your tsconfig or jsconfig paths match what the init step wrote. Because shadcn copies source into your repo, fixing a broken component is just editing the file it generated.

PostgreSQL too many connections under load from a serverless or multi-worker backend. Each Next.js or Django worker that opens its own pool multiplies connections fast, and Postgres caps them. Put a pooler such as PgBouncer (or your managed provider's built-in pooler) in front of the database and point your app at it. This matters more as you scale; PostgreSQL 18 is current and supported for years, so the fix is operational, not a version upgrade.

Sources

Built by Kevin

Like this? You'll like what I'm building too.

Two ways to support and get more of this work.

Desktop App

HEARTH

A privacy-first Life OS for your desktop. Journal, tasks, and notes that stay on your machine. Coming soon, direct download from this site.

Read more
Digital Products

MY TOOLKITS

Receipts-first toolkits for shipping after hours, building Claude agents, publishing on Amazon, and more. The exact methods I used, not theory.

Browse on Whop

Need This Built?

Kevin builds products solo, from first version to live. If you want something like this made, work with him.