Skip to content
Bernardo Fernandez

PERSONAL PROJECT · 2025

Ledgerline.

Financial clarity for freelancers

Context

Freelance money is scattered by default: invoices in one tool, receipts in email, taxes in a spreadsheet, the actual bank somewhere else. I built Ledgerline around a different model — instead of managing documents, track the movement of money: what entered, what is committed, what is safely spendable.

The problem

The hard part was never the dashboard. It was making ingestion and categorization trustworthy enough to act on: bank CSVs in different formats, recurring payees with inconsistent names, and the fact that a financial tool users can't trust is worse than no tool at all.

My role

Sole developer — domain modeling, backend, data pipeline and interface.

What made it technically interesting

Every bank exports CSVs with its own quirks: dates in different formats, debits as positive or negative values, encodings that break mid-file. The ingestion layer has to translate all of them into one reliable transaction model without losing data.

Categorization needs to be automatic enough to save time and correctable enough to stay accurate — a rules engine that learns recurring payees, with every manual correction feeding back into the rules.

The dashboard's core question — 'how much can I safely spend right now' — depends on commitments, not just balances. That means modeling future obligations, not only past transactions.

Decisions

A single normalized transaction model
Every bank format is translated at the edge of the system, so the core domain never needs to know where a transaction came from. Adding a bank became a mapping problem instead of a core rewrite.
Server-side aggregation over client-side math
Monthly summaries are computed in SQL views instead of loading raw transactions into the browser, so the dashboard stays fast even with years of history.
Rules engine with human override
Automation handles the majority of categorization, and manual corrections feed back into the rules — the system gets more accurate the longer it is used.

Result

  • Different bank exports normalize into one transaction model, so the pipeline is extendable by mapping, not rewriting.
  • Monthly and commitment-aware summaries are computed in SQL — the interface never re-derives financial state.
  • Corrections improve the rules engine instead of accumulating as unstructured exceptions.

What I learned

Automating a domain teaches you the domain. Every category I got wrong at first was a gap in my own understanding of how money actually moves through freelance work.

Have a project in this space?

Let's talk about it