Building a Personal CRM with Obsidian and Dataview

· 5 min read
obsidian dataview crm productivity

Prerequisites

Before we get started, make sure you’ve got:

  • Obsidian installed and a vault set up
  • The Dataview plugin
  • The Templater plugin
  • A vague sense of guilt about all the people you’ve forgotten to reply to
  • At least one houseplant you havent killed yet (proves you can maintain something)

What We’re Building

I am absolutely terrible at keeping in touch with people. Not in a “I dont care” way, more in a “three months vanished and I completely forgot we were supposed to grab coffee” way. Sound familiar?

CRMs exist for this, obviously. Salesforce, HubSpot, all those lovely enterprise tools that cost more per month than my coffee habit. But I dont need pipeline management and lead scoring. I need a gentle nudge that says “you haven’t spoken to your mate James in four months, maybe send him a message you absolute hermit.”

Shut up and take my money

So I built one in Obsidian. Plain text, no subscription, fully searchable, and it lives right next to the rest of my notes. Here’s how.

The Approach

  1. Create a person template
  2. Build interaction logging
  3. Set up dashboards with Dataview
  4. Automate reminders so you stop ghosting people

Step 1: Folder Structure

Nothing fancy here. Just some sensible organisation:

vault/
├── People/
│   ├── Work/
│   ├── Friends/
│   └── Networking/
├── Interactions/
└── Templates/
    ├── Person.md
    └── Interaction.md

You could go deeper with the subfolders, but honestly, Obsidian’s search is good enough that you dont need a filing system worthy of the National Archives. Keep it simple.

Step 2: Person Template

This is your contact card. Every person gets one of these:

---
type: person
name: "{{title}}"
company:
role:
met: {{date:YYYY-MM-DD}}
lastContact:
nextFollowUp:
birthday:
location:
tags: []
---

# {{title}}

## Contact
- Email:
- Phone:
- LinkedIn:
- Twitter:

## Context
How do I know this person? What's the connection?

## Notes
Random facts, interests, family info, anything that helps me be a better friend/colleague.

## Topics to Discuss
Things to bring up next time we talk.

## Interactions

The Context section is the real gem. Future you will absolutely thank present you for writing down “met at the DevOps meetup, works on Kubernetes, has a dog called Biscuit.” Trust me, nothing makes someone feel valued like remembering their dog’s name six months later.

Step 3: Interaction Template

Every meaningful conversation gets logged. Not every Slack message, obviously. Just the ones that matter.

---
type: interaction
date: {{date:YYYY-MM-DD}}
people: []
method: meeting
summary:
followUp:
---

# Interaction - {{date:YYYY-MM-DD}}

## People
- [[]]

## Discussion
What did we talk about?

## Action Items
- [ ]

## Follow-up Needed
When and why should I follow up?

The key here is keeping it low friction. If it takes more than 30 seconds to log an interaction, you wont do it. And then you’re back to square one, staring at your contacts list wondering when you last spoke to anyone.

Step 4: Quick Capture

This is where it gets properly useful. Create a QuickAdd or Templater command so you can log an interaction in seconds:

// Templater script for quick interaction logging
const people = app.vault.getMarkdownFiles()
  .filter(f => f.path.startsWith('People/'))
  .map(f => f.basename);

const person = await tp.system.suggester(people, people);
const summary = await tp.system.prompt("Quick summary:");
const followUp = await tp.system.prompt("Follow-up needed?");

const content = `---
type: interaction
date: ${tp.date.now("YYYY-MM-DD")}
people: ["${person}"]
method: note
summary: "${summary}"
followUp: "${followUp}"
---

# Quick Note - ${person}

${summary}

${followUp ? `## Follow-up\n${followUp}` : ''}
`;

await app.vault.create(`Interactions/${tp.date.now("YYYY-MM-DD")}-${person}.md`, content);

Pop open the command palette, run the script, pick a name, jot down what you talked about. Done. The whole thing takes less time than it took you to read this paragraph.

Hackerman

Step 5: Dashboard Queries

Now for the Dataview magic. This is where all that metadata starts paying off.

People needing follow-up:

Haven’t spoken in 90 days:

Ninety days. That’s three whole months of radio silence. If someone shows up on this list, its probably time to send that “hey, long time no speak” message.

Recent interactions:

Birthdays this month:

Step 6: Updating Last Contact

When you log an interaction, update the person’s lastContact field automatically. Otherwise you’re maintaining two sources of truth, and we all know how that ends.

// After creating interaction, update person's lastContact
const personFile = app.vault.getAbstractFileByPath(`People/${person}.md`);
if (personFile) {
  await app.fileManager.processFrontMatter(personFile, (fm) => {
    fm.lastContact = tp.date.now("YYYY-MM-DD");
  });
}

This slots right into the quick capture script from Step 4. One action logs the interaction AND updates the contact. No double entry, no forgetting.

Step 7: Relationship Strength Indicator

Add a strength field to your person template so you can see at a glance who’s drifting:

strength: warm  # cold, warm, hot, close

Query by strength to get a quick health check on your network. “Cold” doesnt mean you’ve fallen out. It just means life happened and you need to reach out.

Step 8: Weekly Review Dashboard

I spend five minutes on this every Sunday morning with a coffee. It isnt glamorous, but it works.

# People Review - {{date:YYYY-MM-DD}}

## Follow-ups Due

## Getting Cold
People I should reach out to:

## This Week's Interactions

## Actions
- [ ] Review follow-ups and reach out
- [ ] Check "getting cold" list
- [ ] Update any stale information

Five minutes. That’s all it takes to stop being the person who “means to get in touch” but never actually does.

Kermit getting to work

Step 9: Tags for Context

Use tags for filtering people by how you know them:

tags: [tech, investor, potential-client, mentor]

This makes it dead easy to pull up everyone in a particular context. “Show me all my tech contacts” or “who do I know that’s an investor” becomes a one-line Dataview query.

The Result

What you end up with:

  • All contacts in searchable plain text
  • Automatic relationship decay alerts
  • Full interaction history per person
  • Zero subscription fees, forever
  • Data you own, stored locally, exportable

Chef’s Kiss

What I’d Do Differently

Add photos to person notes. I’m genuinely terrible with faces, and having a photo in each person’s file would save me from that awful moment of “I definitely know you but I cannot place you at all.” Obsidian supports images in notes, so there’s no excuse really. I just haven’t done it yet.

Relationships are the most valuable thing you’ll ever build. A plain text file and five minutes a week is all it takes to stop letting them quietly fade away.

Related Posts

Comments