Split shared bills without the awkward math. Photograph a receipt, OCR reads the items and prices, decide who ate what, and share the result through one short link.

Timeline: August – August 2026
SplitBill solves the awkward part of splitting a shared bill: figuring out who owes what. Photograph a receipt, on-device OCR reads the items and prices, everyone marks what they had, and the app hands out one short link with the exact breakdown. No login, no install, no manual math.
It's a real, production product, live at splitbills.site, built for the Indonesian market with bilingual support (Bahasa Indonesia + English) and OCR tuned specifically for Indonesian receipt formats.
The original prototype worked, but it cut a corner that quietly broke four of its own promises: it never stored anything on a server. Every bill's data, including items, prices, and participant names, was packed into the URL itself.
| Promised | What Actually Happened |
|---|---|
| Short share links | Links were enormous, since the entire bill was encoded in the URL |
| Private bills (others can't see your amount) | Anyone holding the link could read the full payload |
| Creator sees who's paid | Payment status never crossed devices; it lived only in the browser that set it |
| Auto-delete after 24 hours | Nothing to delete. The data was the link, and expiry was only checked client-side, easy to bypass |
Fixing this meant a real backend: a database to hold bill state, short codes that resolve server-side, and privacy enforcement that can't be defeated by editing a URL, all while keeping the interface, flow, and OCR accuracy pixel-identical to the version already validated with real users.
tesseract.js, tuned ind+eng) running entirely client-side. Photos never leave the device.splitbills.site/s/AB12CD34, valid 24 hours, with QR code and WhatsApp sharing built in.| Layer | Choice |
|---|---|
| Frontend | Vue 3.5 + TypeScript, Vite 7, Tailwind CSS 4, vue-router 4 |
| State | Plain reactive() composables, no Pinia; the app's state shape doesn't need it |
| Backend | Hono + @hono/node-server, one process serving the API and the built frontend |
| Database | MySQL 8 via Drizzle ORM |
| OCR | Tesseract.js (ind+eng trained data), assets self-hosted |
| Testing | Playwright for end-to-end, Node's built-in test runner for unit tests |
| Tooling | Biome for lint and format |
getUserMedia won't run without it) and runs OCR fully in-browser. No image is ever uploaded for processing.Two layers, each proving something the other can't:
node --test, no browser) cover the money logic in the shared calculation module, specifically the rounding edge cases where a naive split could lose or invent a single Rupiah.The e2e suite runs against the production server build rather than the dev server, because the two properties actually worth proving, money computed server-side and payment status crossing devices, don't exist without a real backend in the loop.