Inspiration
One of our teammates once had the best curry goat of her life on a road trip. She wanted to go back, but couldn’t remember the name or find the truck again. What stayed with her was the meal, without a way to return to the place that made it.
That experience became the starting point for Nibbl. We wanted to help people remember where they’ve eaten, what they ordered, and which places they want to revisit. We also wanted that record to feel personal and fun—a collection that grows with your dining experiences.
What it does
Nibbl turns restaurant receipts into a personal collection of evolving cards. Photograph or upload a receipt, and Gemini extracts the restaurant, date, total, and purchased items. You review and correct those details before confirming the visit.
Confirmed receipts earn card XP through visits, menu exploration, and repeat purchases. Each restaurant card progresses through Discovered, Regular, and House Favorite stages. Account progress unlocks badges and titles, while personal ratings, reviews, and pinned cards turn the collection into your own food journal.
How we built it
We built Nibbl with Expo, React Native, and TypeScript. An Express backend connects the app to Gemini, while Supabase handles authentication, PostgreSQL data, and private receipt storage.
We split ownership across backend and integration, receipt scanning, cards and visuals, and profile features. Shared contracts helped those pieces connect, and code reviews, automated tests, and hands-on testing helped us find integration problems.
Gemini proposes receipt details; users confirm them. The backend applies the reward rules, checks for duplicate receipts, and saves progress. Reading an image alone never awards XP.
Challenges we ran into
Getting the iPhone, Expo development server, Express backend, and Supabase configuration working together took more effort than we expected. An app could open successfully while its backend was still unreachable, and receipt processing introduced another connection to diagnose.
We also had to turn inconsistent receipt text into usable data without hiding uncertainty. Abbreviated dish names, unclear quantities, and missing fields made editable confirmation essential.
Integrating parallel work brought its own challenges. Card details, reviews, authentication, and profile updates touched related screens, so resolving Git conflicts was only part of the job—we also had to verify that the combined behavior still worked.
Accomplishments that we’re proud of
We got real receipt photos through Gemini and into editable drafts, and tested confirmation through persisted card progress. We built evolving restaurant cards alongside profile editing, reviews, pins, badges, and title selection.
We’re also proud of the reliability work behind that experience: duplicate protection, transactional rewards, retry behavior, private account data, and reveal recovery. Our integration checks passed 336 automated tests and full TypeScript checking, alongside browser testing and iPhone testing by the team.
What we learned
A working screen doesn’t prove the whole feature works. We learned to trace requests across the phone, backend, database, and external API instead of assuming every failure came from Gemini.
We also learned that merging code and integrating a product are different tasks. Features that worked separately could still interfere with navigation or discard unsaved edits when combined. Clear ownership helped us build in parallel; testing the combined app made that work useful.
What’s next for Nibbl
Our immediate priority is removing the seeded restaurant restriction so receipts from any restaurant can create cards. That includes consistent restaurant and dish identities, so returning to the same place grows the existing card.
We also want to finish public sharing, favorite-order selection, and clearer reward breakdowns, then polish restaurant imagery and avatars. Before calling the app ready, we’ll complete the full iPhone flow against a reliably reachable backend and test recovery across uploads, sign-ins, and interrupted reveals.
Built With
- expo-router
- expo.io
- express.js
- gemini-api
- github
- node.js
- postgresql
- react-native
- react-native-reusables
- supabase
- typescript
- vitest
- zod
Log in or sign up for Devpost to join the conversation.