Inspiration

I could never find a good restaurant to take my partner. The best places in Sydney weren't on the first page of Google: small family-run spots with great ratings and only a few hundred reviews, drowned out by places with thousands. I wanted something that found those hidden gems for me, respected dietary needs, and didn't track me while doing it.

What it does

Ursafind (HiddenGemAI) finds highly rated but little-reviewed restaurants across Sydney and NSW and shows them on a mobile-first dashboard:

  • Filters for dietary needs, allergens to avoid, cuisine, dishes, meal type and price.
  • A chat assistant ("I feel like Korean in the inner west") that recommends only from the reviewed list, using Gemini on Vertex AI for conversation and Qloo's taste data for dishes and venue facts.
  • Venue pages with Google Maps links, photos, recent Google reviews with attribution, and a short AI-written summary labelled as such.
  • A researcher widget showing what the bear mascot is searching for.
  • An RSS feed, a read-only public API, and dark mode.

A human publishes every venue: nothing the AI finds goes live until the operator approves it in the admin CLI. Dietary and allergen tags are marked as guessed from listing text unless confirmed. The site never says a venue is "free" of an allergen, only which allergens a listing mentions.

How we built it

  • Frontend: React, Vite and Tailwind, served as a static site from a Cloud Storage bucket, with an optional global HTTPS load balancer for a custom domain.
  • Backend: three Python/Flask services on Cloud Run:
    • a public read-only API with caching, rate limiting and security headers;
    • a private daily researcher, triggered by Cloud Scheduler, that queries Google Maps data through SerpApi under a hard per-run request ceiling and scores venues on rating against review count;
    • the chat service, with origin checks, a honeypot, request limits, budgets and a kill switch.
  • Data: Firestore, with a strict venue lifecycle (pending_review → published → archived); secrets in Secret Manager; everything in Terraform.
  • Delivery: GitLab CI. Every promotion from dev to test goes through a merge-request gate running ruff, pytest, Semgrep SAST, secret detection, Checkov, Trivy, TruffleHog and the frontend build. Production applies only after a human approves the release.
  • AI agents: Claude Code agents did most of the development, working through GitLab issues and recording every mistake, fix and piece of guidance in a "police file" compliance ledger. Each merge request also gets an adversarial review workflow, where findings have to survive agents trying to disprove them.
  • GitLab Duo: the built-in Code Review and Security Review flows review merge requests. We also built five custom Duo flows: a skeptical review for the dev branch, a pipeline failure explainer, a nightly sweep of new dev commits, a release readiness check, and an issue intake check.

Challenges we ran into

  • Cost control: a daily AI researcher and a public chatbot can burn money fast. We added layered kill switches (an environment ceiling plus a planned Firestore runtime switch), hard request ceilings and per-client throttles.
  • Allergen honesty: we refused to let the AI claim "peanut-free" when it's guessing from listing text.
  • First production deploys: a missing Artifact Registry permission, a Cloud Run secret-propagation race, and Google's front end silently swallowing /healthz on run.app addresses.
  • Image builds that took 20+ minutes on a saturated disk, and fixable CVEs in the base image that we removed before pushing.
  • GitLab Duo flows only start from accounts with Duo access, so our agents' bot token couldn't trigger them. We had to find a safe way to let agents start reviews.
  • A revoked token, exhausted CI minutes, and moving the project into a new GitLab group mid-hackathon.

Accomplishments that we're proud of

  • A live production deployment, built entirely with Terraform and a gated CI pipeline.
  • A real human-in-the-loop design: no venue publishes itself.
  • Adversarial review that caught real bugs before test: old venues being re-dated as "new" in the feed, rate limits that could be bypassed with a forged header, and a summary prompt that could have invented reviewer praise.
  • GitLab Duo working as part of the lifecycle, alongside our own agents rather than replacing their checks.
  • A repository that stays generic, so anyone can fork it for their own city with their own branding and domain.

What we learned

  • AI agents ship fast, but they need guardrails: rules, a ledger of past mistakes, and skeptical reviewers that try to disprove findings.
  • "Inferred" and "verified" are different things, and the UI should say which is which.
  • Cost limits and kill switches belong in the design from day one.
  • Each AI reviewer catches different things: Duo, our adversarial workflow and the security scanners each found issues the others missed.

What's next for Ursafind.com - Hidden Gem AI Restaurant Finder

  • Switch on the daily researcher in production and publish the first venues it finds on its own.
  • Go live on ursafind.com behind the HTTPS load balancer.
  • Ship the expanded tags and filters for all dietary needs, allergens, cuisines, dishes and meal types.
  • A human confirmation step for backfilled venue details.
  • Expand beyond Sydney and NSW, and let users save favourites without tracking.

Built With

Share this project:

Updates

Submission history