A lightweight, build-it-yourself CRM for solopreneurs

A lightweight, build-it-yourself CRM for solopreneurs & consultants (Bases + 2 plugins, ~1 hour)

Earlier, the thread Fully Functional Modular CRM showed a genuinely impressive solo CRM - and a year and a half of replies asking for a release.

Fair enough: most of us don’t want to build a CRM,
we want to have one. But the second-best thing to a release is a recipe you can build in about an hour, own completely, and adapt. This is that recipe. Feedback very welcome — this is a first public version. To be clear, this isn’t a plugin, it’s a recipe that uses existing functionality and existing plugins to create a first version.

It’s aimed at solopreneurs and small consulting/ professional-services practices: the kind of work where you maintain 100–300 warm relationships
and 3–15 open deals, where repeat business and referrals dominate, and where every heavyweight CRM you try silently dies after three weeks of
dutiful data entry.

Design principles

  1. At most two community plugins (a lesson taken straight from that thread): Templater for data entry, plus one community kanban view for Bases (pick a current one from the directory). Everything else is core Obsidian — Bases does the heavy lifting.
  2. Modular, one folder per module, strict naming. Drop any module you don’t need.
  3. Exit-friendly. All data is plain frontmatter in ordinary notes; the .base files only read it. Stop using the system and you keep clean notes.
  4. Capture where you already write. The interaction log is a by-product of the meeting notes you take anyway. That kills the #1 reason CRMs die: entry friction.

Two things this adds that most homegrown CRMs skip, and that matter most in relationship-driven work: a keep-in-touch cadence per contact and
referral-source tracking (who sent this deal your way, and who deserves a thank-you).

Folder structure

crm/
  people/          # one note per person
  orgs/            # one note per organisation (+ attachments)
  deals/           # one note per opportunity
  log/             # meeting & activity notes
  reviews/         # weekly reviews
  inbox/           # quick captures, to be processed
  _templates/      # Templater templates
  contacts.base
  pipeline.base

Templates

Frontmatter keys in English with underscores (keeps Bases formulas clean).

Person (_templates/person.md):

---
type: person
org: "[[]]"
role:
segment: B          # A = core, B = warm, C = broad
warmth: warm        # warm | lukewarm | cold
can_refer: false
referred_by: "[[]]"
cadence_weeks: 8
last_contact:
next_touch:
email:
phone:
tags: [crm/person]
---

[Call](tel:+00000000000) · [Mail](mailto:[email protected])

## Context
<!-- how you met, talking points, interests -->

## Log
<!-- newest on top; links to notes in crm/log/ -->

Organisation (_templates/org.md):

---
type: org
sector:
status: prospect    # client | past-client | prospect | partner
tags: [crm/org]
---

## People

## Documents

Deal (_templates/deal.md):

---
type: deal
org: "[[]]"
contact: "[[]]"
stage: lead         # lead | conversation | scoping | proposal | won | lost
value: 0
referral_source: "[[]]"
proposal_sent:
expected_close:
next_step:
tags: [crm/deal]
---

## Notes

Meeting note (_templates/meeting.md), file name
YYYY-MM-DD meeting <name>:

---
type: log
contact: "[[]]"
org: "[[]]"
date: {{date}}
touch: meeting      # meeting | email | event | newsletter
tags: [crm/log]
---

## Notes

## Agreed
- [ ]

The capture rule — ten seconds, and it is the whole system: after any contact, create a meeting note from the template and update two dates on the person’s card: last_contact = today, next_touch = today + cadence.

The two Bases files

(Bases syntax is still evolving — double-check function names against the current help docs for your Obsidian version.)

contacts.base — three views:

filters:
  and:
    - file.hasTag("crm/person")
views:
  - type: table
    name: All contacts
    order: [file.name, org, segment, warmth, last_contact, next_touch]
  - type: table
    name: Overdue
    filters:
      and:
        - next_touch <= today()
    sort:
      - property: next_touch
        direction: ASC
    order: [file.name, org, next_touch, cadence_weeks]
  - type: table
    name: Referrers
    filters:
      and:
        - can_refer == true
    order: [file.name, org, last_contact]

pipeline.base — open deals, grouped and as a kanban:

filters:
  and:
    - file.hasTag("crm/deal")
views:
  - type: table
    name: Open pipeline
    filters:
      and:
        - stage != "won"
        - stage != "lost"
    group_by: stage
    order: [file.name, org, value, next_step, expected_close]
  - type: table
    name: Quiet proposals
    filters:
      and:
        - stage == "proposal"
        - proposal_sent < today() - "14 days"
    order: [file.name, org, value, proposal_sent]
  - type: kanban        # view type provided by the kanban plugin
    name: Board
    group_by: stage

Add a summary on the value column (sum) in the table view: that’s your pipeline total per stage — a pipeline report with zero moving parts.

The weekly review — the engine

One fixed slot per week (say Friday, 16:00, calendar-blocked). Template:

---
type: review
week: {{date:GGGG-[W]WW}}
---

## Who's overdue
![[crm/contacts.base#Overdue]]

## Quiet proposals
![[crm/pipeline.base#Quiet proposals]]

## Referrers — who deserves a thank-you?
![[crm/contacts.base#Referrers]]

## Actions for next week (max 5)
- [ ]

Without this ritual any CRM decays, including this one. Keep the touches small — two lines and a relevant link is a perfectly good ping. For newsletters: tag people (e.g. crm/newsletter), make a view, export as CSV to your mail tool. The CRM itself never sends anything.

What it deliberately does not do

  • No email/calendar sync, no automation, no reminders that fire while Obsidian is closed — the weekly review carries that load.
  • No engagement scores or auto-generated summaries (that would need a plugin; see the questions below).
  • Multi-user? No. This is a single-owner system. If two people need to work the same client data simultaneously, use a real shared CRM.
  • If GDPR applies to you: everything-local is a genuinely nice compliance story (no processor, “right to be forgotten” = search & delete), but disk encryption, a deliberate sync choice and yearly pruning are on you. Don’t put sensitive personal details in the Context section.

Feedback welcome!

  • Does the Bases syntax above work on your setup / version? Anything that has a cleaner idiom by now?
  • Which kanban-for-Bases view are people happiest with?
  • Does the two-plugin constraint hold for you, or is there a third that earns its keep?
  • If parts of this were a (free, local-only) plugin — automatic last_contact when you link a meeting note, an “overdue” nudge outside the review, engagement scoring — which would actually matter to you?
  • What’s missing for your practice?
1 Like