The Problem
Freelancers in India do their bookkeeping in March, which is another way of saying they do not do it at all. Eleven months of receipts live in a pocket, a glovebox, and a WhatsApp chat with themselves. The tax number they carry in their head all year is a guess, and the guess is usually wrong in whichever direction hurts more. Then the asks for the books, and the books are a shoebox. Mine included. The year Cleantab started, my own bank statement held over a thousand transactions I had never categorised, and the honest answer to "how much tax should you have set aside" was a shrug. The product exists because that shrug got expensive. Every decision in the app answers one question: does this make the March handover to the CA better or worse? Features that impressed in a demo but did not survive that question did not ship.What It Is
Cleantab is a phone-first that does the bookkeeping at the moment of spending instead of eleven months later. Snap a bill and AI reads it: amount, merchant, GST, category, all filled before you have put the receipt down. You type nothing. Income works the same way: log a payment or import a whole bank statement, and the app tells you what to set aside for tax, per invoice, all year.
Your Drive Is the Database
Cleantab keeps no database of user records. The books live in the user's own Google Drive as plain CSV files and photos, under a folder the user can open, read, and take away. The app asks for the narrowest Drive permission that exists, , so it cannot see anything it did not create. This is a design decision wearing an architecture costume. "We take privacy seriously" is a policy that can change with a funding round. "Your financial records are physically on your Drive and not on our servers" is a fact a user can verify by opening Drive. It also solves offboarding and sharing in one move: leaving Cleantab means simply not opening it again, the data stays yours in a format Excel reads, and handing the CA the books is a native Drive share rather than an export feature.The Phantom Tax Bill
The app showed me a tax bill of ₹2,44,111 for the year. My accountant, reading the same bank statement, said ₹0. The accountant was right. The tax engine was never wrong. Of ₹24.27 lakh credited to my account that year, only ₹9.94 lakh was professional income. The rest was family transfers, credit card repayments, a loan disbursement, and money moved between my own accounts. The classifier had swept most of it in as income, and every rupee of the phantom bill flowed from that list. On a personal bank account, most credits are not income. Any design that assumes otherwise taxes your mother's birthday transfer. That inverted the classifier's whole posture. A credit is only counted as income when something says so, and the row shows what: every ticked credit carries a plain-English reason, "15 payments from this payer across 11 months, reads like a client", with a confidence level. The review screen groups credits by payer instead of by date, so one decision covers fifteen rows. Anything the classifier cannot justify lands in a "couldn't tell" bucket, unticked, because the safe default is to justify inclusion, never exclusion. The import screen carries more design weight than any other, because most users arrive in the worst month with the worst artefact, a whole year's bank statement. It splits into two tabs, Money in and Money out, because the decisions on each side are different: credits are an income question, debits are a categorisation chore, and interleaving them makes the reader re-load context on every row. The import runs long, so it says so. A progress dialog counts payers as they are judged, writes land in chunks with the running total visible, and the finished screen opens on the payer groups that need a human rather than the hundreds of rows that do not. Rows the app refuses to touch are locked with the reason stated on the row, because a tick that silently refuses reads as broken, and a reader who knows why a row is locked stops fighting it. Re-imports were designed for, not merely tolerated. Downloading an overlapping statement is the normal case, banks make clean date cuts hard, so the app spots the overlap and asks one question, update the existing import or bring it in separately, instead of quietly doubling a year of income. A row matching an existing entry on date, amount, and narration is barred from the write entirely. The doubling class of bug is closed at the door, not swept up afterwards. After the redesign, my books computed the accountant's figure to the rupee.The Salary Taxed Twice
The second bug was subtler and worth ₹1,28,582. My employer's fifteen salary credits look exactly like client income: a company name, regular payments, healthy amounts. The classifier ticked them as professional receipts, so the same money was taxed twice, once as the salary declared in settings and once as deemed business profit. No rule that only reads the bank statement can fix this, because nothing in a statement says "employer". The fix reads the two together: a payer whose yearly total lands within a band of the declared salary, wide because the declared figure is gross while the bank sees pay after deductions, and who pays with salary-like regularity, gets flagged as the likely employer. Only the closest match, only ever one. The interesting design choice is what happens next. That verdict ships with low confidence on purpose, so the review screen draws the eye to it rather than quietly settling it. A wrong employer guess silently absorbed would be a repeat of the phantom bill with the sign flipped. The same humility shapes the salary settings: the app shows the salary it found in the books next to the declared figure with a button to adopt it, a proposal and never an overwrite, because the two numbers measure different things and silently replacing one with the other would understate the return.
The March Handover
The finale of the product is a PDF. Send to CA builds a report from the live books: title page, contents, cash flow, financial statements, and the tax computation with every input shown. The report prints what was credited beside what is taxed, "of which salary, of which professional receipts", so the CA never has to reconcile a smaller gross-receipts figure by guesswork. When exceeds the year's liability, the report says refund, in a row, rather than leaving a negative number to interpret. Shipping it taught me a lesson about verification I have kept since. A release note claimed amounts now print the ₹ symbol. They did not. The fonts were embedded, but every figure was still drawn in a face where ₹ renders as a superscript ¹, an error invisible in code review because the code was plausible and only the rendered page was wrong. The eval that guards it now renders the PDF and reads the text back off the page, asserting on what a reader would actually see. The same habit caught a receipt filed into the wrong financial year, which made one document disagree with itself by ₹1,202. Documents that add up are the product. Everything else is decoration.Selling It Honestly
The product needed a front door, and the front door got the same design standard as the app. The marketing site at cleantab.in is built on the product's own metaphor rather than a borrowed trend: a khata, a ledger that draws itself in as you scroll. Rules underline themselves, numbers count up, and mono annotations sit in the margins the way a bookkeeper's pencil notes do. The centrepiece is a scrollytelling pipeline that tells the whole product in one pinned scene, a receipt is snapped, read field by field, jarred for tax, and filed into the folder, so a visitor has watched the product work before a single feature is named. The pricing page is one comparison table and nothing else. Cards with adjectives got deleted, both plans sit side by side with every limit stated, and the yearly price is anchored to the one number the audience already knows, less than a single CA filing. The privacy page could have been a list of negations. It became the site's one dark act instead, with the copy rewritten positive: "It all lives in your Drive." The same honesty is enforced in the plumbing. The site runs analytics behind an opt-in consent banner, geo-gated at the edge so pages stay static. The app runs none. The free tax calculator carries a masking attribute so the figures a visitor types are never captured by session recording, and five places where the site claimed "no tracking" were rescoped to say exactly where that is true rather than quietly deleted. The launch still had to be earned. The night before, a full audit of my own product found the kind of bug that ends trust in a finance app: every plan and quota gate failed open when a request simply omitted its identity cookie, so deleting one cookie in devtools unlocked every paid feature. It also found two test harnesses that had been green for weeks because they tested hand-copied versions of the real code, a passing test of a copy being a lie with a checkmark. The gates now refuse without identity, every harness imports the code it claims to test, and the suite grew to eleven. The version was deliberately reset to 1.0.0, with release notes rewritten to describe what the app does rather than the archaeology of how it got there, and Cleantab launched on 27 July 2026 on Product Hunt and Peerlist. Free tier for light use, Pro at ₹299 a month or ₹2,399 a year on Razorpay, and my own year's books reading ₹0, matching the accountant to the rupee.Platform Evolution
Lessons
- Correct engine, wrong inputs, wrong product The tax maths was never the bug. The income list feeding it was. Verifying the glamorous part of a system while trusting the boring part is how a right answer becomes a ₹2.44 lakh wrong one.
- Justify inclusion, never exclusion On a personal bank account most credits are not income. Every ticked credit carries its reason in plain English, and anything unjustified stays out until a human says otherwise.
- Confidence is a design material The employer guess ships with low confidence on purpose so the review screen draws the eye to it. Where a verdict lands in the interface matters as much as whether it is right.
- Assert on what the reader sees The ₹ that rendered as ¹ passed every code review and failed on paper. The eval now reads the rendered PDF back, because the artefact the user holds is the only truth worth testing.
FAQ
Because the user's books should survive the company. Drive means the data is readable without Cleantab, in CSVs Excel opens, shareable with a CA through Drive itself, and verifiably not on our servers. The app holds only plan and quota counters. The drive.file scope means it cannot even see files it did not create. The cost is real engineering pain, Drive permits duplicate names and has no transactions, and that cost is paid on our side of the boundary rather than the user's.
Amount, merchant, GST, date, and a suggested category, extracted by Gemini from the photo or PDF. When a field cannot be read it stays empty and says so rather than guessing. A receipt dated in a different financial year is filed into its own year, not the year it was photographed in.
A section of Indian tax law for professionals that deems 50% of gross receipts to be profit and taxes that, ignoring individual expenses. It is why most freelancers' tax depends almost entirely on getting the income list right, which is exactly where the design effort went.
It has to justify the inclusion. Known clients, recurring payers with client-like patterns, and payments carrying professional markers get ticked with the reason stated. Personal-looking transfers land unticked in a couldn't-tell bucket. The one honest gap: a family member who transfers money monthly can read like a client on recurrence alone, so recurrence-only verdicts carry low confidence and surface for review instead of settling silently.
The engine computes slab tax, the 87A rebate, advance-tax instalments, EPF and state professional tax where they apply, and it matched a practising accountant's figure to the rupee on a real year with 1,114 transactions. The honest answer is that the number is as right as the income list, which is why the review experience is the real tax feature.
Nothing, which is the point. The folder is in your Drive and stays there. There is no export step because there was never an import into anywhere else, and there is no server-side copy to request deletion of.
Because the audience decides with a comparison, not a mood board. Cards with adjectives were deleted, the two plans sit side by side with every limit stated, the yearly price is anchored against the cost of a single CA filing, and the small print is printed small rather than hidden behind a link. The page sells by being legible, which is the product's whole pitch in miniature.
The phone is where receipts happen, and a PWA installs from a link, works offline, and sends reminders without a store gatekeeping releases. The desktop site shows a QR code that hands the session to the phone. A Play Store presence via TWA is on the roadmap, but the product did not need to wait for it.