Inspiration

Small businesses in the Urbana-Champaign area struggle with attracting new clientele, with most potential customers walking right past their doors. Generic promotion campaigns are most often ignored and loyalty apps are clunky apps/subscriptions that cause clutter and are inconvenient to download.

What it does

We built a real-time discount discovery engine that surfaces nearby restaurant offers using geofencing and makes redeeming them seamless through integrated Stripe checkout. At its heart, the product helps users instantly find deals around them and complete their purchase in just a few taps.

How we built it

We built the (Promo)ximity as a full-stack system with four distinct layers working together. The backend is a FastAPI application with SQLAlchemy and SQLite. It exposes a REST API that handles merchant registration, geofence configuration, customer check-ins, and offer generation. It uses Haversine math to determine whether a customer's GPS coordinates fall inside a merchant's configured radius. When a check-in triggers a geofence, the engine classifies the customer into one of four tiers — new, regular, frequent, or lapsed — based on their visit history and how recently they were last seen. We then added a loyalty token system on top: customers accumulate tokens across visits (with decay for inactivity), which unlocks Bronze, Silver, Gold, and Platinum tiers that boost their base discount by up to +15 percentage points. Every discount is hard-capped at the merchant's configured maximum, so merchants stay in full control. Offers are fulfilled through Stripe. We create a real Coupon and Checkout Session per offer, and track redemptions via Stripe webhooks that mark offers as redeemed in the database. In demo mode, a local mock checkout page stands in seamlessly when live credentials aren't configured. The frontend is a single-page app using Leaflet for the customer map and MapLibre GL for 3D building rendering. Merchants register and configure geofences through a separate registration flow. The customer view shows live geofence circles on the map, lets you simulate check-ins, and displays offer results in real time. An analytics drawer shows offer performance without leaving the page.

Challenges we ran into

The SQLite migration problem hit us mid-hackathon. After expanding our Customer model to include loyalty_tokens and loyalty_tier, we identified that SQLAlchemy’s create_all() initializes new tables but does not automatically modify existing ones. We quickly resolved this by aligning the database schema with the updated model, ensuring full support for our loyalty features without disrupting existing merchant data. Stripe's discount + checkout flow had a few footguns. PaymentLinks don't reliably apply coupons in all configurations, so we switched to checkout.session instead, which gives us a hosted page, proper coupon application, and webhook delivery for checkout.session.completed events all in one. In demo mode without real credentials, we route to a local /demo/checkout/{id} page that simulates the experience without hitting Stripe at all.

Accomplishments that we're proud of

We’re genuinely proud that we built something that is not just technically functional, but meaningful. At its core, our MVP makes discovering nearby restaurant discounts effortless and redeeming them seamless through direct Stripe checkout integration, which is one of the main features and a core part of the experience.

More than anything, we’re proud of the intention behind it. We wanted to create something that genuinely benefits small businesses while giving residents and college students in Champaign and Urbana a reason to explore more of what the community has to offer. Every supporting system exists to make that experience smoother and more empowering. It feels less like a hackathon prototype and more like the beginning of something we’d actually want to see used locally, and that’s what we’re most excited about.

What we learned

We learned more about geofencing, and about integrating Stripe Connect API to generate personalized payment links.

What's next for (Promo)ximity

We would love to expand the scale of our API to include businesses outside of the Urbana-Champaign area. We are also planning on integrating user financial history for customers to receive personalized recommendations based on known references. Lastly, we would like our data analytics campaign to include merchant analytics that businesses can use to track success of various promos and update promotional deals based on real-time data.

Built With

Share this project:

Updates