njord

Personal and business ledger with direct bank connections

running in production

01

A double-entry-ish household ledger that replaces a self-hosted budgeting app and keeps the books for a small company. Accounts, categorised transactions with splits, transfers that pair across books, envelope budgeting, recurring bills, debt payoff, investments and net worth, reconciliation against statements, closed periods, and Schedule C reporting. Banks connect through Plaid; every row the bank sends is staged before it touches the ledger, so a cursor can never move past data that was not saved.

Bank rows are staged before they are appliedThe bank returns a page of rows and a cursor. Rows are written to a staging table, checked for duplicates and pending status, then applied to the ledger. The cursor advances only after the rows are saved.banka page + a cursorstagedwritten before anythingtouches the ledgerpending rows waitduplicates by bank id,then by contentledgerinteger centsthe cursor advances only after the rows are saveda crash costs a repeated page, never a missing one

02

The parts worth mentioning

  • Import rules derived from a previous pipeline’s failures: pending rows never import, an inclusive cutoff with a seven-day look-back, duplicate protection by bank id plus a content guard
  • Verified by replaying two years of real bank exports and comparing every account against the old system — the exercise found six bugs before any of it was trusted
  • Envelope budgeting reproduced exactly: 595 figures across seventeen months matched the app it replaces, to the cent
  • Money is integer cents everywhere, parsed from the decimal text rather than through a float

03

Built with

StackNestJS · Next.js · PostgreSQL · Drizzle · Plaid
Sourceprivate

The repository is private: it holds real financial and business records. Happy to walk through the code or the design in a conversation.