Fund Admin
A fund accounting and reporting platform for a venture firm. A double entry ledger underneath, investor level capital accounts on top, and the statements a fund administrator has to produce on any date you name.

Project Overview
Fund Admin is a fund accounting and reporting platform for a venture firm, and it is the only thing I have built where a rounding difference is a bug report rather than a shrug. The job it does sounds simple until you try it: on any date you name, say what every investor owns, what it cost, what it is worth now and what the fund earned. Then do it across several entities at once, with a capital call half collected and a valuation that landed after the period closed.
Underneath the whole thing is double entry. Every action in the app, a purchase, a realisation, a valuation adjustment, a distribution, posts a journal entry rather than updating a number in place. The reports are then derived from the ledger instead of being calculated alongside it, which is the difference between a system an accountant will sign off and a dashboard that happens to agree with one this quarter. It also means the trial balance is a real check, not decoration.
Returns are the part everyone wants and nobody wants to verify. Performance is computed from irregular cashflows with a solver that converges on the rate to a tight tolerance, and it deliberately declines to return a figure when the cashflows cannot support one. An internal rate of return on a position that has only ever had money put into it is not a small error, it is a meaningless one, and a blank is easier to defend than a confident wrong number. Valuations reconcile in both directions, per share and in total, including the fund of funds case where the same underlying sits in more than one sleeve and the movements must not be counted twice.
The most useful thing I changed was not arithmetic. Reversing or deleting a batch of transactions began as a loop of requests from the browser: pick forty, fire forty, hope. When one failed halfway you were left with a partially reversed ledger, which is worse than not having reversed anything. That work moved into the database as a single atomic operation scoped to one client, so the batch either completes or leaves nothing behind. Financial writes that are not atomic are a corruption bug waiting for a slow connection.
Imports are where real data fights back. Clients send spreadsheets, spreadsheets contain the same holding spelled three different ways, and an import that trusts them will happily create three holdings. The importer now does fuzzy matching across candidate names and raises a warning for a human to resolve rather than silently merging on a similarity score. Deciding on someone's behalf is how you end up with two positions quietly collapsed into one and nobody able to say when it happened.
Then there is the unglamorous half that makes it a fund system rather than a reporting tool. Interest accrues on the day count convention each instrument actually uses rather than one house default. Management fees step down over the life of a commitment, so the computation walks the periods and applies the rate in force for each. Seven statements come out the other end, trial balance through to partner capital accounts, each exporting to Excel, PDF and Word, because the three people who read them each want a different one.
Roughly 64,000 lines of TypeScript between October 2025 and January 2026, with an end to end suite running against every push. The React was never the interesting part.
Key Features
- Double entry journal behind every investment action, so the statements derive from the ledger rather than beside it
- Seven reports: trial balance, general ledger, chart of accounts, statement of net assets, statement of operations, cash flow and partner capital accounts
- Report configuration for period type, comparison period and which columns appear
- Every statement exports to Excel, PDF or Word
- Performance returns solved from irregular cashflows, per investment and per entity
- Capital calls with a collections tracker, receivable and prepaid handling, and posting by due date
- Management fee computation that steps the rate down over the life of a commitment
- Interest accrual on the day count convention each instrument actually uses
- Batch reversal and deletion handled atomically in the database rather than as a loop of requests
- Spreadsheet import for investments, commitments, investors and cash, with duplicate warnings
Challenges & Solutions
Batch operations that ran as a loop of requests and could leave a ledger half reversed
Client spreadsheets carrying the same holding spelled three different ways
Valuations that have to reconcile per share and in total, including the fund of funds case where one underlying sits in more than one sleeve
Period comparisons where inception, the report period and the comparison period are three separate date ranges
Statements that have to tie back to the ledger on any date, including one inside a closed period
Key Learnings
Project Info
Timeline
October 2025 to January 2026
Team
Small team, everything through pull request review
Status
Tech Stack
Frontend
Data
Reporting
Testing
Deployment