Software a business actually runs on.

Not landing pages. The ledger that knows who owes what. The assistant that answers at ten at night. The sixteen thousand shops nobody had a list of.

I am not a career developer. I direct AI tooling, and I finish.

A list of languages would misrepresent how the work gets done, so here is the honest version. The code is written by tooling I direct. The judgement is mine.

Which means I move fast on scope and slow on the things that break quietly. The query missing a tenant filter. The rate limit nobody tested. The backup never restored.

Most of what I am proudest of is a guard that makes a bad state impossible, or a decision not to build something at all.

01 / 06

In private use

Kanakku

The problem
A lending business run on notebooks and one spreadsheet. Interest worked out by hand, monthly, and no dependable answer to the only question that matters: who owes what today.
What I built
A desktop ledger holding parties, loans, deposits, repayment schedules and receipts, with the interest rules encoded exactly as the business actually applies them, including the awkward ones nobody writes down. Cash and account movements stay separate throughout, because conflating them is what made the spreadsheet untrustworthy.
Worth knowing
It needs no internet and no server, because it has to work during a power cut in a town with patchy broadband. The database is encrypted at rest, since it holds other people's financial position. And overdue is a defined rule, not a feeling: unpaid more than ten days after a month closes.

Electron · TypeScript · React · encrypted SQLite · Mac and Windows installers

Pending interest screen grouping unpaid interest by month, with per-party totals and a pay action on each line
Kanakku dashboard showing active loans, deposits and interest owed
Loan register

The interest engine, which is the part that took the longest: what is owed, by whom, for which month. Test workspace, invented names.

02 / 06

Personal, in daily use

Personal assistant

The problem
My own. Everything worth remembering arrived as a passing thought — a payment, a name, something to chase on Friday — and went nowhere, because the cost of writing it down was higher than the thought was worth at the time.
What I built
An assistant on Telegram, running on one MacBook Air at home. Speak or type and it files it: reminders that ring and keep ringing, spending by category, who owes what, who to call. Transcription and the language model both run on the machine itself — nothing is sent anywhere. It now serves several people at once, each with their own bot and their own database.
Worth knowing
The model is never asked anything the code can compute. It picks which action was meant; every rupee figure and every date is worked out in Python, because a model that invents a number does it convincingly. And keeping people apart is structural rather than careful: one SQLite file each, so there is no query that could return the wrong person's row.

Python · SQLite · faster-whisper · Ollama · FastAPI · long polling, no inbound ports

The chooser: one tile per person, each showing how recently their bot was heard from and how much they have captured
Spending page for one person, showing their monthly total and six-month history
The same spending page for a second person, showing entirely different figures

Pick a person, and the whole dashboard is theirs — the red bar names whose. The same page for two of them, below. Test workspace, invented names.

03 / 06

Personal, in daily use

Photo archive

The problem
A phone that keeps filling up, and every convenient way of clearing it makes the photograph worse. Sending a picture through a chat app recompresses it on the phone, before it is even uploaded. I measured that loss on a known file: 83% of the data and 60% of the pixels gone, and five downsized copies kept in place of the original. Cloud storage fixes the space and charges rent for it.
What I built
A second Telegram bot on the same MacBook Air at home, with a browser upload page beside it. Say new, name the folder, send the photos, say done. They land as ordinary files in ordinary folders on a disk in the house, at full resolution, and a gallery reached over an SSH tunnel is how I look at them from anywhere. Photos, video, no size limit.
Worth knowing
It refuses anything the chat app has already recompressed, with one tap to keep it anyway. A warning you miss is a downsized photograph in the archive for good, so the safe answer is not to accept it. And the folder tree is the archive while the database is only an index over it: the test suite empties both tables and asserts that every photograph comes back from the disk alone.

Python · SQLite · FastAPI · sips and qlmanage, no imaging library · Tailscale · launchd · 155 checks

The archive: one card per event, each showing how many photographs it holds and how large it is
The same archive grouped by the month each photograph was taken, rather than by folder
One photograph's details: name, size, pixel dimensions, when it was taken, quality reading original bytes, and its sha256

A folder per event, and a timeline across all of them for when you remember the month and not the occasion. Every photograph carries its own proof: original bytes, and the hash of exactly what landed. Test library, stand-in pictures.

04 / 06

Product, multi-tenant

WhatsApp assistant

The problem
Someone messages a business at nine in the evening. The office opens at nine the next morning, and by then they have messaged two competitors.
What I built
An assistant on the business's own number that answers instantly, sends photographs and books a visit. Plus two dashboards: the client's office, and a separate master view across every client with a live check that names which link in the chain is broken.
Worth knowing
Inbound only, and it never discusses price. Both enforced in code, not by instruction, because an AI agent can be talked into quoting a fee and this cannot. Every query is scoped by tenant, and a test fails the build if one is not.

Node 20 · TypeScript · Postgres · WhatsApp Cloud API direct · 88 tests

Enquiries screen showing a pipeline with status, class, area and visit slot
Conversation list with counts for messages today and enquiries needing a reply
Insights screen showing which topics people ask about most

The client's own view. Demo tenant, seeded data, personal numbers masked.

05 / 06

In use

Customer analytics

The problem
Years of orders sitting in exports nobody opened. The business knew its revenue and almost nothing else: not who had quietly stopped ordering, not how exposed it was to losing one big account.
What I built
Twenty screens over 11,054 customers and 87,673 orders: retention cohorts, concentration risk, a call list the office works down, geography, product mix, and a data-quality page showing what the numbers cannot be trusted on.
What it found
785 customers, under a fifth of the base, generate 80% of revenue, and no single customer is worth more than 3.6%. That second number is the reassuring one and nobody knew it. It also showed which cohorts stopped reordering and when, which is the question the business had actually been asking out loud.

Python · Streamlit · SQLite · per-user login · one-click launcher

Concentration risk screen with a Pareto curve, showing the top customer at 3.6 percent of revenue and an HHI of 45
Retention screen with monthly cohort retention charted against signups
Product mix screen

Concentration risk, retention cohorts and product mix. Real data, and these three screens carry no rupee figures or customer names, which is why they are the ones shown.

06 / 06

In use

Map data scraper

The problem
A campaign needed every print operator in a city. Bought lists are stale, mostly wrong and expensive, and the free ones cover a fraction of what is actually out there.
What I built
Point it at any city and any category and it returns a verified list with names, addresses and phone numbers, plotted and filterable. It caches every response so a re-run is free, resumes after interruption, and stops itself at a spend cap. 16,216 shops on this run, across eleven trades. The same tool gives you every dental clinic in Kochi, or every hotel in Coorg.
Worth knowing
It runs on the official Places API, so the data is licensed and the numbers are real. The catch is that a search returns at most sixty results, so an oversized tile silently loses businesses you never learn existed. Tiles size inversely to density, and any query hitting the ceiling is flagged.

Python · Streamlit · Google Places API · SQLite cache · spend cap

Map of Bangalore with 16,216 print shops plotted and colour-coded by trade, with live filters

Every shop found, coloured by trade, filterable by area and by whether they own a press. The filters are the point: the list changes depending on who you are selling to.

Three answers to one brief

A new agency brand with no identity and no clear view of how it should feel. One comp would have been a guess presented as a decision, so I built them all, running. Open any one and scroll it.

Everything else I have shipped →

A courier desktop app that has processed 23,128 shipments, a bill auditor that prices every consignment against a rate card, reconciliation that replaced a morning of manual checking, a QA pipeline that audits a live storefront, and the rest — most of it built for one company, and most of it still running.

If something here looks like a problem you have.

I take on build work directly and white-label for agencies. Fifteen minutes on a call beats a pitch, and I would rather understand the problem first.

Karur, Tamil Nadu Available for freelance and white-label work Repositories are private. Most of this holds real customer and financial data.