Grocery Price Intelligence
Panion
A cross-store price comparison app for grocery shoppers in St. John's, Newfoundland. Compare prices, track deals, plan meals.
Your Stores
Demo
See it in action.
The Problem
Groceries in NL cost more.
You had no way to know where.
Four years working in retail gave me a front row seat to a frustration most people just accept. Customers complained constantly: prices higher than the store down the street, bills higher than expected, no easy way to know before they got to the checkout. I felt it myself too. Browsing five flyers with colorful graphics trying to compare a single product. Instacart marking up prices and calling it convenience. Going home after a grocery run to find the milk expired, or realizing I thought I had eggs but didn't.
The tools existed but none of them solved the full problem. Flyer apps were clunky. Delivery apps weren't built for price-conscious shoppers. Nothing tracked what you had at home, warned you before you ran out, or helped you plan a meal around what was actually on sale.
So I built it. Panion started as an idea in my last semester. I didn't take it seriously until March 2026, when I realized my portfolio needed something real. Not another tutorial project, but something that solved a problem people actually have. Three months later, after late nights, stubborn bugs, and more edge cases than I expected, Panion is that thing.
What It Does
Six features. One grocery run.
Panion links price comparison, shopping lists, pantry tracking, recipes, and AI meal planning into a single flow.
Price Comparison
Search any product and see current prices across all three stores side-by-side, with unit pricing for fair comparison across different pack sizes.
Newfoundland Eggs Large
Dairy ยท 12pk
Prices across stores
Price looks wrong? Report it
Watchlist & Alerts
Save the products you buy regularly. Get a push notification the moment the price drops at any store.
Shopping Lists
Build your grocery list. Panion automatically calculates the estimated total at each store so you know the cheapest run before you leave.
Pantry Tracker
Log what's at home with quantities and expiry dates. Know what's running low before you add it to your list.
Recipes
Browse and save recipes with full ingredient lists. Tap to add everything to your shopping list in one go, and see which store makes the cheapest run for that recipe.
Clove: AI Assistant
An AI cooking assistant with full context: current store prices, your pantry inventory, and your dietary preferences. Get meal ideas based on what's on sale, what you already have, or what fits your diet. When Clove suggests a recipe, a save button appears. One tap and it's in your Recipes page.
Use those thighs tonight. Creamy garlic chicken. Your cream cheese covers the sauce. 20 min, fits your low-carb.
Salmon is $10.91 at Dominion this week. Lemon herb fillet โ low-carb, ~$13 total for 2.
Under the Hood
The decisions that shaped the build.
Authentication
Edge-safe NextAuth v5
NextAuth v5 required splitting auth config into two files: an Edge-safe version for middleware (no Prisma, JWT-only) and a full Node.js version for API routes. The middleware reads onboardingCompleted directly from the JWT, with no database round-trip on every request.
AI Integration
Rate-limited by cookie + IP
Clove is rate-limited using Redis counters: 10 queries/day for signed-in users, 5 per guest cookie with a hard ceiling of 15/day per IP. Enforced via INCR/EXPIRE on Upstash Redis, which handles edge deployments without persistence issues.
Product Decision
Too feature-dense. Built it anyway.
Early feedback was consistent: six features was too much for a v1, pick one and nail it. I understood the argument. I disagreed. The features only make sense together. Price comparison without pantry tracking is half the value. Recipes without knowing what's on sale misses the point. I built the full scope to find out if the integrated experience was worth it. The answer was yes.
Testing
Security boundary tested explicitly
Vitest integration tests run against a real Neon branch database (not mocks). Every route that touches user data verifies that a user cannot read or modify another user's records. The userId scoping is an explicit assertion, not an assumption.
Honest Reflection
What shipped. What didn't.
Stack