Inspiration
Grocery shopping in a shared household creates a surprising amount of overhead. Someone buys the groceries, someone else has to work out which items belong to whom, shared products need to be divided fairly, roommates have to settle up, and eventually someone realizes the eggs, rice, or paper towels are gone.
We kept running into the same problem: every existing app solves only one part of it. Expense-sharing apps divide money, grocery-list apps keep lists, budgeting apps categorize transactions, and inventory apps demand constant manual care. None of them understand how a household actually shops.
That led to a simple idea which became Divvy's foundation:
The receipt is the source of truth.
A receipt tells you what actually entered the household, when, for how much, and who it belonged to. Over time, those receipts form a history we can learn from.
What it does
Divvy turns a grocery receipt into a finished split in a few taps.
- Scan a receipt. Photograph or upload it, and Divvy extracts the individual items.
- Predict ownership. Divvy suggests who each item belongs to. Ownership isn't limited to one person; an item can belong to any combination of household members, such as Coke Zero → TJ, Paper Towels → Everyone, or Fresh Cilantro → Sumedh + Savar.
- Ask only when unsure. High-confidence items are assigned automatically, and the user reviews only the uncertain ones.
- Split and settle. Divvy calculates each person's share and maintains running balances, which can be simplified so the household settles up with fewer payments.
- Learn from corrections. Every correction becomes a new observation, so the model gets better at predicting for this household.
- Predict what you're running low on. From purchase history, Divvy estimates restock timing (for example, sandwich bread bought every 8 days, last bought 9 days ago) and suggests items for the next grocery list, with no manual inventory tracking.
People in a household don't need to be registered users, so a household of four can start using Divvy immediately.
How we built it
We chose a stack that lets us support iOS and Android while keeping infrastructure simple enough to iterate on quickly.
- Mobile: Kotlin Multiplatform with Compose Multiplatform, giving us one primary codebase for both platforms.
- Backend: Kotlin with Ktor, keeping Kotlin across client and server. Ktor is the public API and handles households, receipts, grocery lists, ownership, and balances.
- Database: PostgreSQL with pgvector to store and search semantic embeddings, so we don't need a separate vector database.
- Machine learning: A Python service for embeddings, classification, semantic similarity, confidence calibration, and active learning. Ktor talks to it over a simple internal HTTP API.
- Deployment: Docker Compose on a single 4 vCPU / 8 GB Linux server, with Caddy in front of Ktor. The ML service and the database stay internal to the Docker network.
Caddy on Vultr
|
Ktor
/ \
Python ML PostgreSQL + pgvector
Challenges we ran into
- Kotlin's import overhead: Kotlin requires explicit imports, so every UI file had to be imported into each file that used it, and sometimes individual functions too. This added a lot of friction as the project grew.
- Hosting over HTTPS: iPhones block plain HTTP connections, so we had to obtain certificates to serve our backend over HTTPS on Vultr.
- Thinking long term: On a project this large, we had to plan for maintainability, not just a weekend demo. We followed agile development, which came with its own challenges, and we had to learn to work as a team the way real engineering teams do.
Accomplishments that we're proud of
- True cross-platform support: The app runs on Android, iOS, and the web (via WebAssembly) from a shared codebase.
- Stepping into bigger roles: This isn't our first hackathon, but it's the first where several of us took on larger responsibilities. We're especially proud of our pull requests and the efficient workflow we built.
- A smooth first database build: Our teammate on the database had never worked on one before, and it came together wonderfully.
- Traversing a large codebase: With so many routes and a sprawling file structure, navigating the project was difficult, and we got good at it.
What we learned
- Kotlin: We went into the weekend new to the language and came out with a much stronger understanding of it as a whole.
- Agile and software engineering: We learned far more about agile development and engineering principles, and saw firsthand how React and Kotlin differ across the frontend and ML work.
- Effective collaboration: We learned to solve problems efficiently, request and give code reviews, and resolve merge conflicts. We also learned never to hard-code passwords.
What's next for Divvy
We're focused on making Divvy's ownership predictions smarter and the app easier to trust and debug.
- Smarter ownership predictions: We plan to derive item attributes like category and dietary flags, and to return similar-history evidence alongside each prediction so users can see why Divvy suggested an owner.
- Better diagnostics: An ML status view with a resync action will make it easier to spot and fix problems with the prediction pipeline.
- Clearer connectivity: Server connection status and readable error messages will show up directly in the app instead of failing silently.
- More control over receipts: We're adding the ability to void a receipt, so mistakes are easy to undo.
Built With
- backboard
- docker
- kotlin
- ktor
- ml
- pgvector
- postgresql
- python
- vultr
- xcode
Log in or sign up for Devpost to join the conversation.