47 Ledger · Double-entry books

Books an auditor would trust.

47 Ledger is a double-entry accounting system for small businesses, with several businesses under one login. Every invoice, bill, payment, return and transfer posts a balanced journal entry, and every report is read from those postings.

The app sits behind a sign-in and is invite only for now.

My role
Designed and built it
Started
September 2026
Status
Live, invite only
Built on
Next.js · TypeScript

Why I built it

The problem.

Coming from audit, the question I always ask of a set of books is: where did this number come from? Most small-business tools answer with a total. I wanted one that answers with an entry: every figure traceable to a balanced posting, nothing edited after the fact, and the accounting rules enforced by the database rather than by good intentions.

The application

The main screens, in the order you meet them.

Redrawn live from the application’s own layout with sample figures, not customer records.

Net profit against the previous period, cash and bank, what is owed in and out, with overdue balances on the first screen.

app.ledger.fortysevenlab.com
Workspace › HomeBase · USD

Your financial picture

Overview

+ Add record
6 monthsAll businessesAll clientsAll projects

Net profit

USD 17,841.40

▲ 111% vs previous period

Income 26,250.00 − expenses 8,408.60

Cash / Bank

USD 30,031.40

Ledger balance · all time

Receivables

USD 6,650.00

1 overdue · USD 3,200.00

Payables

USD 2,370.00

1 overdue · USD 900.00

Monthly performance Income Expenses
02K4K6K8KApr 26May 26Jun 26Jul 26Aug 26Sep 26
Income by business↗

Aurora StudioUSD 24,350.00

Cedar Print CoUSD 1,900.00

How it works

One journal underneath everything.

  1. 01

    Every record posts a balanced entry

    Invoices, bills, payments, returns, transfers and opening balances all post double-entry journals. Reports are derived from posted lines, never from stored totals.

  2. 02

    Stock, tax and debts done properly

    Buying stock is an asset, not an expense; selling it books cost of sales at the cost that left the shelf. Tax runs through Output and Input VAT control accounts. Money borrowed or lent never touches profit.

  3. 03

    Several businesses, one login

    Each business has its own figures, and reports filter by business, client or project. Invoices and payments work in the currency of the deal, at the rate actually received.

  4. 04

    Twelve reports from one journal

    Profit and loss, balance sheet, cash flow, trial balance, tax return, general ledger and six breakdowns. The balance sheet checks the accounting equation as it draws.

Audit trail

Corrections never rewrite history.

Change an invoice and the ledger reverses the previous posting and posts the correction. Both stay in the books, so an accountant can follow any figure back to the entry that produced it. This is the part of the design I cared about most.

  • Posted entries cannot be edited or deleted
  • Every posting is labelled with the revision that produced it
  • Corrections appear as reversals, dated and numbered
  • Trial balance and balance sheet verify themselves as balanced
app.ledger.fortysevenlab.com
Workspace › General ledgerBase · USD

Report

General ledger — accounts receivable

Northwind RetailINV-1042All revisions
DateReferenceEntryRevDebitCreditBalance
28 AugINV-1042Invoice issuedr14,500.004,500.00
30 AugINV-1042Reversal of r1 — amount amendedr1 ↺4,500.000.00
30 AugINV-1042Invoice re-postedr24,800.004,800.00
05 SepPAY-0311Part payment receivedr12,000.002,800.00
Totals9,300.006,500.002,800.00

✓ Balance agrees to INV-1042 outstanding. Nothing was edited in place — the correction is two new lines.

What I decided

Four calls I made, and why.

01

Corrections never rewrite history

Posted entries are immutable. Changing a record reverses the old posting and posts the new one, both kept and labelled with the revision that produced them. Voiding reverses; it never deletes.

02

Locking the books lives in the database

Once a period is filed it can be locked, and nothing can be posted, changed or reversed inside it. The rule sits on every register in Postgres, so no screen or API call can post around it.

03

Ticking off the bank is evidence, not an entry

Bank reconciliation compares the ledger, the bank-confirmed figure and the statement. Marking a line reconciled posts nothing, so a filed figure can never move because someone ticked a box.

04

Fewer concepts, not more

I folded leads into clients (a prospect is just a client at an earlier stage) and renamed engagements to jobs. There are deliberately no bank feeds: payments are recorded when they happen, and the books stay correct because every one is a balanced entry.

Built withNext.jsTypeScriptSupabase Postgres (RLS, plpgsql rules)decimal.js20 SQL migrationsPGlite tests