Inspiration
Every group outing starts with the same question — "where should we go?" — and usually ends the same way: the person with the strongest opinion picks, and somebody spends the evening quietly compromising. Recommendation apps don't help, because they recommend to one person. A general-purpose LLM can list "top restaurants in Lisbon", but it is guessing about taste, and it has no way to know that a Studio Ghibli fan and a Radiohead fan will both love the same fado house.
Qloo can know that. Its taste graph connects film, music, books, games and brands to real venues, so it can predict how well a place fits a person from what they already love. We wanted to point that at the hardest version of the problem: not "what will I like?", but "what will all of us like — fairly?"
What it does
Each person adds two or three favourites — a film, an artist, a book, a game, a brand. Pick a city (or leave it blank and let your combined taste choose one), an outing type (evening, full day, date night) and a budget. The agent then plans a route and shows its work live:
- Resolves every favourite to a Qloo entity.
- Profiles each person's taste and finds what the group shares — and when there is no direct overlap, it uses Qloo's cross-domain bridge from the combined signal (e.g. an anime fan and a trip-hop fan meet at "surrealism").
- Picks a destination if none was given, and verifies Qloo actually has venue coverage there before committing (it will skip a perfect-taste beach town with no data).
- Shapes the outing from the shared taste — a music-leaning group gets a live-music nightcap, an art-leaning group starts at a gallery — keeping other categories as fallbacks.
- Gathers candidates for each stop and re-plans when a category is thin in that city.
- Scores every candidate separately for every person using Qloo's per-entity affinity, converts the scores to per-person percentiles so they are comparable, and ranks with a least-misery group score — the unhappiest person counts most.
- Assembles the route with a satisfaction ledger (whoever has been served least gets more say on the next stop) and a walking-distance penalty.
- Audits fairness and re-balances the plan if one person is being short-changed — but only if the group as a whole doesn't pay too much for it.
- Compares against a taste-blind plan — the most popular venue in each category — scored the same way. In our test runs the fair plan scored 83 vs. 57 (Lisbon), 87 vs. 43 (Puerto Vallarta) and 91 vs. 55 (Seoul) on the least-misery group score.
The result is a short itinerary with a fairness meter per person, a route sketch, and a card for every stop explaining who it's for, how it ranks for each person, and what the generic pick would have been.
Live demo: https://common-table-topaz.vercel.app
How we built it
- Next.js (App Router) + TypeScript, deployed on Vercel. The plan endpoint streams agent events as NDJSON so the UI can show each step as it happens.
- Qloo API (hackathon endpoint), server-side only:
/searchto resolve favourites across entity types;/v2/insightswithfilter.type=urn:tagfor per-person and group taste profiles (taste analysis);/v2/insightswithfilter.type=urn:entity:destinationto choose a city;/v2/insightswithfilter.type=urn:entity:place,filter.location.query,filter.tags(place categories found via/v2/tags) andfilter.price_level.maxfor candidates;/v2/insightswithfilter.results.entitiesto score the same candidate pool against each person's own signal — the core of the fairness engine.
- Fairness engine (pure, unit-tested): per-person percentile normalisation, least-misery blend, ledger-weighted greedy assembly, haversine travel penalty, evenness audit.
- Narration: deterministic by default. If a Gemini key is configured, Gemini writes the summary but is rejected unless it names exactly the venues the agent chose — the LLM can phrase the plan, never change it.
- Public-demo safety: per-IP rate limit, a small concurrency gate with back-off for Qloo 429s, in-process caching only (no Qloo data in the repository), and no keys in the client bundle.
Challenges we ran into
- Affinities aren't comparable across people. One person's signal scores every venue around 0.85, another's around 0.70. Averaging raw scores silently favours one person, so we normalise each person within the same candidate pool before combining.
- Taste fit is not the same as coverage. Qloo's best-matching destination for one test group was a small beach town with no venue data at all. The agent now probes candidate destinations for venues before choosing one.
- Thin categories. "Jazz bar" returned one result in Lisbon; "museum" returned one in Puerto Vallarta. The agent keeps ranked fallbacks per stop and re-plans instead of failing or padding the plan.
- Rate limits. Planning a day for three people takes ~40 Qloo calls; firing them all at once triggered 429s. A concurrency gate plus retry with back-off fixed it without making the agent sequential.
- Price data is sparse outside food and drink, so the budget filter only constrains restaurants, cafés and bars.
Accomplishments that we're proud of
- The fairness is visible, not claimed: every stop shows each person's percentile, and the plan shows its evenness score and the taste-blind comparison.
- The agent's decisions are inspectable — every step, re-plan and tool call is streamed to the screen, and the Qloo call count is shown at the end.
- It works for people whose tastes don't overlap at all, which is exactly when groups need help most.
- The whole demo runs with no paid model: the intelligence comes from Qloo.
What we learned
Cross-domain taste is the interesting part of Qloo. Knowing someone likes Radiohead is mildly useful for music recommendations; knowing it shifts which Lisbon fado house they'll enjoy is something no generic model can do. We also learned that fairness needs its own maths — "the average person is happy" and "everyone is happy" are different goals.
What's next for Common Table
- Shareable plans where each person can veto or swap a stop and the agent re-balances live.
- Multi-day trips that carry the fairness ledger across days.
- Accessibility and dietary constraints as hard filters alongside taste.
- A chat-style interface on top of the same tool loop for follow-ups like "somewhere quieter for the second stop".
Built solo with an AI coding agent (Claude Code) as a pair programmer.
Built With
- next.js
- node.js
- qloo
- react
- typescript
- vercel
Log in or sign up for Devpost to join the conversation.