Inspiration

Most review tools ask, "How fast can I reply?" For a small business, the better question is "Should I reply at all?"

A cheerful template under a review that says "the food made me sick, I'm calling a lawyer" can turn a bad day into a legal problem. A reply to a spam ad gives it free visibility. And many local businesses, especially in Pakistan, get reviews in Roman Urdu, Urdu, English, or a mix of all three. Owners often can't tell whether a reply is safe without help.

That's where the tagline came from: Know when not to reply.

What it does

ReviewDesk is a reply desk for Google Business reviews. It sorts every review into one of four lanes:

Lane Meaning
Reply A public reply is safe. A draft is ready for your approval.
Check facts The review makes a claim you should verify before answering.
Hold Do not reply publicly yet. The owner needs to review it first.
Report Looks like spam or a policy violation. Guidance for Google's report option.

For each review it:

  • writes a 30–80 word draft in the reviewer's language, with an English copy so the owner knows exactly what it says;
  • shows why it chose a lane, such as "risk flag: health";
  • lets you edit, keep draft versions, insert saved phrases, and copy the reply;
  • records every decision in a ledger with its reason.

Nothing is posted automatically. The owner approves each reply and copies it by hand. Live posting to Google is a separate, optional setting.

An opt-in Autopilot can record clean, high-star replies after a veto window, but only inside a strict safety policy: it starts off, dry run is on by default, mixed-sentiment reviews wait for a human, and a daily cap limits volume.

Around that core there is a workspace for real use: team roles (owner, manager, responder, viewer), keyword automation rules like "Hold health and legal claims", reusable reply templates, CSV import and export, search and filters, and keyboard shortcuts.

How I built it

  • App: Next.js 16 and TypeScript, deployed on Vercel.
  • Data: Prisma with PostgreSQL.
  • UI: Tailwind CSS and daisyUI, with a motion layer (aurora background, scroll reveal, count-up numbers) that respects reduced-motion settings.
  • Engine: the prompts and policy rules live in a pure logic layer, separate from the database and secrets, so the rules can be read and reviewed on their own.
  • Security: Google credentials are encrypted with AES-256-GCM before storage and never sent back to the browser. Passwords are hashed with bcrypt, sessions use signed httpOnly cookies, and reset links are single-use. Review text goes to the model provider for triage and nowhere else.
  • Process: I built it with an opencode coding agent. An AGENTS.md file set the build order, with a stop after each step so I could review the result before moving on.

The model only suggests. A deterministic policy decides whether an Autopilot reply may be recorded:

$$ \text{auto}(r)=\big[\text{stars}(r)\ge s_{\min}\big]\;\wedge\;\big[\text{lang}(r)\in\mathcal{L}{\text{trusted}}\big]\;\wedge\;\neg\,\text{risk}(r)\;\wedge\;\neg\,\text{mixed}(r)\;\wedge\;\big[n{\text{today}}<c\big] $$

A reply that passes is recorded only after a veto window of $T = 30$ minutes, and the owner can undo it. If any condition fails, the review goes to the approval queue instead.

Challenges

  • Roman Urdu has no spelling standard. "Khana thanda tha" and "khana thanda thaa" both mean the same thing. Detecting the language and keeping the reply natural took the most care. I added a trusted languages setting so Autopilot only touches languages a native reader has checked.
  • Reviews are untrusted input. The demo inbox includes a spam ad and a prompt-injection attempt ("Ignore your previous instructions…"), so the rules are tested against hostile text.
  • Deciding what the AI may never do alone. Writing replies was the easy part. The hard design question was which decisions stay with a human. The answer is encoded as policy rules, not just a prompt.
  • Reviewing agent-written code. A review pass caught a missing constant that would have crashed the credential test, an API route that had been deleted while the UI still called it, and type errors in the Autopilot settings.
  • Accessibility versus animation. My animated headings were silent to screen readers until I added a readable copy of the text.

What I learned

  • Agents work best with clear rules, small steps, and a stop after each one.
  • Safety rules belong in readable code, not only in a prompt.
  • Type checks and lint don't catch everything, such as a UI that screen readers can't read or a route that was quietly removed.
  • For a tool that writes in public, a clear "don't reply" is worth as much as a good draft.

What's next

  • Post approved replies directly to Google through the connected account.
  • Tests for the policy rules and the language checks.
  • Dark mode, once the remaining hard-coded colors move onto theme tokens.

Built With

  • ai
  • bcrypt
  • daisyui
  • eslint
  • github-actions
  • google-business-profile-api
  • google-reviews
  • jwt
  • llm
  • lucide-react
  • neon
  • nextjs
  • node.js
  • nodemailer
  • postgresql
  • prettier
  • prisma
  • radix-ui
  • react
  • rest-api
  • shadcn-ui
  • tailwindcss
  • typescript
  • vercel
Share this project:

Updates

Submission history