Inspiration
Every week, Canadians walk into grocery stores with no idea whether the prices they're seeing are fair. Eggs at one Walmart might be $1.50 more than the No Frills two kilometres away but there's no easy way to know that before you leave the house. With the cost of living rising sharply across Canada, that information gap hits hardest for families on tight budgets.
We asked ourselves: what if every shopper's phone could be a price scanner that contributed to a live, community powered database? That question became Maple Price.
What it does
Maple Price is a community powered grocery price tracker that helps Canadians find the best local deals on everyday essentials.
Maple Price Does The Following:
1) Browse: Open the map and instantly see real grocery stores near you, pulled live from OpenStreetMap. Hot-pink pins show community-submitted deals nearby. 2) Scan: Take a photo of any price tag or receipt. Our in-browser OCR (powered by Tesseract.js) reads the price, product name, and unit automatically. The image is permanently archived to Cloudinary so the community can verify it. 3) Review & Submit: Confirm or correct the extracted data, then hit submit. Your price entry goes live instantly for everyone in the area. 4) Track: Save deals to your personal list and jump directly to Walmart or Instacart to buy with one tap. 5) Plan: Use the Grocery List page to build your shopping list and ask the AI recipe assistant what you can cook with the ingredients you already have.
How we built it
We built Maple Price as a full-stack web application over a single hackathon session.
The tech stack is straightforward:
$$\text{User} \xrightarrow{\text{scan}} \text{OCR (Tesseract.js)} \xrightarrow{\text{extract}} \text{Price Entry} \xrightarrow{\text{store}} \text{SQLite DB}$$
The frontend is React + Vite, styled with custom CSS and animated with Framer Motion The backend is a Node.js / Express REST API backed by an SQLite database Tesseract.js runs fully client-side the browser reads the price tag without any server round-trip Cloudinary stores the raw receipt image permanently so the community can verify submissions Auth0 handles authentication so users have persistent profiles and contribution histories React Leaflet powers the Browse Map using free OpenStreetMap tiles.. no paid API key needed The Overpass API fetches real nearby grocery stores from OpenStreetMap data in real time Tailscale Funnel gave us a secure, public https:// demo URL without deploying to a server
Challenges we ran into
Maps without a paid API Google Maps requires a billing account. We replaced it entirely with react leaflet + CartoDB Dark Matter tiles + the Overpass API. The result looks just as good, costs nothing, and actually returns real store data rather than hardcoded pins.
Auth0 on a Tailscale network auth0-spa-js throws a hard error on plain http:// non-localhost origins. We debugged this blind (blank white screen, no browser console access remotely) by building a React Error Boundary first, which finally showed us the exact error message. The fix was Tailscale Funnel a one command HTTPS tunnel.
OCR accuracy vs. user experience We couldn't make Tesseract perfect, so instead we made it collaborative the raw OCR text is always shown to the user alongside editable form fields. The user is the last line of defence before anything hits the database.
Running multiple dev processes cleanly With both a Vite frontend and an Express backend, plus Tailscale Funnel running in parallel, port collisions were a constant issue. We solved this by locking Vite to strictPort: true on port 5176 so it fails loudly instead of silently jumping to a new port.
Accomplishments that we're proud of
1) Zero paid APIs. The map, the store data, and the OCR all run entirely on free, open-source infrastructure. React Leaflet + OpenStreetMap + the Overpass API replaced Google Maps completely with real, live store data that any paid alternative would charge for.
2) Parallel OCR + cloud upload. When a user hits "Extract Price Data," Tesseract.js reads the image locally in the browser at the same time as Cloudinary uploads it to the cloud. Neither blocks the other the user gets results as fast as possible.
3) Debugging a blank screen remotely. Auth0 silently crashes the entire React tree on non-HTTPS origins. With no browser console access on the remote device, we built a React Error Boundary first which finally fixed the exact error then solved it with Tailscale Funnel to get a real https:// URL without any deployment.
4) Full stack in one session. Frontend, REST API, SQLite database, auth, cloud storage, OCR, real time map data, and a live public demo URL all built and wired together end-to-end during the hackathon.
5) A design that feels like a real product. Dark mode, smooth Framer Motion transitions, custom hot pink accent colour, responsive layouts, and interactive deal cards that link directly to external retailers. It doesn't look like a hackathon project. it looks like something people would actually use.
What we learned
1) OCR on receipts is hard. Price tags come in wildly different fonts, lighting conditions, and layouts. We wrote custom regex extractors for prices, product names, and units — and still let users manually correct anything the model gets wrong.
2) Auth0 SPA SDK requires HTTPS on any non localhost origin. This meant we couldn't use a plain Tailscale IP for our live demo we had to learn Tailscale Funnel to get a real https:// URL on the fly. The Overpass API is incredibly powerful. A single query can return every grocery store, supermarket, and convenience store within 3km of any coordinate for free, forever, with no rate limits for reasonable usage.
3) React Error Boundaries are essential in production apps. Without one, a single Auth0 initialization failure would blank the entire page with no error message nearly impossible to debug remotely.
What's next for Maple Price
1) Push notifications when a deal appears near you 2) Price history graphs per product per store 3) Leaderboard for top community contributors 4) Mobile App
Built With
- api
- auth0
- cloudinary
- css
- express.js
- framer
- html
- javascript
- leaflet.js
- lucide
- motion
- node.js
- openstreetmap
- overpass
- react
- react-leaflet
- router
- sqlite
- tailscale
- tesseract.js
- vite
Log in or sign up for Devpost to join the conversation.