Inspiration

Most neighbourhood kirana stores in India still write bills by hand. The lines are added in a hurry, the total goes at the bottom, and nobody checks it. A few rupees off on each bill adds up over a month, for the shopper and for the shopkeeper who keeps a khata, the running credit book for regular customers.

What it does

  • Snap or upload a photo of a handwritten bill in Hindi, English or a mix of both.
  • Gemini Flash reads every line on the server into item, quantity and amount. The API key never reaches the browser.
  • Every line stays editable, so a misread is easy to fix.
  • Bill Snap adds up the lines and checks them against the written total. Red means the total does not match. Green means it does.
  • Save the checked bill to a customer khata, and export any khata as a CSV file in one click.
  • Demo mode includes six sample bills, so anyone can try the full flow without an API key.

In the demo, the Gupta Store bill says 200, but its lines add up to 194. Bill Snap flags it as 6.00 short. I add the missing item, the strip turns green, and I save the bill to the khata of Anita Sharma. The Raju General Store bill comes out 5.00 extra.

How I built it

I started in an empty folder, installed the Devpost Learn skill pack and ran its skills in order with Cursor as my coding agent:

  1. Start: my learner profile.
  2. Scope: scope.md, what is in and what is out for a small build.
  3. PRD: prd.md, the user, the problem and the main flow.
  4. Spec: spec.md, the screens, the data and the checks.
  5. Build: checklist.md, one slice at a time, each committed only after its checks passed, plus app-map.html.
  6. Ship: the public repo, the MIT license, the README and the video.

The stack is Next.js 16, React 19, TypeScript, Tailwind CSS, Gemini Flash for vision and Vitest for tests. The heart of the app is a pure function called verifyTotal. Nine tests cover mixed language parsing, a match, a mismatch, paise tolerance and edits.

Challenges I ran into

  • Handwriting in two scripts on one bill. Making every line editable was the honest answer, because no model reads every bill perfectly.
  • While recording the demo I found a render loop that crashed the extract page, and a type error that broke the production build. Both are fixed on main.
  • My sample bills first had real brand names on them. I replaced them with generic items like chai patti, noodles and biscuit.

What I learned

Planning first works. Writing the scope before any code kept the build small and finished. Keeping the core check as a pure function with tests meant I could change the screens without worrying about the maths.

What's next

More Indian languages, offline use for shops with weak internet, and a simple khata summary a shopkeeper can share with a customer.

Built With

Share this project:

Updates

Submission history