SliceOfPie
"Every bill-splitting app wanted sign-ups and sent your receipts to a server. I just wanted to scan, split, and share what everyone owes — with your payment info right there. One link, works in the browser."
Split bills without the awkward math. Snap a receipt, assign items, add tip, and share who owes what — all offline, all on-device.
Live Demo
Why
Every bill-splitting app I found either required everyone to sign up, needed an internet connection, or wanted my data. SliceOfPie runs entirely in your browser — no accounts, no backend, no tracking. Install it as a PWA and it works at the restaurant even without signal.
By the numbers
- Lighthouse (mobile): 99 performance, 100 accessibility, 100 best practices, 100 SEO. 0 ms of blocking time and no layout shift.
- About 26 KB of JavaScript (gzipped) to start. The scanner (about 36 MB) only downloads after you ask for it, then works offline.
- No accessibility issues found by axe on any screen, in light or dark.
- 199 unit tests and 42 end-to-end tests, each end-to-end test run on a phone and a desktop screen, all on every push.
- No framework: about 5,200 lines of TypeScript in 50 small modules.
Features
- Even or by-item split — tap people's names under each item (or tick their column on a computer); items nobody is on are flagged before you move on
- The answer first — the bill screen opens with what's owed back to you (or your share, if someone else paid), then each person's amount and a pie of the shares
- OCR receipt scanning — snap a photo with the in-app camera (guide frame, light and hold-still hints), upload one, drop or paste one on a computer, or share one from your gallery (Android, desktop Chrome). PaddleOCR reads it on-device in a Web Worker and picks out the items (including names that wrap onto a second line and "2 x" quantities), discounts, subtotal, tax, tip, total, merchant and date. A live line shows whether the items match the receipt's total, and a photo that can't be read or doesn't add up offers a retake. In an even split, a scan fills in the total
- Offline scanner, on your terms — the scanner (~36 MB) downloads once, after you say yes; Settings shows whether it's ready offline and can download or remove it
- Tip & tax — preset tip buttons, custom %, pre-tax or post-tax, round-up toggle; a tip already printed on a scanned receipt is used as-is instead of adding another
- Bill history — saved to IndexedDB under a name you choose, track who's paid with one tap; Home lists the bills still unpaid. The app asks the browser to keep it, and Settings exports it to a file and imports it back, for a backup or a new phone
- Share or copy — on a computer the bill copies to the clipboard in one click; on a phone it opens the share sheet. Either way your payment details (Venmo, Zelle, Cash App, or your own) are included, and there's a PNG version too
- Picks up where you left off — a reload, or the phone dropping the app while you open Venmo, brings you back to the same screen with the bill intact
- Works like an app — installable, with home-screen shortcuts (scan, enter a total, who owes me), the system back gesture, and updates that apply themselves (held back with a "new version ready" notice while you're in the middle of a bill)
- Phone, tablet and desktop layouts — tabs and a sticky action bar on phones, a live summary beside the steps on tablets, a side rail and a column per person on computers
- Accessible — axe finds no WCAG 2.2 AA issues on any screen in either theme; screen-reader announcements, native dialogs, a color-blind-safe person palette, and layouts that hold at 200% text
- Dark/light theme and currencies — follows your system or set manually; USD, EUR, GBP, JPY and more
- Privacy-first — no server, no analytics, no cookies. Everything stays on your device
What was hard
Reading receipts on the phone. I didn't want receipts going to a server, so OCR had to run in the browser. Tesseract.js was the obvious choice, but on my test images it only got every price right 4 times out of 16. I built a small benchmark page (npm run bench) and tried PaddleOCR's models on ONNX Runtime instead: 16 out of 16. That brought its own problems:
- Size. It's about 36 MB, so the app asks before downloading it, caches it for offline use, and cleans up old versions after an update.
- Speed. It runs in a Web Worker, so the page doesn't freeze while it reads.
- Matching prices to items. It reads each piece of text on its own, so I wrote the code that puts items and prices back on the same line, correcting for a tilted photo first. At 3.5° of tilt, prices were landing next to the wrong items.
The parser is tested against the OCR output of real receipts, so a change that breaks one shows up straight away.
Money that adds up. Splitting $100 three ways gives $33.333…, and rounding each share on its own showed "$66.67 owed back to you" next to two rows of $33.33. Now the shares are worked out in whole cents. Everyone else's share is rounded to the nearest cent, and whoever paid takes the leftover, so it's $33.33, $33.33 and $33.34. A 200-case test checks that the shares always add up to the bill. Along the way I found that 178.365 is stored as 178.36499…, so the total and the shares could round in different directions. Everything now rounds through one function.
여기까지가 README 앞부분입니다. 나머지는 원문에서 읽을 수 있습니다. README 전문 보기 ↗