Follow-ups and deadlines, in one Obsidian vault.
A note per client, a note per deal and two Bases give you one page with who to follow up with today and every contract date in the next seven days. Private, on your own devices, with no monthly fee.
What you’ll build
An agent’s week runs on two lists: who to contact today, and which deadline is coming up. This setup puts both on one page:
- One note per contact: buyers, sellers, past clients and your sphere, each with a next step and a next date.
- One note per deal, with every contract date in its properties.
- Two Bases that turn those notes into lists: follow-ups due, past clients to check on, deadlines in the next seven days, and closings in the next 30.
This is general information, not legal or brokerage advice. Your signed contract, your state’s rules and your brokerage’s policies always come first, and many brokerages require their own system for transaction documents. You need Obsidian 1.9 or later with the Bases core plugin on. Everything below was tested in Obsidian 1.14 with no community plugins.
Step 1: One note per contact
Make a folder called Contacts and one note per person, named after them:
---
type: contact
role: Buyer
stage: Active
next_step: Send three new listings
next_date: 2026-10-14
last_contact: 2026-10-10
---roleis Buyer, Seller, Past client or Sphere.stageis where they are now, such as New lead, Active or Under contract.next_stepandnext_dateare the heart of it. Give every contact both, even if the step is “check in next spring”.last_contactis the date you last spoke. Update it whenever you talk; the past-client list depends on it.
Save it as Templates/Contact.md with the Templates core plugin on, so every new contact starts the same way.
Step 2: Follow-ups due, and past clients to check on
Save this as Contacts.base. (New to Bases? Our Bases recipes show how to paste one in.)
filters:
and:
- type == "contact"
- '!file.inFolder("Templates")'
formulas:
follow_up: if(next_date, if(date(next_date) <= today(), "⏰ Due", "in " + (date(next_date) - today()).days.round(0).toString() + " days"), "")
days_quiet: if(last_contact, (today() - date(last_contact)).days.round(0), "")
properties:
file.name:
displayName: Contact
note.next_step:
displayName: Next step
formula.follow_up:
displayName: Follow-up
formula.days_quiet:
displayName: Days since contact
views:
- type: table
name: Follow-ups due
filters:
and:
- if(next_date, date(next_date) <= today(), false)
order:
- file.name
- role
- stage
- next_step
- formula.follow_up
sort:
- property: next_date
direction: ASC
- type: table
name: Past clients to check on
filters:
and:
- role == "Past client"
- if(last_contact, (today() - date(last_contact)).days > 90, true)
order:
- file.name
- last_contact
- formula.days_quiet- Follow-ups due lists everyone whose next date is today or earlier, oldest first. The
if(next_date, …, false)wrapper skips contacts with no date. - The
follow_upformula shows “⏰ Due” or “in 5 days”..round(0)keeps the days whole across daylight-saving changes. - Past clients to check on lists past clients you haven’t spoken to in 90 days, including anyone with no date at all (the fallback is
true).
Step 3: Deals with every contract date
One note per deal, linked to the client, with each deadline from the contract as a date property:
---
type: deal
side: Buyer
client: "[[Jordan Lee]]"
stage: Under contract
price: 385000
inspection_by: 2026-10-16
appraisal_by: 2026-10-22
financing_by: 2026-10-28
closing_on: 2026-11-07
---Copy each date from the signed contract, then check it a second time. If an amendment changes a date, change the note the same day.
Step 4: Every deadline in the next seven days
filters:
and:
- type == "deal"
- '!file.inFolder("Templates")'
formulas:
closing_in: if(closing_on, (date(closing_on) - today()).days.round(0), "")
properties:
file.name:
displayName: Deal
note.inspection_by:
displayName: Inspection by
note.appraisal_by:
displayName: Appraisal by
note.financing_by:
displayName: Financing by
note.closing_on:
displayName: Closing on
formula.closing_in:
displayName: Days to close
views:
- type: table
name: Deadlines in 7 days
filters:
and:
- stage != "Closed"
- stage != "Fell through"
- if(inspection_by, if(date(inspection_by) >= today(), (date(inspection_by) - today()).days <= 7, false), false) || if(appraisal_by, if(date(appraisal_by) >= today(), (date(appraisal_by) - today()).days <= 7, false), false) || if(financing_by, if(date(financing_by) >= today(), (date(financing_by) - today()).days <= 7, false), false) || if(closing_on, if(date(closing_on) >= today(), (date(closing_on) - today()).days <= 7, false), false)
order:
- file.name
- client
- inspection_by
- appraisal_by
- financing_by
- closing_on
- type: table
name: Closing in 30 days
filters:
and:
- stage != "Closed"
- stage != "Fell through"
- if(closing_on, (date(closing_on) - today()).days <= 30, false)
order:
- file.name
- client
- closing_on
- formula.closing_in
- price
sort:
- property: closing_on
direction: ASC- Deadlines in 7 days lists any open deal with at least one date (inspection, appraisal, financing or closing) between today and a week from now.
||means “or”. - Each date is checked twice: the outer
if()skips a blank date, and the inner one skips dates already past, so a finished inspection doesn’t keep a deal on the list. - Closing in 30 days lists open deals by closing date, with a countdown.
- Closed and fell-through deals are left out of both, so the lists stay short.
The file.hasLink(this.file) trick from our CRM guide gives each client page a list of their own deals.
Step 5: One page to start the day
Make a note called Home:
## Follow-ups due
![[Contacts.base#Follow-ups due]]
## Contract deadlines, next 7 days
![[Deals.base#Deadlines in 7 days]]
## Closing in 30 days
![[Deals.base#Closing in 30 days]]
## Stay in touch
![[Contacts.base#Past clients to check on]]Pin it in a tab (right-click the tab, then Pin). Work the follow-ups, check the deadlines, and the day is planned.
What never goes in your notes
Notes are plain files that sync to every device you use. Keep these out of them:
- Social Security numbers, dates of birth and copies of ID.
- Bank account numbers, wiring instructions and loan details.
- Lockbox, door and alarm codes.
- Passwords for the MLS, e-signature or email accounts.
Write a pointer instead, such as “Lockbox code: in the showing service.” And warn every client about wire fraud early: criminals send fake wiring instructions that look like they come from the agent or the title company. Tell clients to confirm any wiring instructions with the title company, using contact details they look up themselves, never ones from the email.
Mistakes that cost us time
- Contacts with no next date. They never come up as due, so they quietly drop away. Give everyone a date, even months out.
- Dates typed as text. “Oct 16” won’t sort or count down. Use 2026-10-16, or the Date property type.
- A deadline changed in the contract but not in the note. Update the note the same day.
- Templates showing up as clients. The
!file.inFolder("Templates")filter fixes it. - Too many fields. Start with the ones here, and add one only when a list needs it.
Keep going.
How to Build a Simple CRM in Obsidian (No Plugins)
Track clients, follow-ups and invoices with one note per client and a single Base. Copy-paste code, no plugins.
Read the guide Bases recipesObsidian Bases Examples: 10 Copy-Paste Recipes
Ten tested recipes: due this week, days since, late invoices with totals, weighted pipeline, renewals, per-note embeds and the gotchas.
Read the guide Small office ITSmall Office IT Documentation in Obsidian: What to Record
What a small office should write down about its IT, what never to store, and a simple setup in Obsidian.
Read the guide Building with AIA Spec Template for AI Coding Tools (Claude Code, Cursor)
A one-page spec template for Claude Code, Cursor and other AI coding tools, a plan-first prompt, and where Obsidian fits.
Read the guide StudentsObsidian for Students: Track Assignments, Exams and Grades
Assignments with due dates, an overdue list and exam countdowns, plus class pages that list their own work. Copy-paste code, no plugins.
Read the guide Daily planningA Calm Daily Planner in Obsidian: Tasks by Energy and Time
A brain-dump inbox, tasks sorted by energy and minutes, up to three focus tasks, and bills two weeks ahead, on one Today page.
Read the guide Game mastersObsidian for Game Masters: Run a Tabletop RPG Campaign
Session prep in 30 minutes, secrets and clues until they’re revealed, NPCs listed on their places, and faction clocks. Any system.
Read the guide