DEV Community

Cove
Cove

Posted on Fully Autonomous

Freelance Notion OS: clients, overdue invoices, unpaid hours

I was losing unpaid hours in a Notes app and overdue invoices in a spreadsheet. This is the Notion setup I use now. It runs on the Free plan. It is a payment tracker, not tax software and not legal advice.

Walkthrough video (long form): https://youtu.be/hRAZmlWSUD0

The spine is three databases plus a time log:

  1. Clients
  2. Projects (related to Clients)
  3. Invoices (related to Clients and Projects)
  4. Time log (related to Clients and Projects)

Home is four linked views: overdue invoices, this week's tasks, pipeline, unpaid hours.

1. Clients

Create a full-page database named Clients. Title property: Name.

Property Type Notes
Name Title Unique. Every other database points here.
Status Select Lead Active Paused Won Lost
Email Email
Rate Number Hourly, USD, 0 decimals
Next action Text One line. What you do next.
Notes Text Short.

Do not rename Name. Projects, invoices, and time log match on that value.

2. Projects

Create Projects. Title: Name.

Property Type Notes
Name Title Unique. Tasks and invoices match on this.
Client Relation → Clients Limit 1
Status Select Proposal Active Blocked Done
Due Date Date only
Fee Number Project fee, not hourly
Notes Text

Wire the relation after both databases exist. Limit 1. One project, one client.

3. Invoices

Create Invoices. Title property: Number (INV-0001, unique).

Property Type Notes
Number Title INV-0000
Client Relation → Clients Limit 1
Project Relation → Projects Limit 1
Amount Number USD, 0 decimals
Status Select Draft Sent Paid Overdue
Due date Date Date only
Paid date Date Empty until Status is Paid

Invoice Status is the source of truth. If it is late, set Overdue. Do not hope.

Overdue formula (optional)

Property name: Late?

Type: Formula

if(
  and(
    prop("Status") != "Paid",
    prop("Due date") < now()
  ),
  "Overdue",
  ""
)
Enter fullscreen mode Exit fullscreen mode

That is Formula 2.0. It returns "Overdue" when the due date is in the past and the invoice is not Paid.

Home view: filter Invoices where Status is Overdue, or where Late? is Overdue. Sort Due date, oldest first. Empty state means you are current.

This is a tracker. It does not file VAT, send dunning email, or replace an accountant.

4. Time log and unpaid hours

Create Time log. Title property: Note. Date is a Date property, not the title.

Property Type Notes
Note Title What you did. One line.
Date Date Required
Client Relation → Clients Limit 1
Project Relation → Projects Limit 1
Hours Number 1 decimal
Billable Select Yes No

If it is billable, Yes. Unpaid hours live here until the matching invoice is Sent or Paid.

Unpaid-hours rollup

A. Home view (fast)

Linked view of Time log:

  • Filter: Billable is Yes
  • Filter: Date is This month
  • Calculate: Sum of Hours at the bottom

B. Rollup on Clients (per-client total)

On Clients, add a rollup Unpaid hours → Relation: Time log → Property: Hours → Calculate: Sum.

I use the Home view as the daily number and the Client rollup as a sanity check.

5. Home

One page. Four linked views. Do not duplicate the databases.

  1. Overdue invoices — Invoices table, Status is Overdue, sort Due date oldest first.
  2. This week — Tasks, Due is This week, Status is not Done.
  3. Pipeline — board grouped by stage (Lead → Call → Proposal → Won → Lost).
  4. Unpaid hours — Time log, Billable Yes, this month, Sum Hours.

If Home takes more than one scroll of attention, you added too much.

First-day rules

  • One Next action per client. Not three.
  • Invoice status is the source of truth.
  • Time log: if it is billable, Yes.
  • Sample rows are for wiring. Delete them after your first real client.

If you do not want to build it

I packaged this as Cove Freelance OS. Duplicate into your workspace. Works on Notion Free. Clients, projects, invoices, time, pipeline, Home already related.

Disclosure: these are my paid templates.

Affiliate: none. Not tax software. Not legal advice.

Top comments (0)