The brief came from a restaurant owner in our network. He had 4.1 stars on Google — not bad, but not where he wanted to be. The problem wasn't unhappy customers: his regulars loved the place. The problem was selection bias. Unhappy customers leave reviews. Happy ones go home and forget. He wanted to change that ratio without begging customers or gaming the system. That became Review Easy.
The Core Mechanic
The product works in three steps: a customer scans a QR code or clicks a link, they see a simple 'how was your experience?' prompt, and then the AI routes them based on their response. Positive sentiment → they're taken directly to the Google review page with a pre-filled prompt. Negative or mixed sentiment → they're taken to a private feedback form that goes directly to the business owner's email or dashboard. Public praise goes public. Private complaints stay private.
“We were careful about the ethical line here. The routing is transparent — users see a message saying positive feedback will be shared publicly. We're not hiding where they end up. We're just making it easy for the right path.”
The Sentiment Classification Layer
Our first instinct was to use a simple positive/negative/neutral classifier. We tested three approaches: a fine-tuned distilBERT model, a rules-based keyword system, and a prompt-based LLM classifier using Claude Haiku. The LLM classifier won on nuance — it correctly handled responses like 'food was great but service was slow' (mixed → private), which the keyword system always sent to the public path.
The tradeoff was latency. Haiku adds ~300ms to the response path compared to ~50ms for the local model. We accepted this because the UX moment is not time-critical — the user just answered a question and is waiting for the next step. 300ms is invisible there.
Custom Branding Without Infrastructure Overhead
Each business gets their own branded flow — logo, colors, name. The naive implementation is per-client deployments, which doesn't scale. Instead, we built a single multi-tenant Next.js app with a subdomain routing system. The URL contains a business slug (reviews.easydevs.xyz/mario-pizzeria), the app fetches that business's config from Supabase, and the entire page renders with their branding. No per-client infrastructure. Adding a new business takes 30 seconds.
QR Code Generation and Analytics
QR codes are the primary acquisition channel for local businesses — printed on receipts, table cards, menus. We generate them dynamically using qrcode.react with UTM parameters baked in so we can track which placement (table vs. receipt vs. door sticker) drives the most scans. The analytics dashboard shows scan volume, sentiment breakdown, and review conversion rate by placement. For the restaurant owner who started this, receipt QR codes outperformed table cards 3:1.
What We'd Do Differently
The feedback form for negative sentiment was an afterthought in v1 — a plain HTML form that emailed the owner. It worked, but owners rarely acted on it. In v2 we built a proper dashboard with tagging, status tracking, and response templates. Closing the loop on negative feedback is actually the most valuable part of the product for operators — but we underbuilt it the first time.
- V1 mistake: treating negative routing as a dead end rather than the start of a recovery workflow
- V1 mistake: no rate limiting on QR scans — one table card got scraped repeatedly by bots
- V2 fix: proper abuse detection using IP fingerprinting and scan frequency caps
- V2 fix: owner dashboard with feedback triage, response templates, and 30-day trend charts
The Results
The original restaurant client went from 4.1 to 4.6 stars in 8 weeks — 34 new reviews, 29 of which were 5-star. More importantly, the private feedback channel caught 3 recurring issues (a slow ticket printer, one consistently late shift) that the owner fixed. Review Easy is live at reviews.easydevs.xyz if you want to walk through the flow yourself.