Kiran Goutam D← Back to selected work
Journey All projects Get in touch
Design Case Study

Killing the month-end spreadsheet, without recreating it by accident

A shared ledger that parses the bank’s own SMS as it lands, so the month-end spreadsheet never has to be rebuilt. That only works if the automatic version can be trusted without a second look — and four parts of the interface were quietly handing that checking back. This is what it took to fix each one.

Problem statement

Two people, a notebook every day, a spreadsheet every month

The routine was manual twice over: write down what you spent as you spent it, then turn two people’s scattered entries into something that actually showed where the money went. Not hard. Just enough friction, often enough, that the logging slipped and the month-end rebuild got dreaded.

KNKU removes both steps — parse the transaction from the bank’s own SMS as it lands, keep a dashboard that is always current. But that only helps if the automatic version can be trusted without a second look. Four parts of the interface were quietly failing that test, each one teaching the couple to check the app by hand — which is the chore it was built to end.

01 · Legibility

You couldn’t tell what you’d bought without tapping in

The one thing a glance at a row needs to answer — who did I pay — was clipping mid-word or replaced outright by a bank logo, forcing a second look the automation was supposed to make unnecessary.

6 of 6 sampled titles clipped
02 · Honesty

The dashboard handed down a verdict, not a fact

“Overspent by ₹X” compared spending to income that structurally couldn’t land in the same window — wrong most months, stated as fact, the kind of thing you’d start mentally correcting yourself.

Salary falls outside the 21–20 cycle
03 · Trust

It guessed, and presented the guess as settled

A “Recurring” badge was applied by timing alone — two purchases a month apart — with nothing to say the system wasn’t sure, which is precisely the kind of claim you end up re-verifying by hand.

46 flagged, 1 ever confirmed by a person
Where the name comes from

Kanakku — the word for account, kept to its consonants

KNKU
கணக்கு

The project started as exactly what the problem statement above describes — two people trying to keep an honest shared ledger. The Tamil word for account, or calculation, is kanakku (கணக்கு). Stripped to its consonants for a name that reads cleanly in an app icon, it became KNKU.

The product, start to finish

What actually happens between opening the app and seeing the month

Before zooming into what got fixed, the whole loop the household actually lives in — set up once, then almost never open the keyboard again.

01
Real KNKU screen
Set up once, as a household
One person creates the household and gets an invite link; the other joins with it. No separate accounts to reconcile later.
02
Real KNKU screen
Each phone knows whose it is
Picked once per device. Every expense that phone logs is attributed automatically — nobody types their own name in.
03
Real KNKU screen
The dashboard is just already there
Bank SMS arrives → gets parsed → the household total updates. Nobody opened a spreadsheet to make this number exist.
04
Real KNKU screen
Manual entry still exists — for the rest
Cash, a UPI app that didn’t send an SMS, or income — the same form the automatic parser would have filled in, open on demand.
05
Real KNKU screen
Budgets, seen against reality
Each category carries a monthly ceiling the household set once; the bar is how close this month already is, no calculation required.
06
Real KNKU screen
Saving toward something, together
A goal both people contribute to, tracked the same way spending is — not a separate app, not a separate mental model.
07
Real KNKU screen
The household decides what it wants tracked
Income visibility, notifications, lock — each a real switch, not a fixed opinion baked into the product.
08
Unknown VPA q4tr
Context needed
-₹1,250
When the parser genuinely can’t tell, it says so
Routed to a grey-area queue with one tap to resolve — instead of silently guessing a category and being wrong.
Method

Why this had to be built by constantly checking, not designed once

A tool that reads your finances and shows you a number earns trust by being right on real inputs, repeatedly — not by looking finished. Every derivation here exists because a first pass that looked correct turned out, on the household’s actual data, not to be: three row-layout fixes in a row, five versions of the outflow card, forty-six false “recurring” flags found only by running the logic against 640 real transactions. None of that surfaces from a design file.

It is also why the scope kept growing. Fixing the transaction row surfaced the icon problem; fixing that surfaced how much of the ledger was unrecognised merchants; watching real usage surfaced that income had no home in the UI at all. And the checking went wider than the two people building it — testing ran across spouse, friends, parents and elders, because a household finance app has no excuse to work only for the most technical person in the house.

Derivation · 01

Getting a merchant name to actually fit in its own row

The transaction row is the single most-viewed piece of the app. In a 342px-wide row, the title column was measuring 110px — and every fix attempt at first traded one failure for a different one.

1 · found→ 2 · regression→ 3 · regression→ 4 · shipped
PhonePe Merc
24 Sept, 7:20 pm · U
-₹3,400
Unknown VPA q4
23 Sept, 7:22 pm · U
-₹1,250
Found

Title column had no claim on its own space

The left block carried min-w-0 but no flex-1, so it sized to whatever the right column left over — and the right column, shrink-0, took whatever the longest category name (“Grey Area / Needs Context”, 122px) demanded first.

title column: 110px of 342px row
PhonePe Merchant
24 Sept, 7:20 pm · UPI · Kiran
-₹3,400
Regression

Fixing the title broke the line underneath it

Giving the title flex-1 worked — but the metadata line (date · payment · owner) had no width limit of its own, so it now ran straight under the amount column instead of stopping before it.

meta line: 94px over its own container
Rent – Landlord
25 Sept, 4:31 pm · Pluxee Ca
-₹42,952
Regression

Clipping the overflow just moved where it broke

Adding overflow-hidden stopped the collision — and started hard-clipping the line mid-word instead, with no ellipsis and a dangling separator: “Pluxee Ca”.

no ellipsis rendered, just a cut string
Real KNKU transaction list
Shipped

Removed a duplicate, capped a column, let both lines breathe

The owner name in the meta line was already shown as a badge one line above — deleting the duplicate freed 68px on its own. The category name got a responsive width cap instead of an unbounded one, so it stops driving the layout without disappearing.

0 of 8 titles clipped, 6 of 8 meta lines fit exactly
Derivation · 02

An icon system that answered the wrong question

Per-merchant icons exist so the list scans at a glance. Instead the list read as a wall of identical bank-blue squares — because the icon logic was answering who paid instead of who got paid.

1 · found→ 2 · partial fix→ 3 · shipped
Found

The bank name was winning the match, not the merchant

Title, bank name, and notes were joined into one string and matched against a rule list, first hit wins. /hdfc/ sits 12th of 29 rules — ahead of Amazon, Myntra, Domino’s, BookMyShow. An Amazon order paid on an HDFC card rendered the HDFC logo.

Amazon
Myntra
Toit Brewpub
AMZN Mktpl
Blinkit
9 of 14 rows rendered the bank’s icon, not the merchant’s
Partial fix

Matching each field separately wasn’t enough on its own

Matching title, then notes, then bank — in that order, each on its own — correctly resolved every merchant the rule list already knew. It did nothing for the far more common case: a merchant the list didn’t recognise, which still fell through to the bank as a fallback.

Recognised merchants fixed — unrecognised ones still showed a bank
Shipped

A bank can supply a payment-app icon. Never its own logo.

The fallback to the bank field now excludes bank-brand rules entirely — it can still resolve a UPI app named there (GPay, PhonePe), but never the bank itself. An unrecognised merchant falls to its category glyph, which carries more information than a repeated logo ever did.

Amazon
Myntra
Toit Brewpub
AMZN Mktpl
Blinkit
0 of 14 rows show a bank logo
Derivation · 03

The headline number that kept changing its mind

The outflow card is the first thing either person sees. What it should say — spending only, income only, or a verdict on both — took five real iterations, most of them decided by looking at what it actually said against real weeks.

v1→ v2→ v3→ v4→ v5
Household Outflow
21/9 – 20/10
₹24,200
Today: ₹2,100 · 3 txns
v1 · baseline

Spending only. No visibility into income at all.

The original card, before this pass: a single figure, a today line, a wave chart. Accurate, but a household putting real salary through the ledger had no way to see it reflected anywhere.

Household Outflow
21/9 – 20/10
₹24,200
Today: ₹2,100 · 3 txns
Money in+₹18,500
● Kiran ₹18,500● Mageswari ₹0
Overspent by₹5,700
v2

Added income — and a verdict alongside it

Money in, split by person, plus a net figure that read either “Left over” or “Overspent by.” It looked complete. It compared two numbers that don’t actually share a calendar.

Household Outflow
21/9 – 20/10
₹24,200
Today: ₹2,100 · 3 txns
Money in+₹18,500
● Kiran ₹18,500● Mageswari ₹0
v3 · caught the honesty problem

Removed the verdict, kept the income

Salary lands outside the household’s 21st–20th billing cycle, so the “Overspent” comparison was wrong most months regardless of how the month actually went. The line came out. Money In stayed, on its own, as a block beneath the figure.

Household Outflow
21/9 – 20/10
₹24,200
Today: ₹2,100 · 3 txns
v4

A figure with nothing left to say didn’t earn its block

Once the verdict was gone, a standalone Money In block with a per-person split felt heavier than the information deserved on a card whose one job is the spend total. Cut entirely.

Real KNKU Overview hero card
v5 · shipped

In and out, at a glance, deciding nothing for you

A compact in/out readout sits beside the period label — visible in one look, gone entirely when the household turns income tracking off. The headline number underneath stays exactly what it says it is: spending.

Derivation · 04

“Recurring” is a claim — and only a person can make it

The system used to infer a recurring bill from timing: the same title twice, roughly a month apart. Run against the household’s real 640 transactions, it flagged forty-six titles this way. One had ever actually been marked recurring by a person.

Flagged by the timing heuristic
What it actually was
Chai
A tea run that happened to repeat a month apart, once
Petrol
Routine refuelling, not a subscription
Groceries
A normal weekly-ish purchase, mislabelled as a standing bill
Netflix ✓ kept
The one title a person had actually tapped “recurring” on

The badge now reflects only what someone marked, in the add or edit form — a single tap flags the whole title group, so a real bill is tagged once, not re-confirmed every month. The system suggests nothing it can’t back up.

What carried across all four

Principles the work kept coming back to

Show identity, not infrastructure

An icon, a label, a badge should answer what the person actually wants to know — who did I pay — never how the system happened to find that out.

from the icon derivation

Never assert what only a person can know

Timing can suggest a pattern. It can’t confirm a commitment. The interface should say “this looks recurring” as a question, or wait for the person to say so — not state it as settled.

from the recurring derivation

A number is a claim — check it before you show it

“Overspent by” wasn’t wrong because of a bug; it was wrong because the comparison it made didn’t hold up against the data it actually had. Showing two figures beat asserting one conclusion.

from the outflow card derivation

The fix isn’t done until the regression is gone too

Three separate attempts at the same row each solved the stated problem and broke something adjacent. Shipping meant checking the whole row, not just the line that was reported.

from the row-legibility derivation
Where this sits in the market

Automatic capture and a real two-person household rarely come together

India has no shortage of expense trackers that read bank SMS, and no shortage of apps built for couples. What’s uncommon is a product that is both at once — without asking two people to move their money into a new account to get it.

CapabilitySMS-parsing trackers
(Moneyview, axio)
Couple money apps
(Splitwise, Coupl)
KNKU
Reads existing bank SMS, no manual entryYesRarelyYes
Built around two people sharing one viewNo — single userYesYes
Works with accounts you already haveYesCoupl requires a new joint account & cardsYes
Flags what it can’t confidently categoriseGuesses silentlyN/A — manual entryGrey-area queue
“I paid, but it was really your expense”No concept of a partnerSplitting, as a debtAcknowledgement, as household spend

Category research: SMS-based trackers in India, money apps built for couples, and Coupl’s own joint-account model. KNKU column reflects this build.

The last two rows are the ones that don’t show up in a feature-comparison table but matter every day in a real household: most trackers have no concept of a second person at all, so an unrecognised transaction just gets a wrong guess and a shrug. KNKU routes it to a queue instead — and separately, when one partner pays for something that’s really the other’s, it’s held until the other person acknowledges it — so it lands as their spend, not silently attributed to whoever’s card it hit.

Where this goes next

From one household’s ledger to a data layer that works for anyone’s

KNKU is early by design — one household’s tool, built by two people. Three directions, and one reason none of them is close yet.

One picture, not six apps

SMS parsing works around the real problem: money moving across several UPI apps and cards that don’t talk to each other. The structural fix is India’s RBI-regulated Account Aggregator framework, which lets an app pull real transaction data with explicit, revocable consent — the difference between guessing well and being told.

A household, not just a couple

Nothing in the model is specific to a husband and wife. Who spent what, what needs acknowledging, what everyone can see — that applies to parents and children, or any group managing money together.

A dashboard you shape

Overview, Category, Goals are fixed because that is what one household needed. Different people inside a household want different things in front of them.

What’s actually in the way

Three constraints, two of them already visible on this page. iOS gives a web app no way to read a message, which is why the whole ingestion pipeline is an iOS Shortcut. The free hosting tier sleeps after fifteen idle minutes, which is how a phone automation silently loses one. And bank integration needs licensing and partnerships a self-funded two-person project doesn’t have. The product is early because it is.

In numbers

What changed, measured

6 / 6 → 0 / 8
transaction titles clipping in the list
9 / 14 → 0 / 14
rows wearing a bank logo instead of the merchant’s
46 → 1
titles asserted as “recurring” without being told to
5
real iterations on the outflow card, each driven by looking at what it said
19
commits, each verified against the running app before shipping
2
people who use every screen in this case study daily

This pass also covered the layer underneath the interface — a security audit, deploy pipeline, and an SMS-to-ledger automation for the household’s two phones — kept out of this write-up because it isn’t design work, not because it didn’t happen.

React 19 + Tailwind Framer Motion iOS PWA Figma-free — iterated live in the running app

What this shows

None of these four problems looked like a design flaw from the code. Each surfaced only by putting the real screen against real data. And the interesting part was never any single fix — it was catching, every time, that the first one had quietly traded one problem for another, and not calling it done until it hadn’t.

Designed and built with Claude Opus 5 in Claude Code, iterating directly against the live app rather than static mockups. Screens on this page are faithful recreations of the real interface — same layout, same colour and icon system, same measured failure states — built with illustrative figures in place of the household’s actual financial data.