Dani
Retail clienteling platform for visits, messaging, promotions, and check-ins
Project Details
High-touch retail teams usually manage client relationships across scattered tools: a point-of-sale system for purchases, separate notes for preferences, ad hoc messaging for follow-up, and no clean way to know when a customer actually walks into the store. That makes premium service inconsistent, slows down staff response times, and leaves store owners without a single place to see customer context, live activity, and campaign performance.
Dani brings the full clienteling loop into one product: a customer mobile app, a store dashboard, and a real-time backend that keeps both sides in sync. Customers can join a store with a PIN, check in with a QR code, chat with sales staff, view promotions, and manage preferences, while store teams can handle messaging, promotions, visits, check-ins, and analytics from one dashboard.
What It Does
QR Check-In
Customers scan a store QR code when they arrive, and the backend validates access before notifying connected store staff immediately. That removes the usual front-of-house guesswork around who has walked in and who needs attention.
Clienteling Chat
Customers and store teams share text and image messages in one-to-one conversations across mobile and web. Websocket delivery, optimistic UI, read-state syncing, and notification fallbacks keep the thread usable in real retail conditions.
Promotion Broadcasts
Store teams can create image-led promotions, manage active dates, and send offers to a single customer or their wider audience. That turns campaigns into a direct extension of the client relationship instead of a separate marketing workflow.
Customer Profiles
The dashboard pulls together spend, last visit, scheduled visits, purchase history, notes, and shopping preferences into one record. Staff get the context they need before replying, planning an appointment, or recommending product.
Store Dashboard
Owners and salespeople work from a single dashboard that combines QR and PIN access, check-ins, visits, messaging, promotions, and analytics. It reduces tool-switching and gives the team one operational surface instead of several disconnected ones.
Role-Based Access
Store owners can manage salespeople, settings, and sensitive actions like PIN regeneration, while sales staff still get the day-to-day tools they need. JWT-based role checks keep the workflow flexible without turning permissions into an afterthought.
In Action
Highlights
What We Built
Dani is a retail clienteling platform built as a three-surface product: an Expo and React Native customer app, a Next.js dashboard for store teams, and a FastAPI backend backed by Supabase. Customers sign in, connect to a store with a PIN, keep conversations with staff, browse current promotions, manage shopping preferences, and review visits or purchases from one mobile app. Store owners and salespeople work from a role-aware web dashboard for QR and PIN access, check-ins, customer records, messaging, visit planning, promotions, and analytics. The backend uses direct PostgreSQL queries for screen-specific payloads, Supabase Storage for logos and message media, and websocket connections for real-time updates. Together, the system turns high-touch retail service into a product instead of a collection of disconnected tools.
The Hardest Problems
The difficult part was not drawing the interface; it was keeping three user types coherent across three clients and one shared data model. Customers, salespeople, and store owners all touch the same conversations and customer records, but they need different permissions, different navigation paths, and different notification behavior. Real-time delivery also had to degrade gracefully: active browser tabs get in-app alerts, background dashboard sessions get browser notifications, and offline mobile users fall back to APNs push delivery. Several dashboard screens also depend on aggregated context such as last visit, spend, preferences, unread counts, and scheduled appointments, which meant the backend had to favor purpose-built SQL over shallow CRUD endpoints. That architecture work is what makes the product feel immediate instead of stitched together.
What We Learned
The biggest lesson is that clienteling only works when relationship context and operational actions live side by side. A message thread matters more when it sits next to visit history, purchase totals, and promotion tools, and a check-in alert matters more when it links straight into the customer record. If this moved into a next phase, the first improvement would be stronger shared contracts across the mobile app, dashboard, and backend so event payloads and API types are defined once instead of repeated across repos. A monorepo or shared SDK would also make websocket events, analytics models, and role capabilities easier to evolve without drift. The product proved a simple point: good retail software is really orchestration software disguised as customer service.
The Result
Dani now covers the full loop from store discovery and arrival to follow-up messaging and retention campaigns. Customers can join a store with a PIN, check in with a QR scan, share preferences, and stay connected through a native app, while store teams can respond from a browser dashboard with live alerts and deeper customer context. The repository points to deployment-ready infrastructure such as Supabase auth and storage, websocket messaging, APNs notifications, and Azure-hosted API targets, even though no public customer-facing URL is documented here. The guiding principle behind the build is simple: if retail relationships matter, the software should remember the relationship for the team.
Like what you see?
Let's build your next product together.