Bookings[email protected] San Antonio · Texas
Obsidian guide · Real estate agents

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.

Updated October 2026 · Tested in Obsidian 1.14 · No plugins

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:

Contacts/Jordan Lee.md
---
type: contact
role: Buyer
stage: Active
next_step: Send three new listings
next_date: 2026-10-14
last_contact: 2026-10-10
---
  • role is Buyer, Seller, Past client or Sphere. stage is where they are now, such as New lead, Active or Under contract.
  • next_step and next_date are the heart of it. Give every contact both, even if the step is “check in next spring”.
  • last_contact is 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.)

Contacts.base
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_up formula 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:

Deals/42 Cedar Lane.md
---
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

Deals.base
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:

Home.md
## 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.
More guides

Keep going.