AfterCart — Devpost Submission
Inspiration
Everyone has a theory about where to shop cheapest. Costco for bulk. Walmart for staples. The theory is wrong — not universally, but product by product. The cheapest store for your cereal isn't the cheapest store for your olive oil. Store loyalty is expensive, and most people never find out because every tool for finding out requires work nobody actually does.
We started from the other end. Not the trip you're planning — the receipt you're already holding. The data is right there. You just can't read it yet.
What it does
The product has one irreducible loop that everything else is built around:
- User photographs a grocery receipt
- OCR extracts every line item, quantity, and price
- Each item is matched to the same or equivalent product, with top-N candidates surfaced
- User reviews the matches — confirms with one tap, swaps individual items among candidates or searches through 900k products directly when the matcher missed
- User sees a single headline number: what the same basket would have cost elsewhere, and where. Item-level breakdown is available on demand
- Every upload silently contributes a timestamped price data point to the community database
How we built it
Three problems that compounded on each other — and that was the challenge.
Receipt text isn't structured data. It's two columns flattened into characters — abbreviations, loyalty discounts, store codes. We built a parser that reconstructs the structure from scratch. It outperforms a frontier vision model on real receipts, at zero cost per scan. But bad parsing corrupted everything downstream, so it had to be right before we could test anything else.
Clean text still gives you SAFWY BFLS CKNG THGH 2.13LB. We built a hybrid matcher combining text similarity, semantic embeddings, and pack-size awareness to turn abbreviation soup into a real product. Conservative by design — a wrong match misleads; no match is honest. But we couldn't validate the matcher until the parser was solid.
Then the math. The same peanut butter comes in a 16oz jar at Safeway and a 48oz jar at Costco. Comparing total prices is meaningless. We normalize to price per unit so the savings number actually means something. And we couldn't trust the math until the matching was right.
Data was the other wall. We collected prices manually, imported from real receipts, and filled gaps with AI-generated synthetic data while building the infrastructure for community uploads to replace it.
Technology Next.js, Cloud Run, Cloud SQL + pgvector, Google Vision API, Vertex AI, Gemini 2.5 Flash, Open Food Facts
Accomplishments that we're proud of
The full loop works on real receipts. One sentence that hides a lot.
The harder thing to be proud of is what we didn't do: inflate savings numbers, pretend a store covers your basket when it covers part of it, or compare a 48oz jar to a 16oz jar by total price. Hackathon demos have every incentive to make the numbers look good. We didn't.
What we learned
We came in expecting noise between store prices. We found structure instead. Different chains run different margin strategies per category — no single store wins across the board, which is the whole reason a tool that optimizes per-item rather than per-store is worth building.
GCP made the build viable. Cloud SQL with pgvector, Cloud Run for the API, Vertex AI for the LLMs — managed infrastructure was the right tradeoff for a small team moving fast. The cost is platform-specific knowledge. The alternative is owning the ops, and we couldn't afford to.
We orchestrated the build through Reconstruct.app, an agent-coordination layer for Claude. It shifted what "writing code" means. The unit of work moved from "write this function" to "describe what should happen, supervise the worker, review the seams." Speed came from clarity of specification, not the model itself — and the human's job moves to the joins, which is exactly where bad assumptions hide.
What's next for AfterCart
Polish and refining the user experience. We have enough real pricing data to launch. The next step is going live in Davis: real stores, community uploads, the flywheel actually turning.
Then pre-trip routing: once you've uploaded a few receipts, AfterCart knows your usual basket and can tell you where to shop before you go. Hindsight is useful. A recommendation you act on is better.
Built With
- claude-code
- cloud-run
- cloud-scheduler
- cloud-sql
- cloud-storage
- docker
- gemini-2.5-flash
- google-cloud
- google-vision-api
- javascript
- next.js
- node.js
- open-food-facts
- pgvector
- postgis
- postgresql
- react
- reconstruct.app
- secret-manager
- sqlite
- tailwind-css
- typescript
- vertex-ai



Log in or sign up for Devpost to join the conversation.