Selected work / 2026
Nila: building an AI accountantPaused
About four months building an AI accounting product on my own, from messy invoice PDFs to GST workings an accountant can check.
- My role
- Solo founder-engineer, from talking to firms to shipping it
- Timeframe
- About four months in 2026 (May to October)
- Working system
- PDF upload, invoice review, GST workings, exports and Tally posting
- Outcome
- Worked on real bills; paused before any firm adopted it
I spent about four months building Nila, an AI accounting app for chartered-accountant firms in India. The job was simple to say: take the pile of bills a client sends every month, get the details into a working file, and show the accountant exactly what needs checking before they file the GST return.
I did all of it myself: visiting firms, deciding what to build, the Phoenix backend, the React front end, the extraction pipeline, deployment, and a Windows connector for Tally. I leaned heavily on AI coding agents. They wrote a lot of the code, and I made the product and engineering calls, chased down failures, and decided what stayed.
Source code · Product website · Extraction deep dive
One bill, then a whole month
You upload a PDF. Nila works out which pages belong to which invoice, reads each one, and puts the result right beside the original bill. The accountant can check the tax, compare the totals with what’s printed, and fix anything that’s off.
An invoice in review. Open the image to see the full screen.
All the month’s invoices then roll up into a sales working, with GST checks, GSTR-1 sections, and an Excel working and JSON file to download. The accountant always has the source bills to go back to, so they aren’t handed a spreadsheet of model output they have to take on faith.
The month’s summary, with the workings ready to download.
Where I put the boundaries
It’s a Phoenix app with a React and TypeScript front end. PostgreSQL holds the data and Oban runs the background jobs. The AI models only hand back structured readings of the bills; everything that decides money, like calculations, validation, corrections and the return itself, lives in Elixir code I can test.
The main flow:
Original PDF
→ find the pages and group them into documents
→ read each invoice, keeping where each value came from
→ clean up and run fixed checks
→ accountant reviews and corrects
→ monthly GST workings and exports
I cared about this split because “the model gave me valid JSON” and “this invoice can go into a tax return” are very different things. An invoice can come back perfectly shaped and still be in the wrong month, be missing tax details, or need a treatment the return doesn’t support.
I also kept what’s printed on the bill apart from anything calculated. If a tax amount isn’t on the bill, Nila leaves it as unknown instead of quietly turning it into zero. When the accountant corrects something, the original reading is kept, and the month is rebuilt with the correction applied.
Sales rules and corrections · How printed taxes are read
When a long upload fails halfway
Reading a big PDF takes many model calls. If one fails and you start the whole upload again, you pay twice, and invoices can shuffle around under someone who’s halfway through reviewing them.
So the pipeline saves its progress as it goes. A retry picks up where it stopped, and invoices keep the same IDs. You can look at a half-read upload, but it doesn’t count towards the month’s totals or exports until it’s finished.
Re-reading an upload that already finished is handled separately. It checks whether anyone has made corrections, and only swaps in the new result once the whole read succeeds. If it fails, the old result stays.
Posting into Tally
Nila could also post reviewed invoices straight into Tally, through a small Windows connector I built in C#/.NET. The tricky part was a lost reply: Tally might have saved the voucher anyway, and if you just retry, you book the same sale twice. So the connector checks for an existing voucher before writing and reads it back afterwards, and anything it can’t confirm gets marked “outcome unknown” for someone to check. It worked against Tally on my own machine, but no firm used it for real. Connector source, built on the open-source TallyConnector library.
The connector running beside TallyPrime with two test companies.
The deepest work: deciding what to trust
Most of my time didn’t go into picking a model. It went into questions like where one document ends and the next begins, whether to read a PDF’s own text or an image of the page, how to shape the output, which taxes are actually printed and which are worked out, and how far you can trust a check that says a value is “on the page”.
One experiment tested a tax schema that looked clearer. The model kept copying line-item taxes into the invoice summary, or inventing a CGST/SGST split for a single combined tax amount. So I tried keeping the breakdown and the total in separate fields, plus a third version with named item fields.
I ran five bills I’d already checked by hand, five times each, through all three versions, with the same inputs, settings and examples. 74 of the 75 requests finished. A response only passed if it captured the summary figures exactly as printed, without adding anything that wasn’t there.
| Format | Faithful printed summaries |
|---|---|
| Earlier tax list | 18 / 25 |
| Separate breakdown and total | 10 / 25 |
| Same, with named item fields | 7 / 24 |
On one bill, the new formats kept turning a single tax total into both CGST and SGST, which doubles the tax. So I kept the old format, even though the new one looked cleaner.
It was a small test on five bills I already knew well, so it tells you nothing about Nila’s overall accuracy. The article has the full method and caveats.
Scored results and test method · Full extraction article →
What the market taught me
I visited 16 firms and tested Nila on real bills, but I never got a paying customer or even an agreed trial. Some firms had a lot of manual preparation work. Others had lighter workflows, or tools that already did the job well enough. In October 2026 I paused Nila, because nobody needed it badly enough to change how they worked.
Looking back, I should have pushed for a small trial much earlier. Getting documents and hearing about the pain taught me how the work is done, but it never told me whether anyone would actually switch and pay.

