AnthonyTlei
← All work

Case study

/

Product systems · Platform & data

Mizan

A private multi-currency household finance system built around an immutable ledger, explicit planning, and explainable balances.

Synthetic Mizan dashboard with a reconciled combined balance, spendable amount, three native-currency accounts, buckets, and recent activity.
What exists
Status
In production
Source
Public description
Evidence
Architecture · Data model · Data flow · Worker design · Failure design · Workflow · Screenshots
Stack
TypeScript · Next.js · React · PostgreSQL · Drizzle ORM

01
Overview

What this is

Mizan is a private household finance system built for two people managing money across USD, KWD, and IDR. It combines everyday transactions, accounts, budgets, reserved buckets, recurring commitments, scheduled payments, and reporting without flattening every number into a single currency or hiding how a balance was produced.

The interface is intentionally calm; the harder work lives beneath it. Transactions are modeled through immutable revisions and balanced ledger postings, currency conversions keep their rates and provenance, and planned items remain plans until an explicit settlement creates financial history.

Built for my household and used by two people across three currencies. The public case study and every screenshot use synthetic data only.

The problem

Generic trackers did not match the household’s combination of shared ownership, multi-currency balances, reserved money, and future commitments. A useful replacement had to be simple in daily use while making corrections, conversions, and automation trustworthy enough to explain later.

What I built and owned

I defined the product and accounting semantics, designed the responsive interface, built the modular Next.js application and PostgreSQL schema, implemented authorization, automation, reporting, and recovery controls, and operate the private deployment.

Disclosure

The running application and source are private. Every screenshot on this page comes from a disposable database containing only synthetic people and transactions; no production data, account names, balances, or URLs are shown.

02
Detail

How it works

Trust comes from the model

Mizan treats the original currency as canonical and preserves settlement and reporting conversions as separate, traceable facts. Monetary values use exact decimals rather than binary floating point. A correction never rewrites history in place: it creates a new revision and new balanced postings, preserving the path from what was entered to what is now considered current.

That exactness is deliberately kept out of the way during ordinary use. The interface speaks in accounts, expenses, transfers, buckets, budgets, and upcoming commitments; the ledger remains available as the reason a balance can be trusted.

Everyday on top, exact underneath

  • 01

    Native currency stays visible

    USD, KWD, and IDR balances remain first-class while reporting conversions retain their rate and provenance.

  • 02

    Planning cannot become history by accident

    Recurring and scheduled commitments affect forecasts, but only an explicit settlement creates a financial transaction.

  • 03

    Buckets reserve; they do not mint money

    Allocations change what is spendable without changing the underlying account balance.

  • 04

    Every request is household-scoped

    Authorization follows the household and member context rather than trusting a record identifier from the browser.

3 images · select one to open the full view

Diagram · select to open the full view

Text description of this diagram

Two members use one responsive, household-scoped application for accounts, transactions, budgets, buckets, upcoming commitments, and reports. Financial commands pass through authorization and domain rules before they create immutable transaction revisions, journals, and balanced postings in PostgreSQL. Exact decimals and exchange-rate provenance preserve the financial truth.

Recurring and scheduled commitments are stored as planning records rather than ledger entries. When a member explicitly settles one, the application creates the corresponding financial history. Background effects travel through an outbox to an idempotent scheduled worker, which records failures and supports safe retry.

Synthetic evidence

The screenshots were captured from a fresh disposable PostgreSQL database populated with fictional people, accounts, balances, budgets, buckets, and transactions. No production database, development database, private URL, or real financial record was used.

03
Result

What came of it

shippedA private two-person household can record expenses, income, transfers, refunds, adjustments, budgets, buckets, and future commitments in one system while preserving each amount’s native currency.Private household deployment; public screenshots use synthetic data.
reproducibleCorrections create new immutable revisions; balanced postings and FX provenance make the resulting balances traceable rather than silently overwritten.
reproducibleRecurring and scheduled items remain planning records until an explicit settlement creates financial history, so forecasts cannot masquerade as posted money.
reproducibleThe outbox and worker path is idempotent and records failures for recovery instead of relying on one request to complete every side effect.

04
Links

Where to look

productionRunning application — private household deploymentsourceSource code — private

Something similar in mind?

If this is close to a problem you have, the fastest thing is usually a short conversation about what you are actually trying to change.

Discuss a project