Building a Treasury Planning Application
An internal application called the Treasury Console connects agreements, obligations, payroll and planned invoices as linked records for cash and P&L planning.
- role
- Finance Systems Owner / Product Design & AI-Assisted Development
- duration
- September 2026 – present
- stack
- TanStack StartReactTypeScriptJSON LinesAI developer toolsGit
- tags
- financeproduct-designdata-modelingforecastingAI-assistedsystems-design
Key outcomes
5 outcomes · in progress- A workbook-grounded HTML design became a routed TanStack Start application
- Basic contract records became agreement lines; outgoing obligations gained dated terms
- Typed registers support in-app review and one validated revision path for application and agent edits
- A stored, multi-year planned-invoice register derives from agreement terms and service lines
- Register-backed revenue and expenses feed P&L planning and budget comparison
The Workbooks Held the Business Model
I had already built an AI-maintained cash flow forecasting workbook. That made the weekly update faster, but it also exposed what the workbooks could not express cleanly.
Our cash-flow and master-budget workbooks held more than numbers. They held assumptions about when customers would pay, how agreements became revenue, what we owed, when money would leave, and which version of a forecast was being discussed. Some of that knowledge lived in formulas. Much of it lived in comments, pasted exports, and the judgment of the person maintaining the books.
I wanted an application that could manage cash and P&L forecasts without forcing the business model back into cells. I call the internal application that grew from this work the Treasury Console. The job began with understanding the spreadsheets well enough to preserve what they did, then making the underlying commitments and calculations explicit enough to improve them.
From Interface Design to Working Application
Before coding, I documented the current process, requirements, calculations, controls, and decisions. An interactive HTML design built from workbook extracts let me work through the screens against real examples. It gave me something concrete to review: not just what a page looked like, but what a person would inspect or change on it.
That design became a TanStack Start application with routed screens, shared components, data loaders, register-backed views, and a server-side path for saving changes. The work moved beyond an interface prototype into the behavior behind each screen: what a value meant, when it took effect, which source supported it, and what should happen when someone corrected it.
My role spanned the finance model, product decisions, interaction design, and AI-assisted implementation. I used AI developer tools inside the repository throughout planning, design, implementation, and review. The source records, models, application code, and checks were in the same workspace, so I could inspect a source, try an approach, build it, and audit the result without handing the context from one disconnected tool to another. I brought the operating questions, decided what the records meant, and judged whether the working application answered them.
Modeling the Business in Registers
I chose file-based registers so I could develop the application’s data model in the same workspace as the code. Each register holds one kind of record as JSON Lines: one JSON object per line. Typed schemas constrain the fields; stable identifiers link records; revisions preserve what changed. The app reads and writes through those contracts while I refine the model.
That made the repository a practical place to organize and clean existing data. Agents could help turn source material into records, compare rows, surface missing relationships, and propose revisions. I could inspect those changes in Git and then review them in the screen where I would actually use the information. A data-health view made gaps and malformed records visible instead of quietly treating them as zeros.
| What a workbook held | What I modeled |
|---|---|
| A revenue row and an amount | An agreement, service lines and dated quantities and rates |
| A cost copied into future months | An obligation, its cost lines, timing rules and values in force |
| A note beside a number | Source and provenance that can be inspected with the record |
| A changed cell | An appended revision that leaves the earlier record intact |
Here is a simplified, fictional excerpt of an agreement-lines register. Each line is a separate JSON record linked to its parent agreement; quantities and rates live in a related dated-values register.
{"id":"agr-new-example/support","agreementId":"agr-new-example","label":"Managed support","billingMode":"recurring"}
{"id":"agr-new-example/project","agreementId":"agr-new-example","label":"Implementation project","billingMode":"one-time"}
The model stayed directly editable and testable as I built the application and audited the records for our business. I did not have to freeze every decision about a future database before I could build a capable application around the records.
From Contract Lists to Agreement Economics
We already had a contract list in a database. It gave us basic definitions such as names, dates and status. It did not give us the economic detail inside each agreement: the promised service or project, the quantity, rate, billing rule, term, and how those changed over time.
I built that next layer as agreement lines linked to dated values. From a revenue row I could open the agreement and inspect its contract history; from an agreement I could see what a line meant in a particular month. The model connected a definition of a contract to the financial behavior it creates. Where a term was seeded from incomplete evidence, I kept the assumption visible for review instead of presenting it as confirmed contract language.
On the money-out side, I modeled obligations with the same discipline. An accounting system records a vendor bill once it arrives; treasury planning needs to know about commitments before that. Leases, subscriptions, contractors, insurance, taxes, payroll and other obligations have different schedules, sources and degrees of certainty. I represented the parent commitment, its cost lines, the category each line affects, its dated amounts, and the rule for when money is expected to leave.
This gave the console a way to describe the economic commitments on both sides of the business, including facts that did not fit neatly in the accounting system.
From Agreement Terms to Planned Invoices
The planned-invoice generator showed what a connected model could do. It read agreement terms, service lines, and the quantities and rates in force, then produced a stored schedule extending across a rolling multi-year window. Its calculation record pinned the generator version and the input register hashes.
A rerun could compare the new plan with what had already been saved, append only changed future revisions, and preserve earlier history or a person’s reviewed adjustment. These were planned invoices, not invoices issued to customers. Some term ends and renewals still rested on seeded or estimated information, so the schedule showed where better contract evidence was needed.
That was a much richer planning object than another spreadsheet of projected invoice dates. Each future item had a route back to the agreement and line that produced it.
Forecasting from Linked Records
The revenue and expense worksheets resolved monthly figures from the records in force and exposed the basis of each amount. The forecast P&L brought those views into a statement. Budget-versus-forecast comparison aligned categories and derived variances where both sides had a known value. When an actuals adapter was not available, the console did not substitute a plausible-looking number.
The same model let me add scenarios without overwriting the committed plan. A proposed staffing or other change could live separately, be switched into selected forecast views, and show its effect on the P&L. I also brought people, pay history, benefits and employer costs into the planning model, rather than treating payroll as one unexplained salary total. Some cash, balance-sheet and payroll funding views still needed further integration, so I did not treat their prototypes as a complete forecast.
I designed snapshot and comparison views for another question spreadsheets handle poorly: what did we believe at the time, and why did that change? The full forecast-snapshot cadence was not yet operating, while the stored planned-invoice calculations already retained their own reproducible input snapshots.
Reviewing the Model in the Application
The console became the place where I tested the model against how treasury work actually happens. I could inspect a service line, see the history behind a month, review a cost, find a missing source, and decide what to correct. The same register writer served application and agent edits, validated them, refused stale changes, and appended revisions instead of erasing earlier records.
I also wrote a reusable register-modeling skill from this work: how to choose record boundaries, seed from evidence, keep dated values, expose uncertainty, and review questions with the person who owns the business meaning. The related design workbench and review-mode approach has its own case study.
What the Application Made Possible
The result was a working internal application grounded in a financial operating model I could inspect and improve. It connected contract detail, obligations, dated values, multi-year invoice plans, and register-backed forecasts in a way the workbooks could not. A change to a business assumption could be reviewed in the records and the application, with its source and earlier revisions still in view.
I kept the weekly cash cutover and the remaining source reconciliation as separate acceptance work. The result I could show was the application and its model, not a claim that every spreadsheet had already been retired.